/** * Adapt the given response processor function to a filter function that * only operates on the {@code ClientResponse}. * @param processor the response processor * @return the resulting filter adapter */ static ExchangeFilterFunction ofResponseProcessor(Function<ClientResponse, Mono<ClientResponse>> processor) { Assert.notNull(processor, "ClientResponse Function must not be null"); return (request, next) -> next.exchange(request).flatMap(processor); }
private ClientRequest verifyAndGetRequest() { ClientRequest request = this.captor.getValue(); Mockito.verify(this.exchangeFunction).exchange(request); verifyNoMoreInteractions(this.exchangeFunction); return request; }
public static ExchangeFilterFunction toExchangeFilterFunction(InstanceExchangeFilterFunction delegate) { return (request, next) -> { Optional<?> instance = request.attribute(ATTRIBUTE_INSTANCE); if (instance.isPresent() && instance.get() instanceof Instance) { return delegate.exchange((Instance) instance.get(), request, next); } return next.exchange(request); }; }
/** * Variant of {@link #basicAuthentication(String, String)} that looks up * the {@link Credentials Credentials} in a * {@link #BASIC_AUTHENTICATION_CREDENTIALS_ATTRIBUTE request attribute}. * @return the filter to use * @see Credentials * @deprecated as of Spring 5.1 in favor of using * {@link HttpHeaders#setBasicAuth(String, String)} while building the request. */ @Deprecated public static ExchangeFilterFunction basicAuthentication() { return (request, next) -> { Object attr = request.attributes().get(BASIC_AUTHENTICATION_CREDENTIALS_ATTRIBUTE); if (attr instanceof Credentials) { Credentials cred = (Credentials) attr; return next.exchange(ClientRequest.from(request) .headers(headers -> headers.setBasicAuth(cred.username, cred.password)) .build()); } else { return next.exchange(request); } }; }
@Override public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) { return authorizedClient(request, next) .map(authorizedClient -> bearer(request, authorizedClient)) .flatMap(next::exchange) .switchIfEmpty(next.exchange(request)); }
public static ExchangeFilterFunction setDefaultAcceptHeader() { return (request, next) -> { if (request.headers().getAccept().isEmpty()) { Boolean isRequestForLogfile = request.attribute(ATTRIBUTE_ENDPOINT) .map(Endpoint.LOGFILE::equals) .orElse(false); List<MediaType> acceptedHeaders = isRequestForLogfile ? DEFAULT_LOGFILE_ACCEPT_MEDIATYPES : DEFAULT_ACCEPT_MEDIATYPES; return next.exchange(ClientRequest.from(request) .headers(headers -> headers.setAccept(acceptedHeaders)) .build()); } return next.exchange(request); }; }
@Override public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) { Optional<OAuth2AuthorizedClient> attribute = request.attribute(OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME) .map(OAuth2AuthorizedClient.class::cast); return Mono.justOrEmpty(attribute) .flatMap(authorizedClient -> authorizedClient(request, next, authorizedClient)) .map(authorizedClient -> bearer(request, authorizedClient)) .flatMap(next::exchange) .switchIfEmpty(next.exchange(request)); }
public static ExchangeFilterFunction convertLegacyEndpoint(LegacyEndpointConverter converter) { return (ClientRequest request, ExchangeFunction next) -> { Mono<ClientResponse> clientResponse = next.exchange(request); if (request.attribute(ATTRIBUTE_ENDPOINT).map(converter::canConvert).orElse(false)) { return clientResponse.flatMap(response -> { if (response.headers() .contentType() .map(t -> ACTUATOR_V1_MEDIATYPE.isCompatibleWith(t) || APPLICATION_JSON.isCompatibleWith(t)) .orElse(false)) { return convertClientResponse(converter::convert, ACTUATOR_V2_MEDIATYPE).apply(response); } return Mono.just(response); }); } return clientResponse; }; }
/** * Return a filter that applies HTTP Basic Authentication to the request * headers via {@link HttpHeaders#setBasicAuth(String, String)}. * @param user the user * @param password the password * @return the filter to add authentication headers with * @see HttpHeaders#setBasicAuth(String, String) * @see HttpHeaders#setBasicAuth(String, String, Charset) */ public static ExchangeFilterFunction basicAuthentication(String user, String password) { return (request, next) -> next.exchange(ClientRequest.from(request) .headers(headers -> headers.setBasicAuth(user, password)) .build()); }
@Before public void setup() { MockitoAnnotations.initMocks(this); this.exchangeFunction = mock(ExchangeFunction.class); when(this.exchangeFunction.exchange(this.captor.capture())).thenReturn(Mono.empty()); this.builder = WebClient.builder().baseUrl("/base").exchangeFunction(this.exchangeFunction); }
@Override public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) { return next.exchange(request) .flatMap( response -> redirectIfNecessary(request, next, response)); }
/** * Consume up to the specified number of bytes from the response body and * cancel if any more data arrives. * <p>Internally delegates to {@link DataBufferUtils#takeUntilByteCount}. * @param maxByteCount the limit as number of bytes * @return the filter to limit the response size with * @since 5.1 */ public static ExchangeFilterFunction limitResponseSize(long maxByteCount) { return (request, next) -> next.exchange(request).map(response -> { Flux<DataBuffer> body = response.body(BodyExtractors.toDataBuffers()); body = DataBufferUtils.takeUntilByteCount(body, maxByteCount); return ClientResponse.from(response).body(body).build(); }); }
@Override public Mono<ClientResponse> exchange() { ClientRequest request = (this.inserter != null ? initRequestBuilder().body(this.inserter).build() : initRequestBuilder().build()); return exchangeFunction.exchange(request).switchIfEmpty(NO_HTTP_CLIENT_RESPONSE_ERROR); }
@Test public void apply() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ClientResponse response = mock(ClientResponse.class); ExchangeFunction exchange = r -> Mono.just(response); boolean[] filterInvoked = new boolean[1]; ExchangeFilterFunction filter = (r, n) -> { assertFalse(filterInvoked[0]); filterInvoked[0] = true; return n.exchange(r); }; ExchangeFunction filteredExchange = filter.apply(exchange); ClientResponse result = filteredExchange.exchange(request).block(); assertEquals(response, result); assertTrue(filterInvoked[0]); }
protected WebClient createWebClientForSocketAddress(InetSocketAddress socketAddress) { Builder builder = WebClient.builder().defaultHeaders(it -> it.addAll(getDefaultHeaders())); if (connector != null) { builder = builder.clientConnector(connector); } String baseUrl = String.format("%s://%s:%d", this.scheme, socketAddress.getHostString(), socketAddress.getPort()); return builder.baseUrl(baseUrl).filter((request, next) -> next.exchange(request).doOnError(errorListener)).build(); } }
public static ExchangeFilterFunction retry(int defaultRetries, Map<String, Integer> retriesPerEndpoint) { return (request, next) -> { int retries = 0; if (!request.method().equals(HttpMethod.DELETE) && !request.method().equals(HttpMethod.PATCH) && !request.method().equals(HttpMethod.POST) && !request.method().equals(HttpMethod.PUT)) { retries = request.attribute(ATTRIBUTE_ENDPOINT).map(retriesPerEndpoint::get).orElse(defaultRetries); } return next.exchange(request).retry(retries); }; } }
public static ExchangeFilterFunction addHeaders(HttpHeadersProvider httpHeadersProvider) { return toExchangeFilterFunction((instance, request, next) -> { ClientRequest newRequest = ClientRequest.from(request) .headers(headers -> headers.addAll(httpHeadersProvider.getHeaders( instance))) .build(); return next.exchange(newRequest); }); }
log.trace("Absolute URL '{}' for instance {} not rewritten", request.url(), instance.getId()); if (request.url().toString().equals(instance.getRegistration().getManagementUrl())) { return next.exchange(ClientRequest.from(request) .attribute(ATTRIBUTE_ENDPOINT, Endpoint.ACTUATOR_INDEX) .build()); return next.exchange(request); .url(newUrl) .build(); return next.exchange(newRequest); });
@Override public void subscribe(CoreSubscriber<? super ClientResponse> subscriber) { final ClientRequest.Builder builder = ClientRequest.from(this.request); Context context = subscriber.currentContext(); this.next.exchange(builder.build()).subscribe(new WebClientTracerSubscriber( subscriber, context, findOrCreateSpan(builder), this)); }
@Test public void withStringAttribute() { Map<String, Object> actual = new HashMap<>(); ExchangeFilterFunction filter = (request, next) -> { actual.putAll(request.attributes()); return next.exchange(request); }; this.builder.filter(filter).build() .get().uri("/path") .attribute("foo", "bar") .exchange(); assertEquals("bar", actual.get("foo")); ClientRequest request = verifyAndGetRequest(); assertEquals("bar", request.attribute("foo").get()); }