nginx 中的自定义标头:先记录,然后清理

nginx 中的自定义标头:先记录,然后清理

我需要解析 nginxaccess_log并将记录与用户帐户关联。为此,我决定使用自定义标头:

  1. 应用程序发送自定义标头(如x-userid
  2. Nginx 使用自定义日志格式将该值存储在 access_log 中$sent_http_x_userid
  3. 标头正在被清除,因此客户端看不到它more_clear_headers 'x-userid'

日志记录工作正常,我可以在 access_log 中看到正确的用户 ID。但是,如果我打开清除部分,access_log 会显示“-”,而不是实际用户 ID。

我做错什么了吗?是否可以在将应用程序的标头发送到客户端之前记录该标头,然后使用 nginx 将其清空?

有没有更好的方法来实现这个功能?应用程序是 PHP7,nginx 是 1.10.3

答案1

变量名的$sent_http_x_userid字面意思是标题是发送到客户端。当你清理它时,nginx 将不会发送它,并且不会有变量$sent_http_x_userid

但你真正需要的是记录你已经已收到来自上游。为此$upstream_http_x_userid您可以写入日志的变量。

如果你不想将此标头传递给客户端,则有proxy_hide_header指示。

所以总的来说看起来像这样

log_format coolname '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent [uid=$upstream_http_x_userid] '
                    '"$http_referer" "$http_user_agent"';

server {
    ...
    access_log /var/log/nginx/cool.log coolname;

    location /whatever {
        proxy_pass http://your-app;
        proxy_hide_header x-userid;
    }
}

答案2

我以为这很简单,只需将标头的内容存储在变量中(使用“set”),然后在 log_format 中使用该变量,忽略已清除的标头。但这失败了:set 命令在调用后端之前执行(当上游标头尚未设置时)。

但使用 LUA 却成功了:

            set $saved_uid "X";
            header_filter_by_lua_block {
              ngx.var.saved_uid = ngx.var.upstream_http_x_userid;
            }
            more_clear_headers 'x-userid';

并在log_format中使用该变量:

log_format coolname
  '$remote_addr - $remote_user [$time_local] '
  '"$request" $status $body_bytes_sent [uid=$saved_uid] '
  '"$http_referer" "$http_user_agent"';

相关内容