com.firefly.example.http.proxy.ProxyDemo Maven / Gradle / Ivy
package com.firefly.example.http.proxy;
import com.firefly.$;
import com.firefly.client.http2.SimpleHTTPClient;
import com.firefly.codec.http2.model.HttpStatus;
import com.firefly.codec.http2.stream.HTTPOutputStream;
import com.firefly.net.tcp.SimpleTcpClient;
import com.firefly.net.tcp.TcpConnection;
import com.firefly.server.http2.SimpleHTTPServer;
import com.firefly.server.http2.SimpleResponse;
import com.firefly.utils.concurrent.Callback;
import com.firefly.utils.concurrent.Promise;
import com.firefly.utils.io.BufferUtils;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author Pengtao Qiu
*/
public class ProxyDemo {
public static void main(String[] args) {
SimpleHTTPClient client = $.createHTTPClient();
SimpleHTTPServer server = $.createHTTPServer();
SimpleTcpClient tcpClient = $.createTCPClient();
server.acceptHTTPTunnelConnection((request, serverConnection) -> {
SimpleResponse response = request.getAsyncResponse();
request.getAttributes().computeIfAbsent("tunnelSuccess", k -> {
CompletableFuture p = tcpClient.connect(request.getURI().getHost(), request.getURI().getPort());
p.thenAccept(tcpConn -> {
serverConnection.upgradeHTTPTunnel().thenAccept(tunnel -> {
tcpConn.receive(dstBuf -> tunnel.write(dstBuf, Callback.NOOP))
.onException(e -> $.io.close(tcpConn))
.onClose(() -> request.remove("tunnelSuccess"));
tunnel.receive(tcpConn::write);
});
$.io.close(response);
}).exceptionally(e -> {
response.setStatus(HttpStatus.BAD_GATEWAY_502);
$.io.close(response);
return null;
});
return p;
});
}).headerComplete(srcRequest -> {
long start = System.currentTimeMillis();
System.out.println(srcRequest.toString());
System.out.println(srcRequest.getFields());
try {
// copy origin request line and headers to destination request
Promise.Completable outputCompletable = new Promise.Completable<>();
SimpleHTTPClient.RequestBuilder dstReq = client.request(srcRequest.getMethod(), srcRequest.getURI().toURI().toURL())
.addAll(srcRequest.getFields())
.output(outputCompletable);
long contentLength = srcRequest.getContentLength();
if (contentLength > 0) {
// transmit origin request body to destination server
AtomicLong count = new AtomicLong();
srcRequest.content(srcBuffer -> outputCompletable.thenAccept(dstOutput -> {
try {
if (count.addAndGet(srcBuffer.remaining()) < contentLength) {
dstOutput.write(srcBuffer);
} else {
dstOutput.write(srcBuffer);
dstOutput.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}));
} else {
outputCompletable.thenAccept($.io::close);
}
srcRequest.messageComplete(req -> {
SimpleResponse srcResponse = req.getAsyncResponse();
dstReq.headerComplete(dstResponse -> {
// copy destination server response line and headers to origin response
System.out.println(dstResponse.toString());
System.out.println(dstResponse.getFields());
srcResponse.setStatus(dstResponse.getStatus());
srcResponse.setReason(dstResponse.getReason());
srcResponse.setHttpVersion(dstResponse.getHttpVersion());
srcResponse.getFields().addAll(dstResponse.getFields());
}).content(dstBuffer -> {
// transmit destination server response body
System.out.println("receive dst data -> " + dstBuffer.remaining());
try {
srcResponse.getOutputStream().write(BufferUtils.toArray(dstBuffer));
} catch (IOException e) {
e.printStackTrace();
}
}).messageComplete(dstResponse -> {
$.io.close(srcResponse);
System.out.println("time: " + (System.currentTimeMillis() - start));
}).end();
});
System.out.println("block time: " + (System.currentTimeMillis() - start) + "|" + srcRequest.getRequest().getURIString());
} catch (Exception e) {
e.printStackTrace();
}
}).listen("localhost", 6666);
}
}