Spring-cloud-gateway: Modify Request Body for a GET request

Created on 3 Jul 2019  ·  7Comments  ·  Source: spring-cloud/spring-cloud-gateway

We currently have custom code for modifying request body which works but I want to move to the standard ModifyRequestBodyGatewayFilterFactory.

We have a scenario where Spring Cloud Gateway received a GET request and we need call an internal GraphQL api with a POST and a request body.

ModifyRequestBodyGatewayFilterFactory works great if there is a body present in the original request but doesn't apply the rewriteFunction when there is no body on GET requests.

I am using v2.1.2.RELEASE and I have hacked together a change to ModifyRequestBodyGatewayFilterFactory which works for me:

Mono<?> modifiedBody = serverRequest.bodyToMono(inClass)
        .defaultIfEmpty("") //added this line
        .flatMap(o -> config.rewriteFunction.apply(exchange, o));

I appreciate that the ModifyRequestBodyGatewayFilterFactory is beta, but would it be possible to support adding a body for GET requests in the future?

enhancement help wanted

Most helpful comment

I'm not sure I like the edit.

I think I prefer this (closer to what was there prior to the edit).

.switchIfEmpty((Mono) config.rewriteFunction.apply(exchange, null)); //added this line

I don't like the idea of having a body with an empty string. I also think it might need to be opt-in since it is very unusual.

All 7 comments

In general, I don't think it is expected that GET requests would contain a body. There is an interesting thread on this on SO https://stackoverflow.com/questions/978061/http-get-with-request-body.

The change is small enough, that I dont think it would hurt though.

I'm not sure I like the edit.

I think I prefer this (closer to what was there prior to the edit).

.switchIfEmpty((Mono) config.rewriteFunction.apply(exchange, null)); //added this line

I don't like the idea of having a body with an empty string. I also think it might need to be opt-in since it is very unusual.

The original GET doesn't contain a body.

I can add have a go at creating a merge request for this with the opt-in configuration if that would be useful.

@sam-lewis PRs welcome if it is along the lines of my comment.

My interim scheme:
new Predicate copy from ReadBodyPredicateFactory,has all request can match this route。

@Component
public class GwReadBodyPredicateFactory extends AbstractRoutePredicateFactory<GwReadBodyPredicateFactory.Config> {
...
                        return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange,
                            (serverHttpRequest) -> ServerRequest
                                    .create(exchange.mutate().request(serverHttpRequest)
                                            .build(), messageReaders)
                                    .bodyToMono(inClass)
                                    .doOnNext(objectValue -> exchange.getAttributes().put(
                                            CACHE_REQUEST_BODY_OBJECT_KEY,
                                            objectValue.toString().replaceAll("[\n\t\r'']", "")))  //elegant string
                                    .map(objectValue -> config.getPredicate()
                                            .test(objectValue))
                                    .thenReturn(true));// added this line

    ...
}

Is it feasible?@spencergibb

I'm not sure this exactly covers the use-case of this issue, but I worked around empty body in usage of modifyRequestBody by testing for null the original body and returning Mono.empty() when null body.

.modifyRequestBody(String.class, String.class,
                            (webExchange, originalBody) -> {
                                if (originalBody != null) {
                                                                       //modify body
                                                                       [...]
                                    return Mono.just(originalBody);
                                } else {
                                    return Mono.empty();
                                }
                            })

and submitted https://github.com/spring-cloud/spring-cloud-gateway/pull/2000

Was this page helpful?
0 / 5 - 0 ratings

Related issues

esacaceres picture esacaceres  ·  7Comments

ryanjbaxter picture ryanjbaxter  ·  6Comments

pravinkumarb84 picture pravinkumarb84  ·  7Comments

xfworld picture xfworld  ·  3Comments

vborcea picture vborcea  ·  6Comments