@Override public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) { return chain.proceed(removeHopByHopHeaders(request)) .map(HopByHopHeadersRemovingInterceptor::removeHopByHopHeaders); }
private Eventual<LiveHttpResponse> putNewState(LiveHttpRequest request, HttpInterceptor.Context context) { return Eventual.of(request) .flatMap(this::requestedUpdate) .map(this::applyUpdate); }
@Override public Eventual<LiveHttpResponse> handle(LiveHttpRequest request, HttpInterceptor.Context context) { return configHandler(request.queryParam("pretty").isPresent()) .handle(request, context) .map(StyxConfigurationHandler::disableCaching); }
private Eventual<RequestedUpdate> requestedUpdate(LiveHttpRequest request) { return requestedNewState(request) .map(state -> { NamedPlugin plugin = plugin(request); return new RequestedUpdate(plugin, state); }); }
@Override public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) { return chain.proceed(request) .flatMap(response -> response.aggregate(this.maxContentLength)) .flatMap(fullResponse -> Eventual.from(asyncEvent(this.delayMillis)) .map(x -> fullResponse)) .map(HttpResponse::stream); }
@Override public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) { // Note that the request ID is repeated for request logging so that a single search term can be used to find both request and response logs. boolean secure = chain.context().isSecure(); logger.logRequest(request, null, secure); return chain.proceed(request).map(response -> { logger.logResponse(request, response, secure); return response; }); }
private static HttpHandler newHandler(String originId, RequestHandler wireMockHandler) { return (httpRequest, ctx) -> httpRequest.aggregate(MAX_CONTENT_LENGTH) .map(fullRequest -> { LOGGER.info("{} received: {}\n{}", new Object[]{originId, fullRequest.url(), fullRequest.body()}); return fullRequest; }) .flatMap(fullRequest -> { Request wmRequest = new WiremockStyxRequestAdapter(fullRequest); com.github.tomakehurst.wiremock.http.Response wmResponse = wireMockHandler.handle(wmRequest); return Eventual.of(toStyxResponse(wmResponse).stream()); }); }
private static HttpHandler newHandler(RequestHandler wireMockHandler) { return (httpRequest, ctx) -> httpRequest.aggregate(MAX_CONTENT_LENGTH) .map(fullRequest -> { LOGGER.info("Received: {}\n{}", new Object[]{fullRequest.url(), fullRequest.body()}); return fullRequest; }) .flatMap(fullRequest -> { Request wmRequest = new WiremockStyxRequestAdapter(fullRequest); com.github.tomakehurst.wiremock.http.Response wmResponse = wireMockHandler.handle(wmRequest); return Eventual.of(toStyxResponse(wmResponse).stream()); }); } }
@Test public void mapsValues() { StepVerifier.create(new Eventual<>(Flux.just("hello")).map(String::toUpperCase)) .expectNext("HELLO") .verifyComplete(); }
@Override public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) { LiveHttpRequest newRequest = request.newBuilder() .header(VIA, viaHeader(request)) .build(); return chain.proceed(newRequest) .map(response -> response.newBuilder() .header(VIA, viaHeader(response)) .build()); }
private Publisher<LiveHttpResponse> sendRequest(LiveHttpRequest request, List<RemoteHost> previousOrigins, int attempt) { if (attempt >= MAX_RETRY_ATTEMPTS) { return Flux.error(new NoAvailableHostsException(this.id)); } Optional<RemoteHost> remoteHost = selectOrigin(request); if (remoteHost.isPresent()) { RemoteHost host = remoteHost.get(); List<RemoteHost> newPreviousOrigins = newArrayList(previousOrigins); newPreviousOrigins.add(remoteHost.get()); return ResponseEventListener.from(host.hostClient().handle(request, HttpInterceptorContext.create()) .map(response -> addStickySessionIdentifier(response, host.origin()))) .whenResponseError(cause -> logError(request, cause)) .whenCancelled(() -> originStatsFactory.originStats(host.origin()).requestCancelled()) .apply() .doOnNext(this::recordErrorStatusMetrics) .map(response -> removeUnexpectedResponseBody(request, response)) .map(this::removeRedundantContentLengthHeader) .onErrorResume(cause -> { RetryPolicyContext retryContext = new RetryPolicyContext(this.id, attempt + 1, cause, request, previousOrigins); return retry(request, retryContext, newPreviousOrigins, attempt + 1, cause); }) .map(response -> addOriginId(host.id(), response)); } else { RetryPolicyContext retryContext = new RetryPolicyContext(this.id, attempt + 1, null, request, previousOrigins); return retry(request, retryContext, previousOrigins, attempt + 1, new NoAvailableHostsException(this.id)); } }
/** * Aggregates content stream and converts this response to a {@link HttpResponse}. * <p> * Returns a {@link Eventual <HttpResponse>} that eventually produces a * {@link HttpResponse}. The resulting full response object has the same * response line, headers, and content as this response. * <p> * The content stream is aggregated asynchronously. The stream may be connected * to a network socket or some other content producer. Once aggregated, a * HttpResponse object is emitted on the returned {@link Eventual}. * <p> * A sole {@code maxContentBytes} argument is a backstop defence against excessively * long content streams. The {@code maxContentBytes} should be set to a sensible * value according to your application requirements and heap size. When the content * size stream exceeds the {@code maxContentBytes}, a @{link ContentOverflowException} * is emitted on the returned observable. * * @param maxContentBytes maximum expected content size * @return a {@link Eventual} */ public Eventual<HttpResponse> aggregate(int maxContentBytes) { return Eventual.from(body.aggregate(maxContentBytes)) .map(it -> new HttpResponse.Builder(this, decodeAndRelease(it)) .disableValidation() .build() ); }
@Override public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) { return request.aggregate(config.maxContentLength()) .flatMap(fullHttpRequest -> Eventual.from(asyncOperation(config.delayMillis()))) .map(outcome -> request.newBuilder().header("X-Outcome", outcome.result())) .flatMap(x -> chain.proceed(request)); } }
@Override public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) { String header = xHcomPluginsHeader(request); final String configPath = environment.pluginConfig(String.class); String pluginsList = environment.configuration().get("plugins.active").get(); LiveHttpRequest newRequest = request.newBuilder() .header(X_HCOM_PLUGINS_HEADER, header) .header(X_HCOM_PLUGINS_CONFIGURATION_PATH, configPath) .header(X_HCOM_PLUGINS_LIST, pluginsList) .header("X-Hcom-Styx-Started", styxStarted) .header("X-Hcom-Styx-Stopped", styxStopped) .build(); Function<ByteBuf, String> byteBufStringFunction = byteBuf -> byteBuf.toString(Charsets.UTF_8); return chain.proceed(newRequest) .flatMap(response -> response.aggregate(1 * 1024 * 1024)) .map(response -> response.newBuilder() .header(X_HCOM_PLUGINS_HEADER, header) .header(X_HCOM_PLUGINS_CONFIGURATION_PATH, configPath) .header(X_HCOM_PLUGINS_LIST, pluginsList) .header("X-Hcom-Styx-Started", styxStarted) .header("X-Hcom-Styx-Stopped", styxStopped) .build()) .map(HttpResponse::stream); }
@Test public void convertsToStreamingHttpRequest() throws Exception { HttpRequest fullRequest = new HttpRequest.Builder(POST, "/foo/bar").body("foobar", UTF_8) .version(HTTP_1_1) .header("HeaderName", "HeaderValue") .cookies(requestCookie("CookieName", "CookieValue")) .build(); LiveHttpRequest streaming = fullRequest.stream(); assertThat(streaming.method(), is(HttpMethod.POST)); assertThat(streaming.url(), is(url("/foo/bar").build())); assertThat(streaming.version(), is(HTTP_1_1)); assertThat(streaming.headers(), containsInAnyOrder( header("Content-Length", "6"), header("HeaderName", "HeaderValue"), header("Cookie", "CookieName=CookieValue"))); assertThat(streaming.cookies(), contains(requestCookie("CookieName", "CookieValue"))); StepVerifier.create(streaming.aggregate(0x10000).map(it -> it.bodyAs(UTF_8))) .expectNext("foobar") .verifyComplete(); }
@Test public void convertsToStreamingHttpResponse() throws Exception { HttpResponse response = response(CREATED) .version(HTTP_1_1) .header("HeaderName", "HeaderValue") .cookies(responseCookie("CookieName", "CookieValue").build()) .body("message content", UTF_8) .build(); LiveHttpResponse streaming = response.stream(); assertThat(streaming.version(), is(HTTP_1_1)); assertThat(streaming.status(), is(CREATED)); assertThat(streaming.headers(), containsInAnyOrder( header("Content-Length", "15"), header("HeaderName", "HeaderValue"), header("Set-Cookie", "CookieName=CookieValue") )); assertThat(streaming.cookies(), contains(responseCookie("CookieName", "CookieValue").build())); StepVerifier.create(streaming.aggregate(0x100000).map(it -> it.bodyAs(UTF_8))) .expectNext("message content") .verifyComplete(); }