其他分享
首页 > 其他分享> > Zuul关于application/x-www-form-urlencoded踩坑

Zuul关于application/x-www-form-urlencoded踩坑

作者:互联网

一、问题描述:

POST请求,A项目调用B项目,空格转码成了%20;

POST请求,A项目调用zuul,zuul转发到B项目,空格变成了+号;

具体问题:

1、A通过调用FormBody对contentType为application/x-www-form-urlencoded的入参进行编码,其将空格转成了%20

 

2、通过A直接调用B,因为contentType为application/x-www-form-urlencoded,所以tomcat在处理这个请求的时候,从body里面拿出数据流写入parameter里面,导致B项目采取req.getInputStream()的方式拿入参时,没有获取到,所以需要从ParameterMap中获取

如图上第2点所示,最终拿到数据进行编码后再写回 req.getContentLength()长度的数组里面,方法为:in.readFully(dataOrigin),这样写没有问题,因为A入参过来编码空格转成了%20,这儿编码后也将+号替换成了%20,所以A直接调用B这段代码没有问题(URLEncoder.encode(nowStr,"utf-8")是将空格转成+)

3、通过A先调用zuul网关,由于在zuul网关中FormBodyWrapperFilter中会对contentType为application/x-www-form-urlencoded的数据进行特殊处理,将入参中的空格编码成+,然后再写回body中,org.springframework.http.converter.FormHttpMessageConverter.writeForm(MultiValueMap<String, String>, MediaType, HttpOutputMessage)

 这样,contentLength将会变短,因为原先空格转成了%20,但是在zuul网关中空格转成了+号,所以当再次转发到B项目时,还是会走上图中的if块中的将+再次编码成%20的逻辑,这样

 入参的contentLength和改写后的字符串.getBytes的长度肯定是不等的,再用contentLength的长度去装改写后的入参的数据肯定装不下,所以会报错

二、解决办法

将图中的 req.getContentLength()换成改写后的body.length即可,如果是A直接调用B,那么contentLength肯定是和改写后的入参的长度相等的,因为本身就是将空格换成了%20,如果A调用Zuul网关,再由Zuul网关调用B,由于Zuul网关将空格换成了+号,所以contentLength变短了,那么在上图将空格转成了%20后,入参的byte长度肯定会变成,所以这个时候要么用入参的长度的数组去装改写后的入参,要么在改写后将新的长度写入contentLength里面即可!!!!

标签:www,调用,20,form,contentLength,zuul,网关,空格,Zuul
来源: https://blog.csdn.net/DJYDFT2831djydft/article/details/121787113