in zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java [309:398]
private HttpRequestMessage buildZuulHttpRequest(HttpRequest nativeRequest, ChannelHandlerContext clientCtx) {
PerfMark.attachTag("path", nativeRequest, HttpRequest::uri);
// Setup the context for this request.
SessionContext context;
if (decorator != null) { // Optionally decorate the context.
SessionContext tempContext = new SessionContext();
// Store the netty channel in SessionContext.
tempContext.set(CommonContextKeys.NETTY_SERVER_CHANNEL_HANDLER_CONTEXT, clientCtx);
context = decorator.decorate(tempContext);
// We expect the UUID is present after decoration
PerfMark.attachTag("uuid", context, SessionContext::getUUID);
} else {
context = new SessionContext();
}
// Get the client IP (ignore XFF headers at this point, as that can be app specific).
Channel channel = clientCtx.channel();
String clientIp = getClientIp(channel);
// This is the only way I found to get the port of the request with netty...
int port =
channel.attr(SourceAddressChannelHandler.ATTR_SERVER_LOCAL_PORT).get();
String serverName = channel.attr(SourceAddressChannelHandler.ATTR_SERVER_LOCAL_ADDRESS)
.get();
SocketAddress clientDestinationAddress =
channel.attr(SourceAddressChannelHandler.ATTR_LOCAL_ADDR).get();
InetSocketAddress proxyProtocolDestinationAddress = channel.attr(
SourceAddressChannelHandler.ATTR_PROXY_PROTOCOL_DESTINATION_ADDRESS)
.get();
if (proxyProtocolDestinationAddress != null) {
context.set(CommonContextKeys.PROXY_PROTOCOL_DESTINATION_ADDRESS, proxyProtocolDestinationAddress);
}
// Store info about the SSL handshake if applicable, and choose the http scheme.
String scheme = SCHEME_HTTP;
SslHandshakeInfo sslHandshakeInfo =
channel.attr(SslHandshakeInfoHandler.ATTR_SSL_INFO).get();
if (sslHandshakeInfo != null) {
context.set(CommonContextKeys.SSL_HANDSHAKE_INFO, sslHandshakeInfo);
scheme = SCHEME_HTTPS;
}
// Decide if this is HTTP/1 or HTTP/2.
String protocol = channel.attr(Http2OrHttpHandler.PROTOCOL_NAME).get();
if (protocol == null) {
protocol = nativeRequest.protocolVersion().text();
}
// Strip off the query from the path.
String path = parsePath(nativeRequest.uri());
// Setup the req/resp message objects.
HttpRequestMessage request = new HttpRequestMessageImpl(
context,
protocol,
nativeRequest.method().asciiName().toString().toLowerCase(Locale.ROOT),
path,
copyQueryParams(nativeRequest),
copyHeaders(nativeRequest),
clientIp,
scheme,
port,
serverName,
clientDestinationAddress,
false);
// Try to decide if this request has a body or not based on the headers (as we won't yet have
// received any of the content).
// NOTE that we also later may override this if it is Chunked encoding, but we receive
// a LastHttpContent without any prior HttpContent's.
if (HttpUtils.hasChunkedTransferEncodingHeader(request) || HttpUtils.hasNonZeroContentLengthHeader(request)) {
request.setHasBody(true);
}
// Store this original request info for future reference (ie. for metrics and access logging purposes).
request.storeInboundRequest();
// Store the netty request for use later.
context.set(CommonContextKeys.NETTY_HTTP_REQUEST, nativeRequest);
// Store zuul request on netty channel for later use.
channel.attr(ATTR_ZUUL_REQ).set(request);
if (nativeRequest instanceof DefaultFullHttpRequest) {
ByteBuf chunk = ((DefaultFullHttpRequest) nativeRequest).content();
request.bufferBodyContents(new DefaultLastHttpContent(chunk));
}
return request;
}