diff --git a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java index b03e76b9dd..02fce09afa 100644 --- a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java +++ b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java @@ -21,7 +21,6 @@ import static com.netflix.netty.common.HttpLifecycleChannelHandler.CompleteReason.SESSION_COMPLETE; import static com.netflix.zuul.netty.server.http2.Http2OrHttpHandler.PROTOCOL_NAME; -import com.netflix.netty.common.HttpLifecycleChannelHandler; import com.netflix.netty.common.SourceAddressChannelHandler; import com.netflix.netty.common.ssl.SslHandshakeInfo; import com.netflix.netty.common.throttle.RejectionUtils; @@ -133,7 +132,7 @@ private void channelReadInternal(final ChannelHandlerContext ctx, Object msg) th if (clientRequest.decoderResult().isFailure()) { LOG.warn( "Invalid http request. clientRequest = {} , uri = {}, info = {}", - clientRequest.toString(), + clientRequest, clientRequest.uri(), ChannelUtils.channelInfoForLogging(ctx.channel()), clientRequest.decoderResult().cause()); @@ -159,6 +158,19 @@ private void channelReadInternal(final ChannelHandlerContext ctx, Object msg) th ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); zuulRequest.getContext().setError(ze); zuulRequest.getContext().setShouldSendErrorResponse(true); + } else if (zuulRequest.getHeaders().getAll(HttpHeaderNames.HOST.toString()).size() > 1) { + LOG.debug( + "Multiple Host headers. clientRequest = {} , uri = {}, info = {}", + clientRequest, + clientRequest.uri(), + ChannelUtils.channelInfoForLogging(ctx.channel())); + final ZuulException ze = new ZuulException("Multiple Host headers"); + ze.setStatusCode(HttpResponseStatus.BAD_REQUEST.code()); + StatusCategoryUtils.setStatusCategory( + zuulRequest.getContext(), + ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); + zuulRequest.getContext().setError(ze); + zuulRequest.getContext().setShouldSendErrorResponse(true); } handleExpect100Continue(ctx, clientRequest); @@ -206,7 +218,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exc } if (reason == CompleteReason.PIPELINE_REJECT && zuulRequest != null) { - StatusCategoryUtils.setStatusCategory(zuulRequest.getContext(), ZuulStatusCategory.FAILURE_CLIENT_PIPELINE_REJECT); + StatusCategoryUtils.setStatusCategory(zuulRequest.getContext(), ZuulStatusCategory.FAILURE_CLIENT_PIPELINE_REJECT); } if (reason != SESSION_COMPLETE && zuulRequest != null) { diff --git a/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java b/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java index 425729ec26..bf043992ef 100644 --- a/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java +++ b/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java @@ -200,6 +200,35 @@ public void maxHeaderSizeExceeded_setBadRequestStatus() { ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); } + @Test + public void multipleHostHeaders_setBadRequestStatus() { + ClientRequestReceiver receiver = new ClientRequestReceiver(null); + EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestEncoder()); + PassportLoggingHandler loggingHandler = new PassportLoggingHandler(new DefaultRegistry()); + + // Required for messages + channel.attr(SourceAddressChannelHandler.ATTR_SERVER_LOCAL_PORT).set(1234); + channel.pipeline().addLast(new HttpServerCodec()); + channel.pipeline().addLast(receiver); + channel.pipeline().addLast(loggingHandler); + + HttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/post"); + httpRequest.headers().add("Host", "foo.bar.com"); + httpRequest.headers().add("Host", "bar.foo.com"); + + channel.writeOutbound(httpRequest); + ByteBuf byteBuf = channel.readOutbound(); + channel.writeInbound(byteBuf); + channel.readInbound(); + channel.close(); + + HttpRequestMessage request = ClientRequestReceiver.getRequestFromChannel(channel); + SessionContext context = request.getContext(); + assertEquals(StatusCategoryUtils.getStatusCategory(context), + ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); + assertEquals("Multiple Host headers", context.getError().getMessage()); + } + @Test public void setStatusCategoryForHttpPipelining() {