Created
June 22, 2015 15:15
-
-
Save missedone/76517e618486db746056 to your computer and use it in GitHub Desktop.
Http hijacking for docker startExec API call. (this is not a general purpose hijacking for any http request, not going to replace any http client)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import javax.net.SocketFactory; | |
import javax.net.ssl.SSLSocketFactory; | |
import java.io.*; | |
import java.net.Socket; | |
import java.net.URI; | |
import java.util.Map; | |
import java.util.Map.Entry; | |
public class HttpHijack { | |
private static final Logger log = LoggerFactory.getLogger(HttpHijack.class); | |
private URI uri; | |
private Socket socket; | |
private boolean handshakeCompleted; | |
private InputStream chin; | |
private OutputStream chout; | |
public HttpHijack(URI url) { | |
uri = url; | |
} | |
public void post(Map<String, String> headers, String payload) throws java.io.IOException { | |
String host = uri.getHost(); | |
String path = uri.getPath(); | |
if (path.equals("")) { | |
path = "/"; | |
} | |
String query = uri.getQuery(); | |
if (query != null) { | |
path = path + "?" + query; | |
} | |
socket = createSocket(); | |
chout = socket.getOutputStream(); | |
StringBuffer extraHeaders = new StringBuffer(); | |
if (headers != null) { | |
for (Entry<String, String> entry : headers.entrySet()) { | |
extraHeaders.append(entry.getKey() + ": " + entry.getValue() + "\r\n"); | |
} | |
} | |
StringBuffer request = new StringBuffer(); | |
request.append("POST " + path + " HTTP/1.1\r\n"); | |
request.append("Upgrade: tcp\r\n"); | |
request.append("Connection: Upgrade\r\n"); | |
request.append("Host: " + host + "\r\n"); | |
if (headers != null) { | |
for (Entry<String, String> entry : headers.entrySet()) { | |
request.append(entry.getKey() + ": " + entry.getValue() + "\r\n"); | |
} | |
} | |
request.append("Content-Length: " + payload.length() + "\r\n"); | |
request.append("\r\n"); | |
request.append(payload); | |
chout.write(request.toString().getBytes()); | |
chout.flush(); | |
chin = socket.getInputStream(); | |
BufferedReader reader = new BufferedReader(new InputStreamReader(chin)); | |
String header = reader.readLine(); | |
if (!header.equals("HTTP/1.1 101 UPGRADED")) { | |
throw new IOException("Invalid handshake response: " + header); | |
} | |
do { | |
header = reader.readLine(); | |
log.info("header: {}", header); | |
} while (!header.equals("")); | |
handshakeCompleted = true; | |
} | |
private Socket createSocket() throws java.io.IOException { | |
String scheme = uri.getScheme(); | |
String host = uri.getHost(); | |
int port = uri.getPort(); | |
if (port == -1) { | |
if (scheme.equals("https")) { | |
port = 443; | |
} else if (scheme.equals("http")) { | |
port = 80; | |
} else { | |
throw new IllegalArgumentException("Unsupported scheme"); | |
} | |
} | |
if (scheme.equals("https")) { | |
SocketFactory factory = SSLSocketFactory.getDefault(); | |
return factory.createSocket(host, port); | |
} else { | |
return new Socket(host, port); | |
} | |
} | |
public InputStream send(String command) throws java.io.IOException { | |
if (!handshakeCompleted) { | |
throw new IllegalStateException("Handshake not complete"); | |
} | |
chout.write(command.getBytes("UTF-8")); | |
chout.flush(); | |
// looks like "exit" can't explicitly close the session, | |
// shutdown output stream to force close it | |
// so that stdout/stderr can be consumed via inputstream | |
socket.shutdownOutput(); | |
return socket.getInputStream(); | |
} | |
public void close() throws java.io.IOException { | |
chin.close(); | |
chout.close(); | |
socket.close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
HIi @missedone I am trying tho run a java program using docker-java api ,in my scenario it the java code requires input at runtime , below is my code. Please help how i can i use your program to attach Stdin at runtime.
package com.examenginedashboard.docker.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import com.examenginedashboard.CONSTANTS.MyValuesConstans;
import com.examenginedashboard.codePG.service.HttpHijack;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.api.command.InspectExecResponse;
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.api.model.Volume;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.command.ExecStartResultCallback;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
public class APIBasedCodeCompiler {
}