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;
}
}
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);
}
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();
}
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;
}
Aggregations