欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring cloud gateway部署到k8s上UrlEncode问题

程序员文章站 2024-03-20 23:15:46
...

问题

k8singress使用的是ingress-nginx.

项目中用到了spring cloud gatewayAPI网关,部署环境有dockerk8s等. 测试出现一个问题:
请求的URL路径中如果出现了中文参数,如http://localhost:8080/test?param=你好,如果部署在docker或者裸机上,后台服务接收到的参数param你好,但是如果部署在k8s上,后台接收到的参数可能是UrlEncode之后的%E4%BD%A0%E5%A5%BD,这不是后台需要的. 虽然可以在后台通过URLDecoder.decode(name, "UTF-8")强制解码,不过比较麻烦.

分析

测试中发现,

  • 如果直接将后台服务部署到k8s上,通过service -> ingress暴露出来,不管是通过k8sClusterIP,如http://10.96.240.18:8080/test?param=你好, 还是通过ingress域名http://local.com/test?param=你好请求后台服务,后台能够正确接收到参数为你好,证明问题可能不是因为部署在k8s上造成的,只可能是spring cloud gatewayAPI网关原因;
  • 但是部署在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);
    }
}