diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java index 5dbb9013..402cea0c 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java @@ -65,6 +65,15 @@ public class ModifyRequestBodyGatewayFilterFactory BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, config.getOutClass()); HttpHeaders headers = new HttpHeaders(); headers.putAll(exchange.getRequest().getHeaders()); + + // the new content type will be computed by bodyInserter + // and then set in the request decorator + headers.remove(HttpHeaders.CONTENT_LENGTH); + + // if the body is changing content types, set it here, to the bodyInserter will know about it + if (config.getContentType() != null) { + headers.set(HttpHeaders.CONTENT_TYPE, config.getContentType()); + } CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); return bodyInserter.insert(outputMessage, new BodyInserterContext()) // .log("modify_request", Level.INFO) @@ -76,7 +85,7 @@ public class ModifyRequestBodyGatewayFilterFactory long contentLength = headers.getContentLength(); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.putAll(super.getHeaders()); - if (contentLength >= 0) { + if (contentLength > 0) { httpHeaders.setContentLength(contentLength); } else { // TODO: this causes a 'HTTP/1.1 411 Length Required' on httpbin.org @@ -99,7 +108,12 @@ public class ModifyRequestBodyGatewayFilterFactory public static class Config { private Class inClass; private Class outClass; + + private String contentType; + + @Deprecated private Map inHints; + @Deprecated private Map outHints; private RewriteFunction rewriteFunction; @@ -122,19 +136,23 @@ public class ModifyRequestBodyGatewayFilterFactory return this; } + @Deprecated public Map getInHints() { return inHints; } + @Deprecated public Config setInHints(Map inHints) { this.inHints = inHints; return this; } + @Deprecated public Map getOutHints() { return outHints; } + @Deprecated public Config setOutHints(Map outHints) { this.outHints = outHints; return this; @@ -156,5 +174,14 @@ public class ModifyRequestBodyGatewayFilterFactory this.rewriteFunction = rewriteFunction; return this; } + + public String getContentType() { + return contentType; + } + + public Config setContentType(String contentType) { + this.contentType = contentType; + return this; + } } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java index a64af933..cfa4cc7e 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java @@ -206,6 +206,21 @@ public class GatewayFilterSpec extends UriSpec { .apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction))); } + /** + * A filter that can be used to modify the request body. + * This filter is BETA and may be subject to change in a future release. + * @param inClass the class to convert the incoming request body to + * @param outClass the class the Gateway will add to the request before it is routed + * @param newContentType the new Content-Type header to be sent + * @param rewriteFunction the {@link RewriteFunction} that transforms the request body + * @param the original request body class + * @param the new request body class + * @return a {@link GatewayFilterSpec} that can be used to apply additional filters + */ + public GatewayFilterSpec modifyRequestBody(Class inClass, Class outClass, String newContentType, RewriteFunction rewriteFunction) { + return filter(getBean(ModifyRequestBodyGatewayFilterFactory.class) + .apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction).setContentType(newContentType))); + } /** * A filter that can be used to modify the response body * This filter is BETA and may be subject to change in a future release. diff --git a/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java b/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java index 7901b668..58b5fc19 100644 --- a/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java +++ b/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java @@ -70,11 +70,8 @@ public class GatewaySampleApplication { ) .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org") .filters(f -> f.prefixPath("/httpbin") - //TODO: add as configuration to modifyRequestBody - .setRequestHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE) - .removeRequestHeader("Content-Length") .addResponseHeader("X-TestHeader", "rewrite_request") - .modifyRequestBody(String.class, Hello.class, + .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> { return Mono.just(new Hello(s.toUpperCase())); }) @@ -83,7 +80,6 @@ public class GatewaySampleApplication { .route("rewrite_request_upper", r -> r.host("*.rewriterequestupper.org") .filters(f -> f.prefixPath("/httpbin") .addResponseHeader("X-TestHeader", "rewrite_request_upper") - .removeRequestHeader("Content-Length") .modifyRequestBody(String.class, String.class, (exchange, s) -> { return Mono.just(s.toUpperCase()+s.toUpperCase());