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

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

 

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

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

如图上第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)

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

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

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

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

二、解决办法

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

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

上一篇:Orbeon form 的安装和使用教程


下一篇:第十三课:人人站模板开发(form 表单信息获取)