Search in sources :

Example 1 with NettyHttpClientResponse

use of com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse in project riposte by Nike-Inc.

the class VerifyCornerCasesComponentTest method invalid_http_call_should_result_in_expected_400_error.

@Test
public void invalid_http_call_should_result_in_expected_400_error() throws Exception {
    // given
    // Normal request, but fiddle with the first chunk as it's going out to remove the HTTP version and make it an
    // invalid HTTP call.
    NettyHttpClientRequestBuilder request = request().withMethod(HttpMethod.GET).withUri(BasicEndpoint.MATCHING_PATH).withPipelineAdjuster(p -> p.addFirst(new ChannelOutboundHandlerAdapter() {

        @Override
        public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
            String msgAsString = ((ByteBuf) msg).toString(CharsetUtil.UTF_8);
            if (msgAsString.contains("HTTP/1.1")) {
                msg = Unpooled.copiedBuffer(msgAsString.replace("HTTP/1.1", ""), CharsetUtil.UTF_8);
            }
            super.write(ctx, msg, promise);
        }
    }));
    // when
    NettyHttpClientResponse response = request.execute(downstreamServerConfig.endpointsPort(), 3000);
    // then
    verifyErrorReceived(response.payload, response.statusCode, new ApiErrorWithMetadata(SampleCoreApiError.MALFORMED_REQUEST, Pair.of("cause", "Invalid HTTP request")));
}
Also used : ApiErrorWithMetadata(com.nike.backstopper.apierror.ApiErrorWithMetadata) ChannelOutboundHandlerAdapter(io.netty.channel.ChannelOutboundHandlerAdapter) NettyHttpClientResponse(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ChannelPromise(io.netty.channel.ChannelPromise) ByteBuf(io.netty.buffer.ByteBuf) NettyHttpClientRequestBuilder(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientRequestBuilder) Test(org.junit.Test)

Example 2 with NettyHttpClientResponse

use of com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse in project riposte by Nike-Inc.

the class VerifyProxyRequestsDoNotAlterRequestToDownstreamServiceTest method proxy_endpoints_should_honor_chunked_transfer_encoding.

@Test
public void proxy_endpoints_should_honor_chunked_transfer_encoding() throws Exception {
    // given
    int payloadSize = 10000;
    String payload = generatePayload(payloadSize);
    NettyHttpClientRequestBuilder request = request().withMethod(HttpMethod.POST).withUri(RouterEndpoint.MATCHING_PATH).withPaylod(payload).withHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED).withHeader(HttpHeaders.Names.HOST, "localhost");
    // when
    NettyHttpClientResponse serverResponse = request.execute(proxyServerConfig.endpointsPort(), incompleteCallTimeoutMillis);
    // then
    assertThat(serverResponse.payload).isEqualTo(DownstreamEndpoint.RESPONSE_PAYLOAD);
    assertThat(serverResponse.statusCode).isEqualTo(HttpResponseStatus.OK.code());
    assertProxyAndDownstreamServiceHeadersAndTracingHeadersAdded();
    String proxyBody = extractBodyFromRawRequest(proxyServerRequest.toString());
    String downstreamBody = extractBodyFromRawRequest(downstreamServerRequest.toString());
    // assert request was sent in chunks
    // https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
    assertThat(downstreamBody).contains("\r\n");
    assertThat(proxyBody).contains("\r\n");
    // assert bodies are equal
    String proxyBodyMinusChunkInfo = extractFullBodyFromChunks(proxyBody);
    String downstreamBodyMinusChunkInfo = extractFullBodyFromChunks(downstreamBody);
    // assert proxy and downstream have same bodies
    assertThat(proxyBodyMinusChunkInfo).isEqualTo(downstreamBodyMinusChunkInfo);
    // assert input payload matches proxy and downstream payloads
    assertThat(proxyBodyMinusChunkInfo).isEqualTo(payload);
    assertThat(downstreamBodyMinusChunkInfo).isEqualTo(payload);
}
Also used : NettyHttpClientResponse(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse) ProxyRouterEndpoint(com.nike.riposte.server.http.ProxyRouterEndpoint) StandardEndpoint(com.nike.riposte.server.http.StandardEndpoint) Endpoint(com.nike.riposte.server.http.Endpoint) NettyHttpClientRequestBuilder(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientRequestBuilder) Test(org.junit.Test)

Example 3 with NettyHttpClientResponse

use of com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse in project riposte by Nike-Inc.

the class VerifyProxyEndpointsDoNotAlterRequestOrResponseByDefaultComponentTest method proxy_endpoints_should_not_alter_request_or_response_when_there_is_no_payload.

@DataProvider(value = { "CHUNKED_REQUEST_CHUNKED_RESPONSE", "CHUNKED_REQUEST_NORMAL_RESPONSE", "NORMAL_REQUEST_CHUNKED_RESPONSE", "NORMAL_REQUEST_NORMAL_RESPONSE" })
@Test
public void proxy_endpoints_should_not_alter_request_or_response_when_there_is_no_payload(CallScenario scenario) throws Exception {
    // given
    NettyHttpClientRequestBuilder request = request().withMethod(HttpMethod.POST).withUri(RouterEndpoint.MATCHING_PATH).withHeader(SOME_EXPECTED_REQUEST_HEADER.getKey(), SOME_EXPECTED_REQUEST_HEADER.getValue()).withHeader(HttpHeaders.Names.HOST, "localhost").withHeader(DownstreamEndpoint.RESPONSE_SHOULD_BE_EMPTY_REQUEST_HEADER_KEY, "true");
    if (scenario.isChunkedRequest) {
        request = request.withHeader(TRANSFER_ENCODING, CHUNKED);
    } else {
        request = request.withHeader(CONTENT_LENGTH, 0);
    }
    if (scenario.isChunkedResponse) {
        request.withHeader(DownstreamEndpoint.RESPONSE_SHOULD_BE_CHUNKED_REQUEST_HEADER_KEY, "true");
    }
    // when
    NettyHttpClientResponse serverResponse = request.execute(proxyServerConfig.endpointsPort(), incompleteCallTimeoutMillis);
    // then
    // Sanity check the response from the caller's perspective.
    assertThat(serverResponse.statusCode).isEqualTo(HttpResponseStatus.OK.code());
    assertThat(serverResponse.payload).isNullOrEmpty();
    // Verify all the requests through the proxy to the downstream.
    verifyRawRequestStuff(scenario, "");
    // Verify all the responses from the downstream through the proxy.
    verifyRawResponseStuff(scenario, "");
}
Also used : NettyHttpClientResponse(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse) NettyHttpClientRequestBuilder(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientRequestBuilder) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 4 with NettyHttpClientResponse

use of com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse in project riposte by Nike-Inc.

the class VerifyProxyEndpointsDoNotAlterRequestOrResponseByDefaultComponentTest method proxy_endpoints_should_handle_always_empty_response_scenarios_correctly.

@DataProvider(value = { "STATUS_204_RESPONSE    |   true", "STATUS_204_RESPONSE    |   false", "STATUS_205_RESPONSE    |   true", "STATUS_205_RESPONSE    |   false", "STATUS_304_RESPONSE    |   true", "STATUS_304_RESPONSE    |   false", "HEAD_REQUEST           |   true", "HEAD_REQUEST           |   false" }, splitBy = "\\|")
@Test
public void proxy_endpoints_should_handle_always_empty_response_scenarios_correctly(AlwaysEmptyResponseScenario scenario, boolean isChunkedResponse) throws Exception {
    // given
    NettyHttpClientRequestBuilder request = request().withMethod(scenario.requestMethod).withUri(RouterEndpoint.MATCHING_PATH).withHeader(SOME_EXPECTED_REQUEST_HEADER.getKey(), SOME_EXPECTED_REQUEST_HEADER.getValue()).withHeader(HttpHeaders.Names.HOST, "localhost").withHeader(CONTENT_LENGTH, 0).withHeader(DownstreamEndpoint.DESIRED_RESPONSE_STATUS_CODE_HEADER_KEY, scenario.responseStatusCode);
    if (isChunkedResponse) {
        request.withHeader(DownstreamEndpoint.RESPONSE_SHOULD_BE_CHUNKED_REQUEST_HEADER_KEY, "true");
    }
    // when
    NettyHttpClientResponse serverResponse = request.execute(proxyServerConfig.endpointsPort(), incompleteCallTimeoutMillis);
    // then
    // Sanity check the response from the caller's perspective.
    assertThat(serverResponse.statusCode).isEqualTo(scenario.responseStatusCode);
    assertThat(serverResponse.payload).isNullOrEmpty();
    {
        // Verify content-length header. We have to do this on the raw on-the-wire data because the Netty
        // HttpObjectAggregator (which is used by NettyHttpClientResponse) adds a Content-Length header even
        // if the original response didn't have one (e.g. 204 response).
        HttpHeaders proxyResponseHeaders = extractHeadersFromRawRequestOrResponse(proxyServerRawResponse.toString());
        HttpHeaders downstreamResponseHeaders = extractHeadersFromRawRequestOrResponse(downstreamServerRawResponse.toString());
        String proxyResponseContentLengthHeader = proxyResponseHeaders.get(CONTENT_LENGTH);
        assertThat(proxyResponseContentLengthHeader).isEqualTo(downstreamResponseHeaders.get(CONTENT_LENGTH));
        // to verifying the value of that header.
        if (scenario.responseStatusCode == 205) {
            // Netty treats 205 special - it strips any payload and transfer-encoding header, and sets
            // content-length to 0. So even though we ask for a chunked response (which would normally lead to
            // null content-length response header), we end up with content-length header equal to zero.
            // See this Netty PR and issue: https://github.com/netty/netty/pull/7891
            // and https://github.com/netty/netty/issues/7888
            assertThat(proxyResponseContentLengthHeader).isEqualTo("0");
        } else if (isChunkedResponse || scenario.responseStatusCode == 204) {
            // Chunked responses will never have content-length header defined, and
            // 204 is special - it should never have content-length returned regardless of transfer encoding.
            assertThat(proxyResponseContentLengthHeader).isNull();
        } else if (scenario.isResponseAllowedToLieAboutContentLength) {
            assertThat(proxyResponseContentLengthHeader).isEqualTo(String.valueOf(DownstreamEndpoint.RESPONSE_PAYLOAD.length()));
        } else {
            assertThat(proxyResponseContentLengthHeader).isEqualTo("0");
        }
    }
    CallScenario normalOrChunkedResponseScenario = (isChunkedResponse) ? CallScenario.NORMAL_REQUEST_CHUNKED_RESPONSE : CallScenario.NORMAL_REQUEST_NORMAL_RESPONSE;
    // Verify all the requests through the proxy to the downstream (not strictly necessary for what this test is
    // testing, but doesn't hurt).
    verifyRawRequestStuff(normalOrChunkedResponseScenario, "");
    // Verify all the responses from the downstream through the proxy.
    if (scenario.expectProxyToStripTransferEncodingResponseHeader) {
        verifyRawResponseStuffButIgnoreTransferEncodingHeader(normalOrChunkedResponseScenario, "");
    } else {
        verifyRawResponseStuff(normalOrChunkedResponseScenario, "");
    }
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) NettyHttpClientResponse(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse) NettyHttpClientRequestBuilder(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientRequestBuilder) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 5 with NettyHttpClientResponse

use of com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse in project riposte by Nike-Inc.

the class VerifyRequestSizeValidationComponentTest method should_return_expected_response_when_endpoint_disabled_chunked_request_size_validation.

@Test
public void should_return_expected_response_when_endpoint_disabled_chunked_request_size_validation() throws Exception {
    NettyHttpClientRequestBuilder request = request().withMethod(HttpMethod.POST).withUri(BasicEndpointWithRequestSizeValidationDisabled.MATCHING_PATH).withPaylod(generatePayloadOfSizeInBytes(GLOBAL_MAX_REQUEST_SIZE + 100)).withHeader(HttpHeaders.Names.TRANSFER_ENCODING, CHUNKED);
    // when
    NettyHttpClientResponse serverResponse = request.execute(serverConfig.endpointsPort(), incompleteCallTimeoutMillis);
    // then
    assertThat(serverResponse.statusCode).isEqualTo(HttpResponseStatus.OK.code());
    assertThat(serverResponse.payload).isEqualTo(BasicEndpointWithRequestSizeValidationDisabled.RESPONSE_PAYLOAD);
}
Also used : NettyHttpClientResponse(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse) NettyHttpClientRequestBuilder(com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientRequestBuilder) Test(org.junit.Test)

Aggregations

NettyHttpClientRequestBuilder (com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientRequestBuilder)22 NettyHttpClientResponse (com.nike.riposte.server.testutils.ComponentTestUtils.NettyHttpClientResponse)22 Test (org.junit.Test)22 DataProvider (com.tngtech.java.junit.dataprovider.DataProvider)10 Endpoint (com.nike.riposte.server.http.Endpoint)5 ProxyRouterEndpoint (com.nike.riposte.server.http.ProxyRouterEndpoint)5 StandardEndpoint (com.nike.riposte.server.http.StandardEndpoint)5 ApiErrorWithMetadata (com.nike.backstopper.apierror.ApiErrorWithMetadata)3 ByteBuf (io.netty.buffer.ByteBuf)2 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2 ChannelOutboundHandlerAdapter (io.netty.channel.ChannelOutboundHandlerAdapter)2 ChannelPromise (io.netty.channel.ChannelPromise)2 SimpleProxyRouterEndpoint (com.nike.riposte.server.http.impl.SimpleProxyRouterEndpoint)1 ComponentTestUtils.createNettyHttpClientBootstrap (com.nike.riposte.server.testutils.ComponentTestUtils.createNettyHttpClientBootstrap)1 Bootstrap (io.netty.bootstrap.Bootstrap)1 Channel (io.netty.channel.Channel)1 DefaultHttpHeaders (io.netty.handler.codec.http.DefaultHttpHeaders)1 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)1