使用标头过滤代理响应标头

are*_*555 2 http nginx nginx-reverse-proxy

我有一个上游服务器,它经常通过返回“Set-Cookie”响应头来设置 Cookie。

我想在上述上游服务器前面有一个 nginx 代理:

Browser => Nginx => Upstream
Run Code Online (Sandbox Code Playgroud)

如果Browser => Nginx请求有标头,X-No-Cookies: true我希望响应Upstream => Nginx => Browser不包含Set-Cookie响应标头。如果X-No-Cookies有任何其他值,我会撒谎Set-Cookie返回未更改的响应标头。我无法更改上游服务器的响应标头行为。

目前我的nginx配置如下,具体注意proxy_hide_header指令的使用。我还在响应头中回显了该$proxy_hide_header变量X-No-Cookies

map $http_x_no_cookies $proxy_hide_header {
  default "";
  "true"  "Set-Cookie";
}

# Homepage
server {
  listen 80;
  server_name example.com;

  location /api {
    proxy_pass        https://example.com/api;
    proxy_hide_header $proxy_hide_header;
    add_header        "X-No-Cookies" $proxy_hide_header;
  }
}
Run Code Online (Sandbox Code Playgroud)

当我使用 cURL 发出请求时:

curl \
  http://example.com/api \
  -H 'X-No-Cookies: true' \
  -I
Run Code Online (Sandbox Code Playgroud)

我得到以下响应标头:

Server: nginx/1.12.2
Date: Thu, 13 Dec 2018 02:26:41 GMT
Content-Type: application/json
Content-Length: 2255
Connection: keep-alive
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization
Access-Control-Allow-Methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Expose-Headers: Content-Length
Set-Cookie: foo=bar; Max-Age=2592000; Expires=Sat, 12 Jan 2019 02:26:41 GMT; Path=/; Domain=example.com; Secure
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-No-Cookies: Set-Cookie
Run Code Online (Sandbox Code Playgroud)

每当proxy_hide_header提供一个 nginx 变量作为参数时,它似乎没有任何效果。如果我将变量交换为字符串($proxy_hide_header替换为"Set-Cookie"),我会得到所需的行为 -Set-Cookie响应标头被省略。

编辑:我已将此问题的代码推送到 GitHub

  • 我的原始(非工作)实现在这里
  • Ivan Shatsky 的解决方案在这里

Iva*_*sky 5

多么有趣的挑战!确实,$proxy_hide_header不接受变量作为其参数,并且不能在if块内使用。我们也不能$upstream_...直接在location块内使用变量,因为它的值还没有被评估。最后我找到了解决方案。我们总是隐藏Set-Cookie标题,然后在需要时再次设置它,通过map表达式计算值:

map $http_x_no_cookies $hide_cookies {
    default "0";
    "true"  "1";
}

map $hide_cookies$upstream_http_set_cookie $cookies {
    ~^0(.*)$ $1;
}

upstream backend {
    server example.com;
}

server {
    listen 80;
    server_name example.com;

    location /api {
        proxy_pass        https://backend/api;
        proxy_hide_header Set-Cookie;
        add_header Set-Cookie $cookies;
    }
}
Run Code Online (Sandbox Code Playgroud)