-
-
Save missedone/76517e618486db746056 to your computer and use it in GitHub Desktop.
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(); | |
} | |
} |
Hi @missedone,
I used your httphijack class but i cannot send many command.
If i call send("ls") once time, it ok but when i call twice It causes error.
How can i use 1 socket stream and can write/read output many time. Please help me. Thanks
String cmd = "bash";
JSONObject input = new JSONObject();
input.put("AttachStdin", true);
input.put("AttachStdout", true);
input.put("Attachstderr", true);
input.put("DetachKeys", "ctrl-p,ctrl-q");
input.put("Tty", false);
JSONArray cmds = new JSONArray();
String[] commands = cmd.split(" ");
for (String c : commands) {
cmds.add(c);
}
input.put("Cmd", cmds);
String content = CommonUtil.sendApiRequest(Configuration.SWARM_ADDRESS + "/containers/" + id + "/exec", "POST", input.toJSONString(), "", false);
JSONObject jcontent = CommonUtil.parseJSONObject(content);
String token = (String) jcontent.get("Id");
HttpHijack httpHijack = new HttpHijack(new URI(Configuration.SWARM_ADDRESS + "/exec/" + token + "/start"));
JSONObject jsonObject = new JSONObject();
jsonObject.put("Tty", false);
jsonObject.put("Detach", false);
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
httpHijack.post(headers, jsonObject.toString());
CommonUtil.sendApiRequest(Configuration.SWARM_ADDRESS + "/exec/" + token + "/resize?h=40&w=80", "POST", "", "text/plain", false);
InputStream send = httpHijack.send("ls\n");
send = httpHijack.send("ls\n");
Error log:
ERROR - Broken pipe
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:141)
at zcore.utilities.HttpHijack.send(HttpHijack.java:128)
at caas.web.handler.ApiController.consoleContainer(ApiController.java:1154)
at caas.web.handler.ApiController.doGet(ApiController.java:105)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:513)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:52)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:745)
Thanks
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 {
public static void connectToDocker(){
DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
.withReadTimeout(1000)
.withConnectTimeout(1000)
.withMaxTotalConnections(100)
.withMaxPerRouteConnections(10);
ExposedPort tcp22 = ExposedPort.tcp(22);
ExposedPort tcp23 = ExposedPort.tcp(23);
Ports portBindings = new Ports();
portBindings.bind(tcp22, Ports.Binding.bindPort(11022));
portBindings.bind(tcp23, Ports.Binding.bindPort(11023));
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
//.withDockerHost("tcp://localhost:11023")
.build();
DockerClient docker = DockerClientBuilder.getInstance(config).build();
Volume volume1 = new Volume("/mydockerbuild");
CreateContainerResponse containerResp = docker.createContainerCmd("busybox")
.withImage(MyValuesConstans.JAVA_DOCKER)
.withCmd("sh", "-c", "while :; do sleep 1; done")
.withAttachStderr(true)
.withAttachStdout(true)
.withAttachStdin(true)
.withExposedPorts(tcp22,tcp23)
.withVolumes(volume1)
.withBinds(new Bind("/home/itcostcut/mydockerbuild",volume1))
.exec();
String containerId = containerResp.getId();
docker.startContainerCmd(containerId).exec();
System.out.println("HOST........... ");
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
final String[] command = {"bash", "-c", "cd mydockerbuild/ && javac Program.java && java -cp . Program exit"};
ExecCreateCmdResponse execCreateCmdResponse = docker.execCreateCmd(containerId)
.withAttachStdout(true)
.withAttachStderr(true)
.withAttachStdin(true)
.withCmd("ls")
.exec();
InspectExecResponse inpect = docker.inspectExecCmd(execCreateCmdResponse.getId()).exec();
System.out.println("Inspect Info........... "+inpect);
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
HttpHijack ws;
try {
ws = new HttpHijack(new URI("http://172.17.0.2:2375/v1.19/exec/" + execCreateCmdResponse.getId() + "/start"));
String payload = "{\"Detach\": false,\"Tty\": false}";
ws.post(headers, payload);
String request = "rock";
Thread.sleep(3000);
InputStream input = ws.send(request);
System.out.println("Request output......... "+input.toString());
} catch (URISyntaxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
docker.execStartCmd(execCreateCmdResponse.getId()).exec(
new ExecStartResultCallback(stdout, stderr)).awaitCompletion();
System.out.println("Output: "+stdout.toString());
System.out.println("Error: "+stderr.toString());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args){
connectToDocker();
}
}
Hi, I have used your code to implement a super pre-alpha implementation of direct file uploading via REST API into running container, if you have any comment write to [email protected]
https://github.com/highel/docker-rest-file-upload/blob/master/DockerRestFileUpload.java