/** * Executes the given request asynchronously, handling the response with the given responseHandlerFunction, and * returns a {@link CompletableFuture} that represents the result of executing the * responseHandlerFunction on the downstream response. Any error anywhere along the way will cause the returned * future to be completed with {@link CompletableFuture#completeExceptionally(Throwable)}. * <p/> * NOTE: This is a helper method for calling {@link #executeAsyncHttpRequest(RequestBuilderWrapper, * AsyncResponseHandler, java.util.Deque, java.util.Map)} that uses {@link * ChannelAttributes#getHttpProcessingStateForChannel(ChannelHandlerContext)} to extract the {@link * HttpProcessingState} from the given ctx argument, and then grabs {@link * HttpProcessingState#getDistributedTraceStack()} and {@link HttpProcessingState#getLoggerMdcContextMap()} to use * as the distributed trace stack and MDC info for the downstream call. */ public <O> CompletableFuture<O> executeAsyncHttpRequest(RequestBuilderWrapper requestBuilderWrapper, AsyncResponseHandler<O> responseHandlerFunction, ChannelHandlerContext ctx) { HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get(); if (state == null) throw new IllegalStateException("state cannot be null"); Map<String, String> mdcContextMap = state.getLoggerMdcContextMap(); Deque<Span> distributedTraceStack = state.getDistributedTraceStack(); requestBuilderWrapper.setCtx(ctx); return executeAsyncHttpRequest(requestBuilderWrapper, responseHandlerFunction, distributedTraceStack, mdcContextMap); }
@Test public void get_set_ChannelHandlerContext_works_as_expected() { // given requestBuilderWrapper = new RequestBuilderWrapper( url, httpMethod, requestBuilder, customCircuitBreaker, disableCircuitBreaker); ChannelHandlerContext ctx = mock(ChannelHandlerContext.class); // when requestBuilderWrapper.setCtx(ctx); // then assertThat(ctx).isEqualTo(requestBuilderWrapper.getCtx()); }
@Test public void executeAsyncHttpRequest_with_ctx_extracts_mdc_and_tracing_info_from_ctx_and_delegates_to_kitchen_sink_execute_method() { // given RequestBuilderWrapper rbwMock = mock(RequestBuilderWrapper.class); AsyncResponseHandler responseHandlerMock = mock(AsyncResponseHandler.class); CompletableFuture cfMock = mock(CompletableFuture.class); doReturn(cfMock).when(helperSpy).executeAsyncHttpRequest( any(RequestBuilderWrapper.class), any(AsyncResponseHandler.class), any(Deque.class), any(Map.class) ); Map<String, String> mdcMock = mock(Map.class); Deque<Span> spanStackMock = mock(Deque.class); state.setLoggerMdcContextMap(mdcMock); state.setDistributedTraceStack(spanStackMock); // when CompletableFuture result = helperSpy.executeAsyncHttpRequest(rbwMock, responseHandlerMock, ctxMock); // then verify(helperSpy).executeAsyncHttpRequest(rbwMock, responseHandlerMock, spanStackMock, mdcMock); assertThat(result).isSameAs(cfMock); verify(rbwMock).setCtx(ctxMock); }
RequestBuilderWrapper rbw = new RequestBuilderWrapper(url, method, reqMock, customCb, false); if (useNettyEventLoop) rbw.setCtx(ctxMock);