问题
k8s
中ingress
使用的是ingress-nginx
.
项目中用到了spring cloud gateway
做API
网关,部署环境有docker
、k8s
等. 测试出现一个问题:
请求的URL
路径中如果出现了中文
参数,如http://localhost:8080/test?param=你好
,如果部署在docker
或者裸机
上,后台
服务接收到的参数param
是你好
,但是如果部署在k8s
上,后台接收到的参数可能是UrlEncode
之后的%E4%BD%A0%E5%A5%BD
,这不是后台需要的. 虽然可以在后台通过URLDecoder.decode(name, "UTF-8")
强制解码,不过比较麻烦.
分析
测试中发现,
- 如果直接将
后台
服务部署到k8s
上,通过service -> ingress
暴露出来,不管是通过k8s
中ClusterIP
,如http://10.96.240.18:8080/test?param=你好
, 还是通过ingress
域名http://local.com/test?param=你好
请求后台服务,后台能够正确接收到参数为你好
,证明问题可能不是因为部署在k8s
上造成的,只可能是spring cloud gateway
做API
网关原因; - 但是部署在
docker
或者裸机
上,通过spring cloud gateway
网关请求后台
服务,后台能够正确接收到参数为你好
,证明网关也是没有问题的,问题只可能是部署环境k8s
的原因; - 如果将网关服务部署到
k8s
上,又有两种情况:- 通过
ingress
域名请求网关 -> 后台
,后台接收到的参数是%E4%BD%A0%E5%A5%BD
,看似是网关的问题; - 通过
ClusterIP
请求网关 -> 后台
,后台接收到的参数是你好
,这又证明网关没问题,看似是ingress
的问题,但前面也证明了ingress
可以正确传递中文
字符,非常的奇怪!
- 通过
- 将
spring cloud gateway
中所有的Filter
全部注释掉,发现通过ingress
域名请求网关 -> 后台
,后台也能正确的接收到中文
参数,证明还是网关
的问题,而且这个问题只有部署在k8s
中搭配ingress-nginx
使用时才会暴露.
解决
依次将注释掉的Filter
加回去,证明问题出现在class XXXX extends ForwardedHeaderFilter
这个类上.这个类用于设置网关跨域访问
和网关本身接口权限验证
.
测试发现,即使只注释成下面这样,还是会有问题,但是注释掉@Component
,就没有问题.应该是super.filter(exchange, chain)
父类这个方法有问题.
@Component
@Slf4j
public class AuthTokenFilter extends ForwardedHeaderFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//跨域问题 接口权限验证 TODO
return super.filter(exchange, chain);
}
}
改成下面这样测试可以解决问题.
@Component
@Slf4j
public class AuthTokenFilter extends ForwardedHeaderFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//跨域问题 接口权限验证 TODO
return chain.filter(exchange);
}
}