Search in sources :

Example 1 with ClientResponse

use of org.springframework.web.reactive.function.client.ClientResponse in project spring-integration by spring-projects.

the class WebFluxRequestExecutingMessageHandler method exchange.

@Override
protected Object exchange(Supplier<URI> uriSupplier, HttpMethod httpMethod, HttpEntity<?> httpRequest, Object expectedResponseType, Message<?> requestMessage) {
    WebClient.RequestBodySpec requestSpec = this.webClient.method(httpMethod).uri(b -> uriSupplier.get()).headers(headers -> headers.putAll(httpRequest.getHeaders()));
    if (httpRequest.hasBody()) {
        requestSpec.body(BodyInserters.fromObject(httpRequest.getBody()));
    }
    Mono<ClientResponse> responseMono = requestSpec.exchange().flatMap(response -> {
        HttpStatus httpStatus = response.statusCode();
        if (httpStatus.isError()) {
            return response.body(BodyExtractors.toDataBuffers()).reduce(DataBuffer::write).map(dataBuffer -> {
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                DataBufferUtils.release(dataBuffer);
                return bytes;
            }).defaultIfEmpty(new byte[0]).map(bodyBytes -> {
                throw new WebClientResponseException("ClientResponse has erroneous status code: " + httpStatus.value() + " " + httpStatus.getReasonPhrase(), httpStatus.value(), httpStatus.getReasonPhrase(), response.headers().asHttpHeaders(), bodyBytes, response.headers().contentType().map(MimeType::getCharset).orElse(StandardCharsets.ISO_8859_1));
            });
        } else {
            return Mono.just(response);
        }
    });
    if (isExpectReply()) {
        return responseMono.flatMap(response -> {
            ResponseEntity.BodyBuilder httpEntityBuilder = ResponseEntity.status(response.statusCode()).headers(response.headers().asHttpHeaders());
            Mono<?> bodyMono;
            if (expectedResponseType != null) {
                if (this.replyPayloadToFlux) {
                    BodyExtractor<? extends Flux<?>, ReactiveHttpInputMessage> extractor;
                    if (expectedResponseType instanceof ParameterizedTypeReference<?>) {
                        extractor = BodyExtractors.toFlux((ParameterizedTypeReference<?>) expectedResponseType);
                    } else {
                        extractor = BodyExtractors.toFlux((Class<?>) expectedResponseType);
                    }
                    Flux<?> flux = response.body(extractor);
                    bodyMono = Mono.just(flux);
                } else {
                    BodyExtractor<? extends Mono<?>, ReactiveHttpInputMessage> extractor;
                    if (expectedResponseType instanceof ParameterizedTypeReference<?>) {
                        extractor = BodyExtractors.toMono((ParameterizedTypeReference<?>) expectedResponseType);
                    } else {
                        extractor = BodyExtractors.toMono((Class<?>) expectedResponseType);
                    }
                    bodyMono = response.body(extractor);
                }
            } else if (this.bodyExtractor != null) {
                Object body = response.body(this.bodyExtractor);
                if (body instanceof Mono) {
                    bodyMono = (Mono<?>) body;
                } else {
                    bodyMono = Mono.just(body);
                }
            } else {
                bodyMono = Mono.empty();
            }
            return bodyMono.map(httpEntityBuilder::body).defaultIfEmpty(httpEntityBuilder.build());
        }).map(this::getReply);
    } else {
        responseMono.subscribe(v -> {
        }, ex -> sendErrorMessage(requestMessage, ex));
        return null;
    }
}
Also used : ParameterizedTypeReference(org.springframework.core.ParameterizedTypeReference) LiteralExpression(org.springframework.expression.common.LiteralExpression) WebClient(org.springframework.web.reactive.function.client.WebClient) Supplier(java.util.function.Supplier) ClientHttpResponse(org.springframework.http.client.reactive.ClientHttpResponse) MimeType(org.springframework.util.MimeType) ValueExpression(org.springframework.integration.expression.ValueExpression) DataBufferUtils(org.springframework.core.io.buffer.DataBufferUtils) Message(org.springframework.messaging.Message) URI(java.net.URI) ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) HttpMethod(org.springframework.http.HttpMethod) Mono(reactor.core.publisher.Mono) AbstractHttpRequestExecutingMessageHandler(org.springframework.integration.http.outbound.AbstractHttpRequestExecutingMessageHandler) BodyExtractor(org.springframework.web.reactive.function.BodyExtractor) DataBuffer(org.springframework.core.io.buffer.DataBuffer) StandardCharsets(java.nio.charset.StandardCharsets) HttpStatus(org.springframework.http.HttpStatus) Flux(reactor.core.publisher.Flux) HttpEntity(org.springframework.http.HttpEntity) BodyExtractors(org.springframework.web.reactive.function.BodyExtractors) ReactiveHttpInputMessage(org.springframework.http.ReactiveHttpInputMessage) MessageHandler(org.springframework.messaging.MessageHandler) BeanFactory(org.springframework.beans.factory.BeanFactory) Expression(org.springframework.expression.Expression) ResponseEntity(org.springframework.http.ResponseEntity) BodyInserters(org.springframework.web.reactive.function.BodyInserters) WebClientResponseException(org.springframework.web.reactive.function.client.WebClientResponseException) Assert(org.springframework.util.Assert) ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) HttpStatus(org.springframework.http.HttpStatus) Mono(reactor.core.publisher.Mono) Flux(reactor.core.publisher.Flux) WebClient(org.springframework.web.reactive.function.client.WebClient) MimeType(org.springframework.util.MimeType) WebClientResponseException(org.springframework.web.reactive.function.client.WebClientResponseException) BodyExtractor(org.springframework.web.reactive.function.BodyExtractor)

Example 2 with ClientResponse

use of org.springframework.web.reactive.function.client.ClientResponse in project spring-cloud-gateway by spring-cloud.

the class SecureHeadersGatewayFilterFactoryTests method secureHeadersFilterWorks.

@Test
public void secureHeadersFilterWorks() {
    Mono<ClientResponse> result = webClient.get().uri("/headers").header("Host", "www.secureheaders.org").exchange();
    SecureHeadersProperties defaults = new SecureHeadersProperties();
    StepVerifier.create(result).consumeNextWith(response -> {
        assertStatus(response, HttpStatus.OK);
        HttpHeaders httpHeaders = response.headers().asHttpHeaders();
        assertThat(httpHeaders.getFirst(X_XSS_PROTECTION_HEADER)).isEqualTo(defaults.getXssProtectionHeader());
        assertThat(httpHeaders.getFirst(STRICT_TRANSPORT_SECURITY_HEADER)).isEqualTo(defaults.getStrictTransportSecurity());
        assertThat(httpHeaders.getFirst(X_FRAME_OPTIONS_HEADER)).isEqualTo(defaults.getFrameOptions());
        assertThat(httpHeaders.getFirst(X_CONTENT_TYPE_OPTIONS_HEADER)).isEqualTo(defaults.getContentTypeOptions());
        assertThat(httpHeaders.getFirst(REFERRER_POLICY_HEADER)).isEqualTo(defaults.getReferrerPolicy());
        assertThat(httpHeaders.getFirst(CONTENT_SECURITY_POLICY_HEADER)).isEqualTo(defaults.getContentSecurityPolicy());
        assertThat(httpHeaders.getFirst(X_DOWNLOAD_OPTIONS_HEADER)).isEqualTo(defaults.getDownloadOptions());
        assertThat(httpHeaders.getFirst(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)).isEqualTo(defaults.getPermittedCrossDomainPolicies());
    }).expectComplete().verify(DURATION);
}
Also used : ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) HttpHeaders(org.springframework.http.HttpHeaders) Test(org.junit.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest)

Example 3 with ClientResponse

use of org.springframework.web.reactive.function.client.ClientResponse in project spring-cloud-sleuth by spring-cloud.

the class TraceWebFluxTests method should_instrument_web_filter.

@Test
public void should_instrument_web_filter() throws Exception {
    // setup
    ConfigurableApplicationContext context = new SpringApplicationBuilder(TraceWebFluxTests.Config.class).web(WebApplicationType.REACTIVE).properties("server.port=0", "spring.jmx.enabled=false", "spring.sleuth.web.skipPattern=/skipped", "spring.application.name=TraceWebFluxTests", "security.basic.enabled=false", "management.security.enabled=false").run();
    ArrayListSpanReporter accumulator = context.getBean(ArrayListSpanReporter.class);
    int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class);
    Controller2 controller2 = context.getBean(Controller2.class);
    clean(accumulator, controller2);
    // when
    ClientResponse response = whenRequestIsSent(port);
    // then
    thenSpanWasReportedWithTags(accumulator, response);
    clean(accumulator, controller2);
    // when
    ClientResponse nonSampledResponse = whenNonSampledRequestIsSent(port);
    // then
    thenNoSpanWasReported(accumulator, nonSampledResponse, controller2);
    // when
    ClientResponse skippedPatternResponse = whenRequestIsSentToSkippedPattern(port);
    // then
    thenNoSpanWasReported(accumulator, skippedPatternResponse, controller2);
    // cleanup
    context.close();
}
Also used : ConfigurableApplicationContext(org.springframework.context.ConfigurableApplicationContext) ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) SpringApplicationBuilder(org.springframework.boot.builder.SpringApplicationBuilder) Environment(org.springframework.core.env.Environment) ArrayListSpanReporter(org.springframework.cloud.sleuth.util.ArrayListSpanReporter) Test(org.junit.Test)

Example 4 with ClientResponse

use of org.springframework.web.reactive.function.client.ClientResponse in project spring-cloud-sleuth by spring-cloud.

the class TraceExchangeFilterFunction method filter.

@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
    final ClientRequest.Builder builder = ClientRequest.from(request);
    Mono<ClientResponse> exchange = Mono.defer(() -> next.exchange(builder.build())).cast(Object.class).onErrorResume(Mono::just).zipWith(Mono.subscriberContext()).flatMap(anyAndContext -> {
        Object any = anyAndContext.getT1();
        Span clientSpan = anyAndContext.getT2().get(CLIENT_SPAN_KEY);
        Mono<ClientResponse> continuation;
        final Tracer.SpanInScope ws = tracer().withSpanInScope(clientSpan);
        if (any instanceof Throwable) {
            continuation = Mono.error((Throwable) any);
        } else {
            continuation = Mono.just((ClientResponse) any);
        }
        return continuation.doAfterSuccessOrError((clientResponse, throwable1) -> {
            Throwable throwable = throwable1;
            if (clientResponse == null || clientResponse.statusCode() == null) {
                if (log.isDebugEnabled()) {
                    log.debug("No response was returned. Will close the span [" + clientSpan + "]");
                }
                handleReceive(clientSpan, ws, clientResponse, throwable);
                return;
            }
            boolean error = clientResponse.statusCode().is4xxClientError() || clientResponse.statusCode().is5xxServerError();
            if (error) {
                if (log.isDebugEnabled()) {
                    log.debug("Non positive status code was returned from the call. Will close the span [" + clientSpan + "]");
                }
                throwable = new RestClientException("Status code of the response is [" + clientResponse.statusCode().value() + "] and the reason is [" + clientResponse.statusCode().getReasonPhrase() + "]");
            }
            handleReceive(clientSpan, ws, clientResponse, throwable);
        });
    }).subscriberContext(c -> {
        if (log.isDebugEnabled()) {
            log.debug("Instrumenting WebClient call");
        }
        Span parent = c.getOrDefault(Span.class, null);
        Span clientSpan = handler().handleSend(injector(), builder, request, tracer().nextSpan());
        if (log.isDebugEnabled()) {
            log.debug("Created a client span for the WebClient " + clientSpan);
        }
        if (parent == null) {
            c = c.put(Span.class, clientSpan);
            if (log.isDebugEnabled()) {
                log.debug("Reactor Context got injected with the client span " + clientSpan);
            }
        }
        return c.put(CLIENT_SPAN_KEY, clientSpan);
    });
    return exchange;
}
Also used : ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) RestClientException(org.springframework.web.client.RestClientException) HttpTracing(brave.http.HttpTracing) ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) ExchangeFunction(org.springframework.web.reactive.function.client.ExchangeFunction) Tracer(brave.Tracer) Span(brave.Span) WebClient(org.springframework.web.reactive.function.client.WebClient) BeansException(org.springframework.beans.BeansException) Mono(reactor.core.publisher.Mono) TraceContext(brave.propagation.TraceContext) Consumer(java.util.function.Consumer) BeanPostProcessor(org.springframework.beans.factory.config.BeanPostProcessor) ClientRequest(org.springframework.web.reactive.function.client.ClientRequest) List(java.util.List) ExchangeFilterFunction(org.springframework.web.reactive.function.client.ExchangeFilterFunction) BeanFactory(org.springframework.beans.factory.BeanFactory) Propagation(brave.propagation.Propagation) HttpClientHandler(brave.http.HttpClientHandler) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Mono(reactor.core.publisher.Mono) RestClientException(org.springframework.web.client.RestClientException) Span(brave.Span) ClientRequest(org.springframework.web.reactive.function.client.ClientRequest)

Aggregations

ClientResponse (org.springframework.web.reactive.function.client.ClientResponse)4 Test (org.junit.Test)2 BeanFactory (org.springframework.beans.factory.BeanFactory)2 WebClient (org.springframework.web.reactive.function.client.WebClient)2 Mono (reactor.core.publisher.Mono)2 Span (brave.Span)1 Tracer (brave.Tracer)1 HttpClientHandler (brave.http.HttpClientHandler)1 HttpTracing (brave.http.HttpTracing)1 Propagation (brave.propagation.Propagation)1 TraceContext (brave.propagation.TraceContext)1 URI (java.net.URI)1 StandardCharsets (java.nio.charset.StandardCharsets)1 List (java.util.List)1 Consumer (java.util.function.Consumer)1 Supplier (java.util.function.Supplier)1 Log (org.apache.commons.logging.Log)1 LogFactory (org.apache.commons.logging.LogFactory)1 BeansException (org.springframework.beans.BeansException)1 BeanPostProcessor (org.springframework.beans.factory.config.BeanPostProcessor)1