/** * Return a composed filter function that first applies this filter, and * then applies the given {@code "after"} filter. * @param afterFilter the filter to apply after this filter * @return the composed filter */ default ExchangeFilterFunction andThen(ExchangeFilterFunction afterFilter) { Assert.notNull(afterFilter, "ExchangeFilterFunction must not be null"); return (request, next) -> filter(request, afterRequest -> afterFilter.filter(afterRequest, next)); }
/** * Apply this filter to the given {@linkplain ExchangeFunction}, resulting * in a filtered exchange function. * @param exchange the exchange function to filter * @return the filtered exchange function */ default ExchangeFunction apply(ExchangeFunction exchange) { Assert.notNull(exchange, "ExchangeFunction must not be null"); return request -> this.filter(request, exchange); }
@Test(expected = IllegalArgumentException.class) public void basicAuthenticationInvalidCharacters() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ExchangeFunction exchange = r -> Mono.just(mock(ClientResponse.class)); ExchangeFilterFunctions.basicAuthentication("foo", "\ud83d\udca9").filter(request, exchange); }
@Test public void statusHandlerMatch() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ClientResponse response = mock(ClientResponse.class); when(response.statusCode()).thenReturn(HttpStatus.NOT_FOUND); ExchangeFunction exchange = r -> Mono.just(response); ExchangeFilterFunction errorHandler = ExchangeFilterFunctions.statusError( HttpStatus::is4xxClientError, r -> new MyException()); Mono<ClientResponse> result = errorHandler.filter(request, exchange); StepVerifier.create(result) .expectError(MyException.class) .verify(); }
@Test public void statusHandlerNoMatch() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ClientResponse response = mock(ClientResponse.class); when(response.statusCode()).thenReturn(HttpStatus.NOT_FOUND); Mono<ClientResponse> result = ExchangeFilterFunctions .statusError(HttpStatus::is5xxServerError, req -> new MyException()) .filter(request, req -> Mono.just(response)); StepVerifier.create(result) .expectNext(response) .expectComplete() .verify(); }
@Test @SuppressWarnings("deprecation") public void basicAuthenticationAbsentAttributes() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ClientResponse response = mock(ClientResponse.class); ExchangeFunction exchange = r -> { assertFalse(r.headers().containsKey(HttpHeaders.AUTHORIZATION)); return Mono.just(response); }; ExchangeFilterFunction auth = ExchangeFilterFunctions.basicAuthentication(); assertFalse(request.headers().containsKey(HttpHeaders.AUTHORIZATION)); ClientResponse result = auth.filter(request, exchange).block(); assertEquals(response, result); }
@Test public void basicAuthenticationUsernamePassword() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ClientResponse response = mock(ClientResponse.class); ExchangeFunction exchange = r -> { assertTrue(r.headers().containsKey(HttpHeaders.AUTHORIZATION)); assertTrue(r.headers().getFirst(HttpHeaders.AUTHORIZATION).startsWith("Basic ")); return Mono.just(response); }; ExchangeFilterFunction auth = ExchangeFilterFunctions.basicAuthentication("foo", "bar"); assertFalse(request.headers().containsKey(HttpHeaders.AUTHORIZATION)); ClientResponse result = auth.filter(request, exchange).block(); assertEquals(response, result); }
@Test @SuppressWarnings("deprecation") public void basicAuthenticationAttributes() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL) .attributes(org.springframework.web.reactive.function.client.ExchangeFilterFunctions .Credentials.basicAuthenticationCredentials("foo", "bar")) .build(); ClientResponse response = mock(ClientResponse.class); ExchangeFunction exchange = r -> { assertTrue(r.headers().containsKey(HttpHeaders.AUTHORIZATION)); assertTrue(r.headers().getFirst(HttpHeaders.AUTHORIZATION).startsWith("Basic ")); return Mono.just(response); }; ExchangeFilterFunction auth = ExchangeFilterFunctions.basicAuthentication(); assertFalse(request.headers().containsKey(HttpHeaders.AUTHORIZATION)); ClientResponse result = auth.filter(request, exchange).block(); assertEquals(response, result); }
@Test public void andThen() { ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ClientResponse response = mock(ClientResponse.class); ExchangeFunction exchange = r -> Mono.just(response); boolean[] filtersInvoked = new boolean[2]; ExchangeFilterFunction filter1 = (r, n) -> { assertFalse(filtersInvoked[0]); assertFalse(filtersInvoked[1]); filtersInvoked[0] = true; assertFalse(filtersInvoked[1]); return n.exchange(r); }; ExchangeFilterFunction filter2 = (r, n) -> { assertTrue(filtersInvoked[0]); assertFalse(filtersInvoked[1]); filtersInvoked[1] = true; return n.exchange(r); }; ExchangeFilterFunction filter = filter1.andThen(filter2); ClientResponse result = filter.filter(request, exchange).block(); assertEquals(response, result); assertTrue(filtersInvoked[0]); assertTrue(filtersInvoked[1]); }
@Test public void limitResponseSize() { DefaultDataBufferFactory bufferFactory = new DefaultDataBufferFactory(); DataBuffer b1 = dataBuffer("foo", bufferFactory); DataBuffer b2 = dataBuffer("bar", bufferFactory); DataBuffer b3 = dataBuffer("baz", bufferFactory); ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build(); ClientResponse response = ClientResponse.create(HttpStatus.OK).body(Flux.just(b1, b2, b3)).build(); Mono<ClientResponse> result = ExchangeFilterFunctions.limitResponseSize(5) .filter(request, req -> Mono.just(response)); StepVerifier.create(result.flatMapMany(res -> res.body(BodyExtractors.toDataBuffers()))) .consumeNextWith(buffer -> assertEquals("foo", string(buffer))) .consumeNextWith(buffer -> assertEquals("ba", string(buffer))) .expectComplete() .verify(); }
/** * Return a composed filter function that first applies this filter, and then applies the * {@code after} filter. * @param after the filter to apply after this filter is applied * @return a composed filter that first applies this function and then applies the * {@code after} function */ default ExchangeFilterFunction andThen(ExchangeFilterFunction after) { Assert.notNull(after, "'after' must not be null"); return (request, next) -> { ExchangeFunction nextExchange = exchangeRequest -> after.filter(exchangeRequest, next); return filter(request, nextExchange); }; }
@Override public Mono<ClientResponse> exchange(ClientRequest<?> request) { Assert.notNull(request, "'request' must not be null"); return this.filter.filter(request, this::exchangeInternal); }
/** * Apply this filter to the given exchange function, resulting in a filtered exchange function. * @param exchange the exchange function to filter * @return the filtered exchange function */ default ExchangeFunction apply(ExchangeFunction exchange) { Assert.notNull(exchange, "'exchange' must not be null"); return request -> this.filter(request, exchange); }