Nginx不喜欢下划线_

一、缘由

最近有发生过一个诡异想象:

  1. 生产环境异常,客户端添加的自定义Header:app_versiion,经过nginx和网关后,传到后端服务会丢失。

  2. 预发布环境正常,预发布和生产的差别在没经过nginx代理。初步判断是Nginx的问题。

  3. 在生产环境访问日志中打印Header信息$http_app_version,值为空。确认是Nginx丢弃了。

  4. 联想到之前upstream下划线的问题,怀疑是下划线的问题。更换Header中下划线为中划线即app-version后,再次通过curl模拟请求,Nginx日志正常打印了app-version的Header信息。

二、自定义Header不喜欢下划线

Nginx会把header中变量的大写字母转化为小写字母,把中划线转换为下划线,再加上前缀http:比如X-LIST 转换为http_x_list。

1、原因

为什么会使nginx和apache服务器对名称中带下划线header不做转发呢,查阅相关资料后发现是CGI(公共网关接口Common Gateway Interface,CGI是Web 服务器运行时外部程序的规范)的历史遗留问题如下,大概意思就是 下划线和中划线都为会被映射为 CGI 系统变量中名中的下划线,这样容易引起混淆。官方解释如下:

If you do not explicitly set underscores_in_headers on;, NGINX will silently drop HTTP headers with underscores (which are perfectly valid according to the HTTP standard). This is done in order to prevent ambiguities when mapping headers to CGI variables as both dashes and underscores are mapped to underscores during that process.

2、Nginx关于头部的两个配置

  • ignore_invalid_headers 默认on

Controls whether header fields with invalid names should be ignored. Valid names are composed of English letters, digits, hyphens, and possibly underscores (as controlled by the underscores_in_headers directive).

  • underscores_in_headers 默认off

Enables or disables the use of underscores in client request header fields. When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive.

上述说明:

  1. underscores_in_headers 默认为off,带有下划线的header默认是invalid。

  2. Nginx对valid_headers的规定就是英文字母,数字,连字号和下划线(可以通过underscores_in_headers控制),默认情况下其他invalid_headers会忽略并丢弃。

3、解决办法

  1. 在自定义header中要使用中划线,禁止使用下划线(推荐)。

  2. 在http或者server中,将underscores_in_headers参数设置为on。

4、nginx的header还禁止dot(.)

三、Upstream name不喜欢下划线

后端是Java服务的情况下,在配置upstream的name的时候,如果带有下划线,比如big_data,前端会反回400错误。

1、原因

2、解决办法

  1. upsrteam的名字不是用下划线,使用中划线或者驼峰。

  2. 在location处设置 proxy_set_header HOST $host

    这个配置的主要是在nginx在转发http请求的时候会加上实际的Host请求头。如http请求是 http://abc.com/hello, 那么nginx在转发http请求的时候会原封不动的把host请求头(Host:abc.com)转发给后台服务。对于nginx而言,如果没有配置proxy_set_header HOST $host的时候会默认修改Host为upstream的名称。

四、排查手段

1、Nginx 错误日志级别

nginx error日志默认级别是error,只打印重要的错误日志。在调试和定位nginx问题的时候可以提高日志级别为debug 或者 info。error_log logs/app_err.log debug;

2、Curl 模拟请求

curl -H "app-version:1.2.3" http://www.abc.com:/health-check

3、Tcpdump抓包

五、启示

  • 排查问题,第一是看日志,debug级别的日志。

  • 排查问题,第二是看官方文档的相关说明。

  • 运维必须系统地学习常用工具组件的官档和教程。

  • 最好能看懂源代码,源代码能解决一切疑问。

  • 抓包,当实在无法确认问题出在哪一个环节的时候,就抓包。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 lxwno.1@163.com

×

喜欢就点赞,疼爱就打赏