Skip to content

ModifyRequestBody GatewayFilter 工厂

你可以使用 ModifyRequestBody 过滤器在网关将请求发送到下游之前修改请求体(Request Body)。

注意

此过滤器只能使用 Java DSL 进行配置(不支持在 application.yml 中配置)。

以下代码演示了如何修改请求体:

Java 配置示例

java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
            .filters(f -> f.prefixPath("/httpbin")
                .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
                    (exchange, s) -> Mono.just(new Hello(s.toUpperCase()))))
            .uri(uri))
        .build();
}

// 示例内部类 Hello
static class Hello {
    String message;

    public Hello() { }

    public Hello(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

代码解析:

  1. 输入类型 (String.class): 告诉过滤器将原始请求体读取为 String。
  2. 输出类型 (Hello.class): 告诉过滤器修改后的请求体应该被转换成 Hello 对象(最终序列化为 JSON)。
  3. Content-Type (MediaType.APPLICATION_JSON_VALUE): 设置下游请求的 Content-Type。
  4. 转换逻辑 (RewriteFunction): 这里的 Lambda 表达式 (exchange, s) -> ... 接收原始的字符串 s,将其转换为大写,放入 Hello 对象中并返回。

注意:空请求体处理

如果请求没有 Body(即 Body 为 null),RewriteFunction 接收到的参数也会是 null。 如果你希望在这种情况下仍然保持请求体为空,应该返回 Mono.empty()

补充教学 —— 为什么要修改请求体?

场景 1:数据格式转换

  • 客户端发送的是 XML 格式的数据。
  • 后端微服务升级了,只支持 JSON 格式。
  • 网关可以在中间拦截,把 XML 读出来,转成 JSON 对象,再发给后端。

场景 2:参数注入/脱敏

  • 注入:所有的请求体里都需要加一个公共字段(比如 traceId 或者 timestamp),可以在网关层统一加上,不用每个端点都写一遍。
  • 脱敏:客户端上传的数据包含敏感信息(如明文密码),网关可以在转发给日志服务或特定后端前,把敏感字段替换成 ******

场景 3:请求体大小写转换

  • 如上面的示例代码所示,把请求体里的字符串全部变成大写。

关键点: 由于请求体修改涉及到反序列化(读出对象) -> 修改逻辑 -> 序列化(写回字节流),这在响应式编程(WebFlux)中稍微有点复杂,所以 Spring Cloud Gateway 目前只支持用 Java 代码(Java DSL)来写这个逻辑,因为 YAML 配置文件没法写复杂的 Lambda 函数。


Based on Spring Framework.