You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx Ingress Controller无法识别URL编码字符问题求助

问题描述

我的Nginx Ingress Controller遇到了编码字符处理的问题:

  • 后端有个带路径变量的端点:GET /api/v2/products/<<product_name_path_variable>>/aggregate,变量允许包含斜杠(比如实际值是android/phone)
  • 访问不含编码字符的URL(如https://myhost.domain.com/myservice/api/v2/products/androidphone/aggregate)能正常响应
  • 但访问编码斜杠的URL(https://myhost.domain.com/myservice/api/v2/products/android%2Fphone/aggregate)时返回404
  • 直接把服务改成NodePort访问就没问题,说明问题出在Ingress层面

当前的Ingress配置如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    konghq.com/strip-path: "true"
    kubernetes.io/ingress.class: nginx
    meta.helm.sh/release-name: myReleaseName
    meta.helm.sh/release-namespace: myNameSpace
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip
  labels:
    app.kubernetes.io/instance: myInstance
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: my-service
    helm.sh/chart: my-service-1.0.12
  name: my-service
  namespace: myNameSpace
spec:
  rules:
  - host: myhost.domain.com
    http:
      paths:
      - backend:
          service:
            name: my-service
            port:
              name: http
        path: /myservice(/|$)(.*)
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - myhost.domain.com
    secretName: myhost.domain.com-tls
解决方案

针对这个Ingress Nginx的已知问题,有几个可行的解决办法:

1. 启用编码URI保留注解

添加nginx.ingress.kubernetes.io/use-encoded-uri: "true"注解,让Ingress不对URI做解码,直接把编码后的路径传给后端。同时可以删掉无关的Kong和Traefik注解(因为用的是Nginx Ingress):

修改后的Ingress元数据注解:

metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    meta.helm.sh/release-name: myReleaseName
    meta.helm.sh/release-namespace: myNameSpace
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-encoded-uri: "true"

这个注解是核心,它能阻止Nginx把%2F解码成/,避免路径被错误拆分,后端就能正确识别带编码斜杠的路径变量。

2. 调整路径规则适配编码字符

如果上面的注解不够,可以修改路径匹配规则,确保包含编码字符的路径能被正确捕获:

把原路径规则/myservice(/|$)(.*)改成/myservice/(.*),同时调整rewrite-target为/$1:

spec:
  rules:
  - host: myhost.domain.com
    http:
      paths:
      - backend:
          service:
            name: my-service
            port:
              name: http
        path: /myservice/(.*)
        pathType: ImplementationSpecific

对应的注解里的rewrite-target也要改:

nginx.ingress.kubernetes.io/rewrite-target: /$1

记得保留use-encoded-uri: "true"注解。

3. 添加Nginx配置片段(进阶)

如果需要更底层的控制,可以用configuration-snippet添加Nginx原生配置,允许编码斜杠:

metadata:
  annotations:
    # 其他必要注解...
    nginx.ingress.kubernetes.io/configuration-snippet: |
      allow_encoded_slashes on;
    nginx.ingress.kubernetes.io/use-encoded-uri: "true"

allow_encoded_slashes on;是Nginx的原生指令,允许请求中包含编码后的斜杠,配合前面的注解,就能彻底解决路径解析问题。

验证

更新Ingress配置后,执行:

kubectl apply -f <你的Ingress配置文件>.yaml

然后用curl测试:

curl -v https://myhost.domain.com/myservice/api/v2/products/android%2Fphone/aggregate

确认返回正常响应即可。

内容的提问来源于stack exchange,提问作者AliReza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 19:52:35