> Docs > Http Intermediary

Http Intermediary

An HTTP intermediary forwards requests and responses between clients and servers.

    client ⇄ { intermediary } ⇄ server 

We can implement an intermediary by using HttpServer and HttpClient

    client ⇄ { HttpServer ⇄ HttpClient } ⇄ server 

The simplest implementation of a proxy would be:

new HttpServer( new HttpClient()::send ).start();

However, some default features of HttpServer and HttpClient are not appropriate for intermediaries; they should be disabled by HttpServerConf.setProxyDefaults() and HttpClient.send0().

The following sections show two examples of intermediaries: Proxy, Load Balancer.

Create a Proxy

To create a simple HTTP proxy at port 9090:

        HttpClient downstream = new HttpClient();
        HttpHandler proxyHandler = request->
        {
            return downstream.send0(request, null);    // use send0() instead of send()
        };

        HttpServer proxy = new HttpServer(proxyHandler);
        proxy.conf()
            .port(9090)
            .setProxyDefaults()                        // use proxy settings
            .trafficDump(System.out::print)
        ;
        proxy.start();

It doesn't do much, except the traffic is dumped which can be used for diagnostics.

See also _HttpProxy.java for a simple HTTP+HTTPS proxy demo.

We can add any custom behaviors to the proxy. For example, to block spam hosts:

        Set<String> spamHosts = new ConcurrentHashMap<String,Boolean>().keySet(true);
        HttpHandler adminHandler = request->
        {
            String add = request.uriParam("add");
            if(add!=null) spamHosts.add(add);
            return HttpResponse.text(200, "spamHosts:"+spamHosts);
        };

        HttpClient downstream = new HttpClient();
        HttpHandler proxyHandler = request->
        {
            // use <http://proxy-admin/> to manage the spam list.
            if(request.host().equals("proxy-admin"))
                return adminHandler.handle(request);

            if(spamHosts.contains(request.host()))
                return HttpResponse.text(403, "blocked");

            return downstream.send0(request, null);
        };

Create a Load Balancer

A load balancer dispatches a client request to one of several internal servers, based on request cookie, URI, IP, etc.

In the following demo, we have two internal servers at port 8081 and 8082. The load balancer runs at port 80, and dispatches requests based on URIs.

        for(int port: new int[]{8081, 8082})
        {
            HttpServer server = new HttpServer(request->
                HttpResponse.text(200, "from server "+port));
            server.conf().port(port);
            server.start();
        }

        HttpClient downstream = new HttpClient();
        HttpServer loadBalancer = new HttpServer(request->
        {
            TcpAddress dest = new TcpAddress("127.0.0.1", 8081);
            if(request.uriPath().equals("/cat"))
                dest = new TcpAddress("127.0.0.1", 8082);

            HttpRequestImpl reqMod = new HttpRequestImpl(request); // copy and modify
            reqMod.header("X-Forwarded-For", request.ip().getHostAddress());
            reqMod.header("X-Forwarded-Proto", request.scheme());

            return downstream.send0(reqMod, dest);
        });
        loadBalancer.conf()
            .port(80)
            .setProxyDefaults()
        ;
        loadBalancer.start();