Skip to content

Instantly share code, notes, and snippets.

@sandipchitale
Last active August 21, 2023 06:42
Show Gist options
  • Save sandipchitale/8fae3e3cc263e9b65593f61ab923b273 to your computer and use it in GitHub Desktop.
Save sandipchitale/8fae3e3cc263e9b65593f61ab923b273 to your computer and use it in GitHub Desktop.
Webclient passthru #webflux #webclient #springboot
package sandipchitale.webclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClientRequest;
import java.time.Duration;
@SpringBootApplication
public class WebclientPassthruApplication {
public static void main(String[] args) {
SpringApplication.run(WebclientApplication.class, args);
}
@RestController
public static class WebclientController {
private final WebClient.Builder webClientBuilder;
public WebclientController() {
this.webClientBuilder = WebClient.builder()
.baseUrl("https://postman-echo.com")
.filter(getXTimeoutMillisFilter())
.filter(getXFrameOptionsFilter());
}
/**
* If X-Timeout-Millis request header is present in the request then set the response timeout to that value.
* Remove cookie header.
*
* @return
*/
private static ExchangeFilterFunction getXTimeoutMillisFilter() {
return ExchangeFilterFunction.ofRequestProcessor((ClientRequest clientRequest) -> {
String timeoutMillis = clientRequest.headers().getFirst("X-Timeout-Millis");
if (timeoutMillis != null) {
return Mono.just(ClientRequest.from(clientRequest)
.headers(httpHeaders -> {
// Cleanup the header
// httpHeaders.remove("X-Timeout-Millis");
// sensitive headers
httpHeaders.remove(HttpHeaders.COOKIE);
})
.httpRequest((ClientHttpRequest clientHttpRequest) -> {
HttpClientRequest reactorRequest = clientHttpRequest.getNativeRequest();
reactorRequest.responseTimeout(Duration.ofMillis(Long.parseLong(timeoutMillis)));
})
.build());
}
return Mono.just(clientRequest);
});
}
/**
* Set X-Frame-Options response header to SAMEORIGIN.
*
* @return
*/
private static ExchangeFilterFunction getXFrameOptionsFilter() {
return ExchangeFilterFunction.ofResponseProcessor((ClientResponse clientResponse) -> {
clientResponse = clientResponse
.mutate()
.headers(httpHeaders -> {
// Remove some headers
// httpHeaders.remove(HttpHeaders.SET_COOKIE);
})
.header("X-Frame-Options", "SAMEORIGIN")
.build();
return Mono.just(clientResponse);
});
}
@RequestMapping("/method")
public Mono<ResponseEntity<byte[]>> method(ServerHttpRequest serverHttpRequest) {
return webClientBuilder
.build()
.method(serverHttpRequest.getMethod())
.uri("/" + serverHttpRequest.getMethod().name().toLowerCase())
.headers(httpHeaders -> {
httpHeaders.addAll(serverHttpRequest.getHeaders());
})
// Pass body through as is
.body(BodyInserters.fromDataBuffers(serverHttpRequest.getBody()))
.retrieve()
// Pass error response through as is
.onStatus((HttpStatusCode status) -> {
return status.isError();
},
(ClientResponse clientResponse) -> {
return Mono.empty();
})
// Pass response through as is
.toEntity(byte[].class);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment