Spring Cloud gateway has filters to modify request body and response body.
ModifyResponseBody
ModifyRequestBody
As mentioned in the specs, for using these filters, we need to use DSL approach rather than YAML file for configuring routes. So essentially you will have a RouteBuilder like below -
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
RouteLocatorBuilder.Builder routeLocator = builder.routes().route(
p -> {
p.method("POST").path("/<path>").filters(f -> {
f.modifyRequestBody(String.class,
String.class,
(exchange, reqMessage) -> {
try {
log.info(">>> INCOMING REQUEST <<< - {}", reqMessage);
//Get query params
exchange.getRequest().getQueryParams();
// In case of any validation errors, throw an exception so that
// it can be handled by a global exception handler
return Mono.just(reqMessage);
} catch (Exception e) {
log.error("Exception while modifying request body", e);
throw new RuntimeException(e.getMessage());
}
});
})
});
}
A global exception handler could then send a standard response back -
public class GlobalExceptionHandler extends AbstractErrorWebExceptionHandler {
@Override
protected RouterFunction<ServerResponse> getRoutingFunction (ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse);
}
private Mono<ServerResponse> renderErrorResponse (ServletRequest request) {
Map<String,Object> errorPropertiesMap = getErrorAttributes (request,ErrorAttributeOptions.defaults());
String customErrMsg = errorPropertiesMap.get("message") != null ? errorPropertiesMap.get("message").toString() : null;
if(customErrMsg != null) {
return ServerResponse.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorPropertiesMap.get("message")));
} else {
return ServerResponse.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorPropertiesMap));
}
}
}