
org.webpieces.httpproxy.impl.chain.Layer4Processor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of embeddablehttpproxy Show documentation
Show all versions of embeddablehttpproxy Show documentation
Someone forgot to fill this in. See http://stackoverflow.com/questions/38272550/how-to-fail-the-gradle-build-if-subproject-is-missing-a-property
The newest version!
package org.webpieces.httpproxy.impl.chain;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.webpieces.frontend.api.FrontendSocket;
import org.webpieces.frontend.api.HttpRequestListener;
import org.webpieces.frontend.api.exception.HttpException;
import org.webpieces.httpclient.api.CloseListener;
import org.webpieces.httpclient.api.HttpClient;
import org.webpieces.httpclient.api.HttpSocket;
import org.webpieces.httpparser.api.dto.HttpRequest;
import org.webpieces.httpparser.api.dto.HttpUri;
import org.webpieces.httpparser.api.dto.UrlInfo;
import org.webpieces.httpproxy.api.ProxyConfig;
import org.webpieces.httpproxy.impl.responsechain.Layer1Response;
import org.webpieces.httpproxy.impl.responsechain.Layer2ResponseListener;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
public class Layer4Processor implements HttpRequestListener {
private static final Logger log = LoggerFactory.getLogger(Layer4Processor.class);
@Inject
private ProxyConfig config;
@Inject
private HttpClient httpClient;
@Inject
private Layer2ResponseListener layer2Processor;
@Inject
private LayerZSendBadResponse badResponse;
private final Cache cache;
public Layer4Processor() {
cache = CacheBuilder.newBuilder()
.concurrencyLevel(4)
.maximumSize(10000)
.expireAfterAccess(3, TimeUnit.MINUTES)
.removalListener(new SocketExpiredListener())
.build();
}
public void processHttpRequests(FrontendSocket channel, HttpRequest req, boolean isHttps) {
log.info("incoming request. channel="+channel+"=\n"+req);
InetSocketAddress addr = req.getServerToConnectTo(null);
if(config.isForceAllConnectionToHttps()) {
addr = new InetSocketAddress(addr.getHostName(), 443);
}
HttpUri uri = req.getRequestLine().getUri();
UrlInfo info = uri.getUriBreakdown();
if(info.getPrefix() != null) {
//for sites like http://www.colorado.edu that won't accept full uri path
//without this, www.colorado.edu was returning 404 ...seems like a bug on their end to be honest
uri.setUri(info.getFullPath());
}
//need synchronization if two clients of proxy access same httpSocket/addr!!!
HttpSocket socket = cache.getIfPresent(addr);
if(socket != null) {
sendData(channel, socket, req);
} else {
openAndConnectSocket(addr, req, channel);
}
}
private void sendData(FrontendSocket channel, HttpSocket socket, HttpRequest req) {
socket.send(req, new Layer1Response(layer2Processor, channel, req));
}
private HttpSocket openAndConnectSocket(InetSocketAddress addr, HttpRequest req, FrontendSocket channel) {
HttpSocket socket = httpClient.openHttpSocket(""+addr.getHostName()+"-"+addr.getPort(), new Layer1CloseListener(addr));
log.info("connecting to addr="+addr);
socket.connect(addr)
.thenAccept(s -> {
sendData(channel, socket, req);
cache.put(addr, socket);
})
.exceptionally(e -> layer2Processor.processError(channel, req, e));
return socket;
}
@Override
public void clientOpenChannel(FrontendSocket channel) {
log.info("browser client open channel="+channel);
}
@Override
public void clientClosedChannel(FrontendSocket channel) {
log.info("browser client closed channel="+channel);
}
private class SocketExpiredListener implements RemovalListener {
@Override
public void onRemoval(RemovalNotification notification) {
log.info("closing socket="+notification.getKey()+". cache removal cause="+notification.getCause());
HttpSocket socket = notification.getValue();
socket.closeSocket();
}
}
private class Layer1CloseListener implements CloseListener {
private SocketAddress addr;
public Layer1CloseListener(SocketAddress addr) {
this.addr = addr;
}
@Override
public void farEndClosed(HttpSocket socket) {
log.info("socket addr="+addr+" closed, invalidating cache");
cache.invalidate(addr);
}
}
@Override
public void sendServerResponse(FrontendSocket channel, HttpException exc) {
badResponse.sendServerResponse(channel, exc);
}
@Override
public void applyWriteBackPressure(FrontendSocket channel) {
log.error("NEED APPLY BACKPRESSURE", new RuntimeException());
}
@Override
public void releaseBackPressure(FrontendSocket channel) {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy