private void assertTooLongFrameErrorResponse(NettyHttpClientResponse serverResponse, ApiError expectedApiError) throws IOException { verifyErrorReceived(serverResponse.payload, serverResponse.statusCode, expectedApiError); }
verifyErrorReceived(response.payload, response.statusCode, INTENTIONAL_EXPLOSION_AFTER_LAST_CHUNK_API_ERROR);
@Test public void should_return_default_payload_when_default_error_handling_occurs() throws IOException { ObjectMapper mapper = new ObjectMapper(); ExtractableResponse response = given() .baseUri(BASE_URI) .port(serverConfig.endpointsPort()) .basePath(DefaultErrorContractEndpoint.MATCHING_PATH) .log().all() .when() .get() .then() .log().headers() .extract(); verifyErrorReceived(response.asString(), INTERNAL_SERVER_ERROR.code(), GENERIC_SERVICE_ERROR); DefaultErrorContractDTO errorContract = mapper.readValue(response.asString(), DefaultErrorContractDTO.class); String errorUidResponseHeader = response.header("error_uid"); assertThat(errorUidResponseHeader).isNotEmpty(); assertThat(errorContract.error_id).isEqualTo(errorUidResponseHeader); UUID errorUidAsUuid = UUID.fromString(errorUidResponseHeader); assertThat(errorUidAsUuid).isNotNull(); }
@Test public void invalid_http_call_with_invalid_URL_escaping_should_result_in_expected_400_error() throws Exception { // given // Incorrectly escaped URLs cause a blowup in RequestInfoImpl when it tries to decode the URL. We can trigger // this by putting a % character that is not followed by a proper escape sequence. NettyHttpClientRequestBuilder request = request() .withMethod(HttpMethod.GET) .withUri("%notAnEscapeSequence"); // 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")) ); }
@Test public void http_call_with_bad_content_type_header_should_result_in_expected_400_error() throws Exception { // given NettyHttpClientRequestBuilder request = request() .withMethod(HttpMethod.GET) .withUri(BasicEndpoint.MATCHING_PATH) .withHeader(HttpHeaderNames.CONTENT_TYPE.toString(), ";"); // 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")) ); }
/** * This test verifies the corner case where the downstream system short circuits and returns a response before * it receives the full request (i.e. the request chunks are still streaming when the response is returned). * This should cause request chunks to fail to stream with an error, but the downstream response should still * be returned to the original caller successfully. */ @Test public void proxy_endpoints_should_successfully_return_short_circuited_downstream_response() throws Exception { // Do this test a bunch of times to try and catch all the race condition possibilities. for (int i = 0; i < 20; i++) { // given int payloadSize = 1024 * 1000; String payload = generatePayload(payloadSize); NettyHttpClientRequestBuilder request = request() .withMethod(HttpMethod.POST) .withUri(RouterEndpointForwardingToShortCircuitError.MATCHING_PATH) .withPaylod(payload) .withHeader(HttpHeaders.Names.CONTENT_LENGTH, payloadSize); // when NettyHttpClientResponse serverResponse = request.execute(proxyServerConfig.endpointsPort(), 3000); // then verifyErrorReceived(serverResponse.payload, serverResponse.statusCode, FAIL_FAST_API_ERROR); } }
@Test public void invalid_http_call_that_causes_Netty_DecoderFailure_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. This will cause Netty to mark the HttpRequest with a DecoderFailure. 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")) ); }