您的位置:首页 > 编程语言 > Java开发

通过Zuul访问服务的URL含有中文字符的解决方案

2018-02-12 09:25 281 查看
通常URL中很少含有中文,无奈业务实现各种奇葩都有,在URL中请求参数里带有中文。在以前直接访问服务时,没有问题,但现在通过API网关zuul,就出现了badMessage: 400 Illegal character 错误,为什么呢?如何解决这个问题呢?

问题

       1)部分中文出现 badMessage: 400 Illegal character 错误

                  出现原因:                  首先TracePreZuulFilter的runFilter()会在request header中存入URL,key是X-Span-Name,如果URL中含有中文,那此时header中就包含了中文。                     

                   之后RibbonRoutingFilter会调用Ribbon中RestClient.java的execute()方法来完成路由,在execute()方法会调用Jersy的ApacheHttpClient4来做后续处理

              

                 最后Jersy会创建一个Connection,内部含有一个byte[ ]数组buffer,再循环header,将每一项都转换成一个char[ ]数组,最后将每一个char[]都追加到byte[ ]数组buffer。                                        

                   比如下图中X-Span-Name=http:/commonservice-dictionary-2/tree/1001/node-name/北京添加到CharArrayBuffer之后,CharArrayBuffer中的byte[ ]数组就变成了                       [X, -, S, p, a, n, -, N, a, m, e, :,  , h, t, t, p, :, /, c, o, m, m, o, n, s, e, r, v, i, c, e, -, d, i, c, t, i, o, n, a, r, y, -, 2, /, t, r, e, e, /, 1, 0, 0, 1, /, n, o, d, e, -, n, a, m, e, /, 北, 京, (, K, H, T, M, L, ,,  , l, i, k, e,  , G, e, c, k, o, ),  , C, h, r, o, m, e, /, 5, 8, ., 0, ., 3, 0, 2, 9, ., 1, 1, 0,  , S, a, f, a, r, i, /, 5, 3, 7, ., 3, 6,  , , , , ,  ]                     

                将每一个char[]都追加到byte[ ]数组buffer的过程中,会出现char—>byte强转的情况。可能会出现溢出现象。                 

               如果char是汉字,在这里强转byte时肯定会溢出,而且有些汉字强换成byte之后会是0到31之间的数字,比如上图实例中“北京”的第一个汉字“北”强转成byte就是23。               因为header中含有0-31之间的字符且不是9,10,13,所以下游应用的HttpParser机会报错。提示Illegal character 。                 

               有些汉字强转byte虽然溢出,但是可能得到的数字在0到31以外,这时下游应用的HttpParser就不会报错,正常通过。所以URL如果含有汉字,有些会使下游应用报错Illegal character。

        2)应用接收到request后,URL的中文部分会变成乱码

               除了上面提到的header中的中文问题以外,URL里的中文传到下游应用100%乱码。               因为RibbonRoutingFilter在做路由之前会调用自身的ProxyRequestHelper的buildZuulRequestURI()方法对URL重新build。build的过程中会从RequestContext中取出URI并用ISO-8859-1编码,所以会产生乱码。                 

                                  

解决

重新定义一个ProxyRequestHelper重写buildZuulRequestHeaders和buildZuulRequestURI,并重新组装到RibbonRoutingFilter中。



最后在启动类Application.java中重新定义ProxyRequestHelper和RibbonRoutingFilter,覆盖原来Spring框架中定义的ProxyRequestHelper和RibbonRoutingFilter。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息