SpringCloud Gateway获取并传递请求体body

在SpringMVC编程中要想在过滤器或者拦截器获取到请求体body,进行一些操作(比如进行验签),需要自定义RequestWrapper extends HttpServletRequestWrapper对Request进行包装,否则你在过滤器里面读取了请求body后,controller就获取不到body了,因为body是输入流,流只能读取一次。(我的例子程序

在SpringCloud Gateway中,有同样的需求。由于Gateway底层用的Webflux响应式编程,所以获取请求体的写法和SpringMVC是不一样的。

提供一个全局过滤器

package com.edu.gateway.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 在Spring Cloud Gateway中,由于请求的 body 只能被读取一次,因此通常的做法是在第一个过滤器中将请求的 body 读取出来,
 * 然后将 body 数据存储在 ServerWebExchange 的 attributes 中,这样其他的过滤器就可以从 attributes 中获取到 body 数据。
 * <p>
 * 首先,我们需要创建一个全局过滤器来读取 body 数据,并将其存储在 ServerWebExchange 的 attributes ,
 * 然后,其他的过滤器就可以从 ServerWebExchange 的 attributes 中获取到 body 数据:
 * String body = exchange.getAttribute("cachedRequestBody");
 *
 * @author 
 * @date 2023年12月07日 13:19
 */
@Slf4j
@Component
public class CacheBodyGlobalFilter implements GlobalFilter, Ordered {


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        HttpMethod method = exchange.getRequest().getMethod();
        log.info("============CacheBodyGlobalFilter==========method:{}",method.name());
        if (method == HttpMethod.GET || method == HttpMethod.DELETE) {
            return chain.filter(exchange);
        }
        return DataBufferUtils.join(exchange.getRequest().getBody())
                .flatMap(dataBuffer -> {
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    String bodyString = new String(bytes, StandardCharsets.UTF_8);
                    log.info("[CacheBodyGlobalFilter]获取到请求体---------{}", bodyString);
                    exchange.getAttributes().put("cachedRequestBody", bodyString);
                    DataBufferUtils.release(dataBuffer);
                    return chain.filter(exchange);
                });
    }

    @Override
    public int getOrder() {
        return -9999;
    }
}

后面过滤器使用

  String bodyJson = exchange.getAttribute("cachedRequestBody");
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CGI(Common Gateway Interface)是一种标准的Web服务器和应用程序之间进行交互的协议。在CGI,Web服务器接收到客户端发送的请求后,会将请求的参数传递给CGI程序,CGI程序再根据这些参数生成响应内容,将响应发送回Web服务器,Web服务器再将响应发送给客户端。 在CGI程序,解析表单数据也是一个常见的任务。表单数据通常以POST或GET方式提交给CGI程序,CGI程序需要解析这些数据才能进行处理。下面是一个简单的CGI程序解析表单数据的示例: ```python #!/usr/bin/env python # -*- coding: utf-8 -*- import cgi form = cgi.FieldStorage() name = form.getvalue('name') age = form.getvalue('age') print("Content-type:text/html") print("") print("<html>") print("<head>") print("<title>CGI Form Example</title>") print("</head>") print("<body>") print("<h2>Hello, %s!</h2>" % name) print("<p>You are %s years old.</p>" % age) print("</body>") print("</html>") ``` 在这个示例,我们使用了Python的cgi模块来解析表单数据。首先,我们调用`cgi.FieldStorage()`函数来获取表单数据。然后,我们可以通过调用`form.getvalue()`方法来获取表单指定名称的值。最后,我们将解析后的数据输出到响应。 需要注意的是,表单数据的解析方式取决于表单提交的方式。如果是使用POST方式提交表单数据,那么表单数据会包含在请求的正文,需要通过`sys.stdin`或`os.environ['CONTENT_LENGTH']`来获取正文长度和正文内容。如果是使用GET方式提交表单数据,那么表单数据会包含在URL,需要通过`os.environ['QUERY_STRING']`来获取URL的查询字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值