public class ClientToProxyConnection extends ProxyConnection<HttpRequest>
Represents a connection from a client to our proxy. Each
ClientToProxyConnection can have multiple ProxyToServerConnections,
at most one per outbound host:port.
Once a ProxyToServerConnection has been created for a given server, it is
continually reused. The ProxyToServerConnection goes through its own
lifecycle of connects and disconnects, with different underlying
Channels, but only a single ProxyToServerConnection object is used
per server. The one exception to this is CONNECT tunneling - if a connection
has been used for CONNECT tunneling, that connection will never be reused.
As the ProxyToServerConnections receive responses from their servers, they
feed these back to the client by calling
respond(ProxyToServerConnection, HttpFilters, HttpRequest, HttpResponse, HttpObject)
.
ProxyConnection.BytesReadMonitor, ProxyConnection.BytesWrittenMonitor, ProxyConnection.RequestReadMonitor, ProxyConnection.RequestWrittenMonitor, ProxyConnection.ResponseReadMonitor, ProxyConnection.ResponseWrittenMonitorChannelHandler.Sharable| Modifier and Type | Field and Description |
|---|---|
private AtomicBoolean |
authenticated |
private ProxyConnection.BytesReadMonitor |
bytesReadMonitor
Activity Tracking/Statistics
We track statistics on bytes, requests and responses by adding handlers
at the appropriate parts of the pipeline (see initChannelPipeline()).
|
private ProxyConnection.BytesWrittenMonitor |
bytesWrittenMonitor |
private SSLSession |
clientSslSession |
private static HttpResponseStatus |
CONNECTION_ESTABLISHED |
private HttpFilters |
currentFilters
The current filters to apply to incoming requests/chunks.
|
private HttpRequest |
currentRequest
The current HTTP request that this connection is currently servicing.
|
private ProxyToServerConnection |
currentServerConnection
This is the current server connection that we're using while transferring
chunked data.
|
private GlobalTrafficShapingHandler |
globalTrafficShapingHandler |
private static Pattern |
HTTP_SCHEME
Used for case-insensitive comparisons when checking direct proxy request.
|
private static String |
LOWERCASE_TRANSFER_ENCODING_HEADER
Used for case-insensitive comparisons when parsing Connection header values.
|
private boolean |
mitming
Tracks whether or not this ClientToProxyConnection is current doing MITM.
|
private AtomicInteger |
numberOfCurrentlyConnectedServers
Keep track of how many servers are currently connected.
|
private AtomicInteger |
numberOfCurrentlyConnectingServers
Keep track of how many servers are currently in the process of
connecting.
|
private AtomicInteger |
numberOfReusedServerConnections
Keep track of how many times we were able to reuse a connection.
|
private ProxyConnection.RequestReadMonitor |
requestReadMonitor |
(package private) ConnectionFlowStep |
RespondCONNECTSuccessful
Tells the Client that its HTTP CONNECT request was successful.
|
private ProxyConnection.ResponseWrittenMonitor |
responseWrittenMonitor |
private Map<String,ProxyToServerConnection> |
serverConnectionsByHostAndPort
Keep track of all ProxyToServerConnections by host+port.
|
channel, ctx, lastReadTime, LOG, proxyServer, runsAsSslClient, sslEngine, StartTunneling| Constructor and Description |
|---|
ClientToProxyConnection(DefaultHttpProxyServer proxyServer,
SslEngineSource sslEngineSource,
boolean authenticateClients,
ChannelPipeline pipeline,
GlobalTrafficShapingHandler globalTrafficShapingHandler) |
| Modifier and Type | Method and Description |
|---|---|
private boolean |
authenticationRequired(HttpRequest request)
Checks whether the given HttpRequest requires authentication.
|
protected void |
becameSaturated()
When the ClientToProxyConnection becomes saturated, stop reading on all
associated ProxyToServerConnections.
|
protected void |
becameWritable()
When the ClientToProxyConnection becomes writable, resume reading on all
associated ProxyToServerConnections.
|
private void |
closeConnectionsAfterWriteIfNecessary(ProxyToServerConnection serverConnection,
HttpRequest currentHttpRequest,
HttpResponse currentHttpResponse,
HttpObject httpObject)
This method takes care of closing client to proxy and/or proxy to server
connections after finishing a write.
|
protected void |
connected()
On connect of the client, start waiting for an initial
HttpRequest. |
private void |
connectionFailedUnrecoverably(HttpRequest initialRequest,
ProxyToServerConnection serverConnection) |
private HttpRequest |
copy(HttpRequest original)
Copy the given
HttpRequest verbatim. |
protected void |
disconnected()
On disconnect of the client, disconnect all server connections.
|
private ConnectionState |
doReadHTTPInitial(HttpRequest httpRequest)
Reads an
HttpRequest. |
protected void |
exceptionCaught(Throwable cause)
Override this to handle exceptions that occurred during asynchronous
processing on the
Channel. |
private void |
fixHttpVersionHeaderIfNecessary(HttpResponse httpResponse)
Chunked encoding is an HTTP 1.1 feature, but sometimes we get a chunked
response that reports its HTTP version as 1.0.
|
private FlowContext |
flowContext() |
private void |
forceDisconnect(ProxyToServerConnection serverConnection) |
InetSocketAddress |
getClientAddress() |
private String |
identifyHostAndPort(HttpRequest httpRequest)
Identify the host and port for a request.
|
private void |
initChannelPipeline(ChannelPipeline pipeline)
Initialize the
ChannelPipeline for the client to proxy channel. |
boolean |
isMitming() |
private boolean |
isRequestToOriginServer(HttpRequest httpRequest)
Returns true if the specified request is a request to an origin server, rather than to a proxy server.
|
private void |
modifyRequestHeadersToReflectProxying(HttpRequest httpRequest)
If and only if our proxy is not running in transparent mode, modify the
request headers to reflect that it was proxied.
|
private void |
modifyResponseHeadersToReflectProxying(HttpResponse httpResponse)
If and only if our proxy is not running in transparent mode, modify the
response headers to reflect that it was proxied.
|
protected void |
readHTTPChunk(HttpContent chunk)
Implement this to handle reading a chunk in a chunked transfer.
|
protected ConnectionState |
readHTTPInitial(HttpRequest httpRequest)
Reading
|
protected void |
readRaw(ByteBuf buf)
Implement this to handle reading a raw buffer as they are used in HTTP
tunneling.
|
private void |
recordClientConnected() |
private void |
recordClientDisconnected() |
private void |
recordClientSSLHandshakeSucceeded() |
(package private) void |
respond(ProxyToServerConnection serverConnection,
HttpFilters filters,
HttpRequest currentHttpRequest,
HttpResponse currentHttpResponse,
HttpObject httpObject)
Send a response to the client.
|
private boolean |
respondWithShortCircuitResponse(HttpResponse httpResponse)
Responds to the client with the specified "short-circuit" response.
|
private void |
resumeReadingIfNecessary() |
protected void |
serverBecameSaturated(ProxyToServerConnection serverConnection)
When a server becomes saturated, we stop reading from the client.
|
protected void |
serverBecameWriteable(ProxyToServerConnection serverConnection)
When a server becomes writeable, we check to see if all servers are
writeable and if they are, we resume reading.
|
protected boolean |
serverConnectionFailed(ProxyToServerConnection serverConnection,
ConnectionState lastStateBeforeFailure,
Throwable cause)
If the
ProxyToServerConnection fails to complete its connection
lifecycle successfully, this method is called to let us know about it. |
protected void |
serverConnectionFlowStarted(ProxyToServerConnection serverConnection)
Called when
ProxyToServerConnection starts its connection flow. |
protected void |
serverConnectionSucceeded(ProxyToServerConnection serverConnection,
boolean shouldForwardInitialRequest)
If the
ProxyToServerConnection completes its connection lifecycle
successfully, this method is called to let us know about it. |
protected void |
serverDisconnected(ProxyToServerConnection serverConnection)
On disconnect of the server, track that we have one fewer connected
servers and then disconnect the client if necessary.
|
protected void |
setMitming(boolean isMitming) |
private boolean |
shouldCloseClientConnection(HttpRequest req,
HttpResponse res,
HttpObject httpObject)
Determine whether or not the client connection should be closed.
|
private boolean |
shouldCloseServerConnection(HttpRequest req,
HttpResponse res,
HttpObject msg)
Determines if the remote connection should be closed based on the request
and response pair.
|
private void |
stripConnectionTokens(HttpHeaders headers)
RFC2616 Section 14.10
HTTP/1.1 proxies MUST parse the Connection header field before a message
is forwarded and, for each connection-token in this field, remove any
header field(s) from the message with the same name as the
connection-token.
|
private void |
stripHopByHopHeaders(HttpHeaders headers)
Removes all headers that should not be forwarded.
|
private void |
switchProxyConnectionHeader(HttpHeaders headers)
Switch the de-facto standard "Proxy-Connection" header to "Connection"
when we pass it along to the remote host.
|
protected void |
timedOut()
This method is called when the underlying
Channel times out due
to an idle timeout. |
(package private) void |
timedOut(ProxyToServerConnection serverConnection) |
private void |
writeAuthenticationRequired(String realm) |
private boolean |
writeBadGateway(HttpRequest httpRequest)
Tells the client that something went wrong trying to proxy its request.
|
private boolean |
writeBadRequest(HttpRequest httpRequest)
Tells the client that the request was malformed or erroneous.
|
private void |
writeEmptyBuffer()
Write an empty buffer at the end of a chunked transfer.
|
private boolean |
writeGatewayTimeout(HttpRequest httpRequest)
Tells the client that the connection to the server, or possibly to some intermediary service (such as DNS), timed out.
|
aggregateContentForFiltering, become, channelActive, channelInactive, channelRead0, channelRegistered, channelWritabilityChanged, disconnect, doWrite, encrypt, encrypt, EncryptChannel, exceptionCaught, getCurrentState, getHttpFiltersFromProxyServer, getLOG, getSslEngine, is, isConnecting, isSaturated, isTunneling, read, resumeReading, stopReading, userEventTriggered, write, writeHttp, writeRaw, writeToChannelacceptInboundMessage, channelReadchannelReadComplete, channelUnregisteredensureNotSharable, handlerAdded, handlerRemoved, isSharableclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waithandlerAdded, handlerRemovedprivate static final HttpResponseStatus CONNECTION_ESTABLISHED
private static final String LOWERCASE_TRANSFER_ENCODING_HEADER
private static final Pattern HTTP_SCHEME
private final Map<String,ProxyToServerConnection> serverConnectionsByHostAndPort
private final AtomicInteger numberOfCurrentlyConnectingServers
private final AtomicInteger numberOfCurrentlyConnectedServers
private final AtomicInteger numberOfReusedServerConnections
private volatile ProxyToServerConnection currentServerConnection
private volatile HttpFilters currentFilters
private volatile SSLSession clientSslSession
private volatile boolean mitming
private AtomicBoolean authenticated
private final GlobalTrafficShapingHandler globalTrafficShapingHandler
private volatile HttpRequest currentRequest
ConnectionFlowStep RespondCONNECTSuccessful
private final ProxyConnection.BytesReadMonitor bytesReadMonitor
private ProxyConnection.RequestReadMonitor requestReadMonitor
private ProxyConnection.BytesWrittenMonitor bytesWrittenMonitor
private ProxyConnection.ResponseWrittenMonitor responseWrittenMonitor
ClientToProxyConnection(DefaultHttpProxyServer proxyServer, SslEngineSource sslEngineSource, boolean authenticateClients, ChannelPipeline pipeline, GlobalTrafficShapingHandler globalTrafficShapingHandler)
protected ConnectionState readHTTPInitial(HttpRequest httpRequest)
readHTTPInitial in class ProxyConnection<HttpRequest>private ConnectionState doReadHTTPInitial(HttpRequest httpRequest)
Reads an HttpRequest.
If we don't yet have a ProxyToServerConnection for the desired
server, this takes care of creating it.
Note - the "server" could be a chained proxy, not the final endpoint for the request.
httpRequest - private boolean isRequestToOriginServer(HttpRequest httpRequest)
When making a request to a proxy, other than a CONNECT or server-wide
OPTIONS request (as detailed below), a client MUST send the target
URI in absolute-form as the request-target.
[...]
An example absolute-form of request-line would be:
GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1
To allow for transition to the absolute-form for all requests in some
future version of HTTP, a server MUST accept the absolute-form in
requests, even though HTTP/1.1 clients will only send them in
requests to proxies.
httpRequest - the request to evaluateprotected void readHTTPChunk(HttpContent chunk)
ProxyConnectionreadHTTPChunk in class ProxyConnection<HttpRequest>protected void readRaw(ByteBuf buf)
ProxyConnectionreadRaw in class ProxyConnection<HttpRequest>void respond(ProxyToServerConnection serverConnection, HttpFilters filters, HttpRequest currentHttpRequest, HttpResponse currentHttpResponse, HttpObject httpObject)
serverConnection - the ProxyToServerConnection that's respondingfilters - the filters to apply to the responsecurrentHttpRequest - the HttpRequest that prompted this responsecurrentHttpResponse - the HttpResponse corresponding to this data (when doing
chunked transfers, this is the initial HttpResponse object
that came in before the other chunks)httpObject - the data with which to respondprotected void connected()
HttpRequest.connected in class ProxyConnection<HttpRequest>void timedOut(ProxyToServerConnection serverConnection)
protected void timedOut()
ProxyConnectionChannel times out due
to an idle timeout.timedOut in class ProxyConnection<HttpRequest>protected void disconnected()
disconnected in class ProxyConnection<HttpRequest>protected void serverConnectionFlowStarted(ProxyToServerConnection serverConnection)
ProxyToServerConnection starts its connection flow.serverConnection - protected void serverConnectionSucceeded(ProxyToServerConnection serverConnection, boolean shouldForwardInitialRequest)
ProxyToServerConnection completes its connection lifecycle
successfully, this method is called to let us know about it.serverConnection - shouldForwardInitialRequest - protected boolean serverConnectionFailed(ProxyToServerConnection serverConnection, ConnectionState lastStateBeforeFailure, Throwable cause)
ProxyToServerConnection fails to complete its connection
lifecycle successfully, this method is called to let us know about it.
After failing to connect to the server, one of two things can happen:
serverConnection - lastStateBeforeFailure - cause - what caused the failureprivate void connectionFailedUnrecoverably(HttpRequest initialRequest, ProxyToServerConnection serverConnection)
private void resumeReadingIfNecessary()
protected void serverDisconnected(ProxyToServerConnection serverConnection)
serverConnection - protected void becameSaturated()
becameSaturated in class ProxyConnection<HttpRequest>protected void becameWritable()
becameWritable in class ProxyConnection<HttpRequest>protected void serverBecameSaturated(ProxyToServerConnection serverConnection)
serverConnection - protected void serverBecameWriteable(ProxyToServerConnection serverConnection)
serverConnection - protected void exceptionCaught(Throwable cause)
ProxyConnectionChannel.exceptionCaught in class ProxyConnection<HttpRequest>private void initChannelPipeline(ChannelPipeline pipeline)
ChannelPipeline for the client to proxy channel.
LittleProxy acts like a server here.
A ChannelPipeline invokes the read (Inbound) handlers in
ascending ordering of the list and then the write (Outbound) handlers in
descending ordering.
Regarding the Javadoc of HttpObjectAggregator it's needed to have
the HttpResponseEncoder or HttpRequestEncoder before the
HttpObjectAggregator in the ChannelPipeline.pipeline - private void closeConnectionsAfterWriteIfNecessary(ProxyToServerConnection serverConnection, HttpRequest currentHttpRequest, HttpResponse currentHttpResponse, HttpObject httpObject)
private void forceDisconnect(ProxyToServerConnection serverConnection)
private boolean shouldCloseClientConnection(HttpRequest req, HttpResponse res, HttpObject httpObject)
req - res - httpObject - private boolean shouldCloseServerConnection(HttpRequest req, HttpResponse res, HttpObject msg)
req - The request.res - The response.msg - The message.private boolean authenticationRequired(HttpRequest request)
Checks whether the given HttpRequest requires authentication.
If the request contains credentials, these are checked.
If authentication is still required, either because no credentials were provided or the credentials were wrong, this writes a 407 response to the client.
request - private void writeAuthenticationRequired(String realm)
private HttpRequest copy(HttpRequest original)
HttpRequest verbatim.original - private void fixHttpVersionHeaderIfNecessary(HttpResponse httpResponse)
httpResponse - private void modifyRequestHeadersToReflectProxying(HttpRequest httpRequest)
httpRequest - private void modifyResponseHeadersToReflectProxying(HttpResponse httpResponse)
httpResponse - private void switchProxyConnectionHeader(HttpHeaders headers)
headers - The headers to modifyprivate void stripConnectionTokens(HttpHeaders headers)
headers - The headers to modifyprivate void stripHopByHopHeaders(HttpHeaders headers)
headers - The headers to modifyprivate boolean writeBadGateway(HttpRequest httpRequest)
httpRequest - the HttpRequest that is resulting in the Bad Gateway responseprivate boolean writeBadRequest(HttpRequest httpRequest)
private boolean writeGatewayTimeout(HttpRequest httpRequest)
httpRequest - the HttpRequest that is resulting in the Gateway Timeout responseprivate boolean respondWithShortCircuitResponse(HttpResponse httpResponse)
HttpFilters.proxyToClientResponse(HttpObject) filter method before writing it to the client. The client
will not be disconnected, unless the response includes a "Connection: close" header, or the filter returns
a null HttpResponse (in which case no response will be written to the client and the connection will be
disconnected immediately). If the response is not a Bad Gateway or Gateway Timeout response, the response's headers
will be modified to reflect proxying, including adding a Via header, Date header, etc.httpResponse - the response to return to the clientprivate String identifyHostAndPort(HttpRequest httpRequest)
httpRequest - private void writeEmptyBuffer()
public boolean isMitming()
protected void setMitming(boolean isMitming)
private void recordClientConnected()
private void recordClientSSLHandshakeSucceeded()
private void recordClientDisconnected()
public InetSocketAddress getClientAddress()
private FlowContext flowContext()
Copyright © 2009–2017 LittleShoot. All rights reserved.