this.reuseXForwarded = reuseXForwarded;
}
@Override
public void run() {
final ClientRequest request = new ClientRequest();
StringBuilder requestURI = new StringBuilder();
try {
if (exchange.getRelativePath().isEmpty()) {
requestURI.append(encodeUrlPart(clientConnection.getTargetPath()));
} else {
if (clientConnection.getTargetPath().endsWith("/")) {
requestURI.append(clientConnection.getTargetPath().substring(0, clientConnection.getTargetPath().length() - 1));
requestURI.append(encodeUrlPart(exchange.getRelativePath()));
} else {
requestURI = requestURI.append(clientConnection.getTargetPath());
requestURI.append(encodeUrlPart(exchange.getRelativePath()));
}
}
boolean first = true;
if (!exchange.getPathParameters().isEmpty()) {
requestURI.append(';');
for (Map.Entry<String, Deque<String>> entry : exchange.getPathParameters().entrySet()) {
if (first) {
first = false;
} else {
requestURI.append('&');
}
for (String val : entry.getValue()) {
requestURI.append(URLEncoder.encode(entry.getKey(), UTF_8));
requestURI.append('=');
requestURI.append(URLEncoder.encode(val, UTF_8));
}
}
}
String qs = exchange.getQueryString();
if (qs != null && !qs.isEmpty()) {
requestURI.append('?');
requestURI.append(qs);
}
} catch (UnsupportedEncodingException e) {
//impossible
exchange.setResponseCode(500);
exchange.endExchange();
return;
}
request.setPath(requestURI.toString())
.setMethod(exchange.getRequestMethod());
final HeaderMap inboundRequestHeaders = exchange.getRequestHeaders();
final HeaderMap outboundRequestHeaders = request.getRequestHeaders();
copyHeaders(outboundRequestHeaders, inboundRequestHeaders);
if (!exchange.isPersistent()) {
//just because the client side is non-persistent
//we don't want to close the connection to the backend
outboundRequestHeaders.put(Headers.CONNECTION, "keep-alive");
}
for (Map.Entry<HttpString, ExchangeAttribute> entry : requestHeaders.entrySet()) {
String headerValue = entry.getValue().readAttribute(exchange);
if (headerValue == null || headerValue.isEmpty()) {
outboundRequestHeaders.remove(entry.getKey());
} else {
outboundRequestHeaders.put(entry.getKey(), headerValue.replace('\n', ' '));
}
}
final SocketAddress address = exchange.getConnection().getPeerAddress();
final String remoteHost = (address != null && address instanceof InetSocketAddress) ? ((InetSocketAddress) address).getHostString() : "localhost";
request.putAttachment(ProxiedRequestAttachments.REMOTE_HOST, remoteHost);
if (reuseXForwarded && request.getRequestHeaders().contains(Headers.X_FORWARDED_FOR)) {
// We have an existing header so we shall simply append the host to the existing list
final String current = request.getRequestHeaders().getFirst(Headers.X_FORWARDED_FOR);
if (current == null || current.isEmpty()) {
// It was empty so just add it
request.getRequestHeaders().put(Headers.X_FORWARDED_FOR, remoteHost);
}
else {
// Add the new entry and reset the existing header
request.getRequestHeaders().put(Headers.X_FORWARDED_FOR, current + "," + remoteHost);
}
}
else {
// No existing header or not allowed to reuse the header so set it here
request.getRequestHeaders().put(Headers.X_FORWARDED_FOR, remoteHost);
}
// Set the protocol header and attachment
final String proto = exchange.getRequestScheme().equals("https") ? "https" : "http";
request.getRequestHeaders().put(Headers.X_FORWARDED_PROTO, proto);
request.putAttachment(ProxiedRequestAttachments.IS_SSL, proto.equals("https"));
// Set the server name
final String hostName = exchange.getHostName();
request.getRequestHeaders().put(Headers.X_FORWARDED_HOST, hostName);
request.putAttachment(ProxiedRequestAttachments.SERVER_NAME, hostName);
// Set the port
int port = exchange.getConnection().getLocalAddress(InetSocketAddress.class).getPort();
request.getRequestHeaders().put(Headers.X_FORWARDED_PORT, port);
request.putAttachment(ProxiedRequestAttachments.SERVER_PORT, port);
SSLSessionInfo sslSessionInfo = exchange.getConnection().getSslSessionInfo();
if (sslSessionInfo != null) {
X509Certificate[] peerCertificates;
try {
peerCertificates = sslSessionInfo.getPeerCertificateChain();
if (peerCertificates.length > 0) {
request.putAttachment(ProxiedRequestAttachments.SSL_CERT, Certificates.toPem(peerCertificates[0]));
}
} catch (SSLPeerUnverifiedException e) {
//ignore
} catch (CertificateEncodingException e) {
//ignore
} catch (RenegotiationRequiredException e) {
//ignore
}
request.putAttachment(ProxiedRequestAttachments.SSL_CYPHER, sslSessionInfo.getCipherSuite());
request.putAttachment(ProxiedRequestAttachments.SSL_SESSION_ID, sslSessionInfo.getSessionId());
}
if(rewriteHostHeader) {
InetSocketAddress targetAddress = clientConnection.getConnection().getPeerAddress(InetSocketAddress.class);
request.getRequestHeaders().put(Headers.HOST, targetAddress.getHostString() + ":" + targetAddress.getPort());
request.getRequestHeaders().put(Headers.X_FORWARDED_HOST, exchange.getRequestHeaders().getFirst(Headers.HOST));
}
clientConnection.getConnection().sendRequest(request, new ClientCallback<ClientExchange>() {
@Override
public void completed(final ClientExchange result) {