【问题标题】:Weird behaviour in Nginx response header for internal redirects内部重定向的 Nginx 响应标头中的奇怪行为
【发布时间】:2021-04-01 00:59:04
【问题描述】:

我有两个上游服务器 A (tomcat) 和 B (tomcat)。 从服务器 A,我正在发送带有“X-Accel-Redirect”标头的内部重定向,在 nginx.conf 中,我已将其重定向到服务器 B。

我正在从服务器 B 发送一个文件作为响应,并将响应的内容类型设置为 application/x-x509-ca-cert。然后显然 Nginx 将其转发给客户端。但是Nginx发给客户端的响应头是application/x-x509-ca-cert; charset=ISO-8859-1

我自定义了日志输出,access.log 看起来像

application/x-x509-ca-cert application/x-x509-ca-cert; charset=ISO-8859-1 127.0.0.1 - - [31/Mar/2021:15:55:13] "GET /uri" 200

通过反复试验,我得出结论,此字符集仅在内部重定向期间附加。 一项此类测试仅使用一台上游服务器 B 完成,并直接提供响应而无需任何内部重定向。 在这种情况下,日志看起来像

application/x-x509-ca-cert application/x-x509-ca-cert 127.0.0.1 - - [31/Mar/2021:15:55:13] "GET /uri" 200

请解释为什么在内部重定向期间会发生这种情况。我找到了一个解决方案来去除这个字符集并读取“Content-Type”标题。

但我想了解为什么在内部重定向期间会观察到这种行为。

我的 nginx.conf 看起来像

events {
     worker_connections 1024;
}

http {
     log_format  custom  '$upstream_http_content_type $sent_http_content_type $remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

     access_log  /var/log/nginx/access.log custom;

     
     upstream A {
          server A:444;
     }

     upstream B {
          server B:442;
     }

     server {
          listen 8445;
          listen 443 ssl;
          server_name A;
          underscores_in_headers on;
          
          location / {
               proxy_set_header Host $host;
               proxy_set_header X-Forwarded-For $remote_addr;
               if ($http_cookie ~ 'A') {
                    proxy_pass https://A;
                    break;
               }

               proxy_pass https://B;
               proxy_redirect https://B/ https://$host:$server_port/;
          }

        location @internalRedirect {
            internal;
             proxy_set_header Host            $host;
             proxy_set_header customHeader true;
             proxy_set_header X-Forwarded-For $remote_addr;
             proxy_pass https://B;
         }
     }
}

【问题讨论】:

    标签: nginx tomcat


    【解决方案1】:

    1. 请求由客户端发出。这称为主要请求。
    2. 请求被发送到上游服务器 A。(在我的例子中,重定向是基于请求标头中的 cookie 值完成的)
    3. 带有@internalRedirectX-Accel-Redirect 标头由服务器A 提供。
    4. Nginx 向服务器 B 发出 子请求

    这里我们需要了解两件事。

    I) 来自Nginx Official documentation

    需要注意的是,如果在子请求中接收到响应,则始终执行从响应字符集到主请求字符集的转换,无论 override_charset 指令设置如何。

    II) 来自apache doc referencing Http specification

    POST 的默认编码: 旧版本的 HTTP/1.1 规范(例如 RFC 2616)指出,如果没有指定字符集,ISO-8859-1 是基于文本的 HTTP 请求和响应正文的默认字符集。

    对于 GET 请求,我找不到明确说明默认内容类型的文档。但根据我目前的经验,我认为它是 ISO-8859-1。


    所以,结合上面的两个信息。

    1. 客户端向 Nginx 发出请求(没有任何字符编码,因此隐含为ISO-8859-1)。

    2. 从上游获取内部重定向标志后,Nginx 发出子请求并获取响应。然后 Nginx 用主请求头中的字符编码覆盖子请求响应头中的字符编码。

    【讨论】:

      猜你喜欢
      • 2011-11-26
      • 2014-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 2023-03-11
      • 2017-01-30
      相关资源
      最近更新 更多