All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.firefly.example.http.proxy.ProxyDemo Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy