【ZUUL】拦截器修改请求体后引出的 Content-Length 问题

背景

项目需求,对业务请求要进行拦截,并在请求体添加指定参数以进行请求合法性校验



实现方式和步骤

需求就是这么个需求了,然后就在 zuul 网关引入了一个 Filter,

在filter的 run 方法上,通过

RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();

拿到了 request

然后再通过

public static JSONObject getPostData(HttpServletRequest request) {
StringBuilder data = new StringBuilder();
String line;
BufferedReader reader;
try {
reader = request.getReader();
while (null != (line = reader.readLine())) {
data.append(line);
}
} catch (IOException e) {
return null;
}
if (data.length() > 0) {
JSONObject requestBody = JSONObject.parseObject(data.toString());
return requestBody;
}
return new JSONObject();
}
}

把 request 参数转成一个 json,
再然后往 json 里面加参数,

json 改变后,需要把修改后的请求体再回写到 request, 但因为 request 是不能改写的,所以又引入了: RequestWrapper 来进行对 request 进行重写
大概就是这样子:

request = new BodyRequestWrapper(request, requestBody.toString());
context.setRequest(request);

BodyRequestWrapper

public class BodyRequestWrapper extends HttpServletRequestWrapper {
private String body;
public BodyRequestWrapper(HttpServletRequest request, String context) {
super(request);
body = context;
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes("UTF-8"));
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}

至此第一阶段,就完工了,在本地测试了一下,嗯,还挺好,效果达到了。

问题

问题来了~
在本地测试都挺好的一个代码,一放到测试环境,诶,就不行了,
报错信息,大概就是请求参数解析错误,一个好好的请求参数,硬生生地只截取了一部分,造成 json 解析错误了。

继续定位

嗯。。。大概知道是 Content-Length 的问题了,但是这个 Content-Length 为什么会出问题呢,
一样的请求,之前也没毛病啊?

经过一翻思索,突然想起,不是修改了请求体参数吗!它的长度自然也跟着变化了,
嗯,然后再一查。。。找到了方案,

就是在 BodyRequestWrapper 这个类上,重写 getContentLength 和 getContentLengthLong 这两个方法,把请求体重新计算后再返回就好了。emmm, nice !

@Override
public int getContentLength() {
return body.length();
}
@Override
public long getContentLengthLong() {
return body.length();
}

还是报错

修改一个版本后,满怀希望部署上去,一测,。。。。还是有问题! 还是一样的问题,这个长度还是不对!
怎么回事!
不是重写了这个长度的计算了吗!!!

emmm, 当时也是傻了,这里需要返回的根本不能按字符串长度去计算,应该按字节数组长度去返回才行。
于是,改成这样:

@Override
public int getContentLength() {
return body.getBytes().length;
}
@Override
public long getContentLengthLong() {
return body.getBytes().length;
}

终于!!!好了啊!!泪目了。

小记一下,千万记得,程序里面计算长度,网络传输说的长度,都是字节流的长度啊。。。

posted @   aaacarrot  阅读(557)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
历史上的今天:
2022-04-04 maven 常用指令
2022-04-04 springboot常见报错
点击右上角即可分享
微信分享提示