proxy_set_header官网说明

官网关于proxy_set_header的说明如下:

Syntax:   proxy_set_header field value;
Default:  proxy_set_header Host $proxy_host;
          proxy_set_header Connection close;
Context:  httpserverlocation

Allows redefining or appending fields to the request header passed to the proxied server. The value can contain text, variables, and their combinations. These directives are inherited from the previous level if and only if there are no proxy_set_header directives defined on the current level. By default, only two fields are redefined:

proxy_set_header Host       $proxy_host;
proxy_set_header Connection close;

If caching is enabled, the header fields “If-Modified-Since”, “If-Unmodified-Since”, “If-None-Match”, “If-Match”, “Range”, and “If-Range” from the original request are not passed to the proxied server.

An unchanged “Host” request header field can be passed like this:

proxy_set_header Host       $http_host;

However, if this field is not present in a client request header then nothing will be passed. In such a case it is better to use the $host variable – its value equals the server name in the “Host” request header field or the primary server name if this field is not present:

proxy_set_header Host       $host;

In addition, the server name can be passed together with the port of the proxied server:

proxy_set_header Host       $host:$proxy_port;

f the value of a header field is an empty string then this field will not be passed to a proxied server:

proxy_set_header Accept-Encoding "";
几个需要注意的地方:
  • $host、$proxy_host和$http_host区别
  • Http协议header头中的host对Nginx的影响

$host、$proxy_host和$http_host区别

为了更方便的说明这三者之间的区别,我们使用一个转发范例进行说明:

    upstream myapp1 {
        server app.example.com;
    }

    server {
        listen 80;
        server_name  proxy1.test.com;
        location / {
            proxy_pass http://myapp1;
            proxy_set_header Host $host;
        }
    }

    server {
        listen 80;
        server_name  proxy2.test.com;
        location / {
            proxy_pass http://myapp1;
            proxy_set_header Host $proxy_host;
        }
    }

   server {
        listen 80;
        server_name  proxy3.test.com;
        location / {
            proxy_pass http://myapp1;
            proxy_set_header Host $http_host;
        }
    }
  • $host 按照如下优先级获得
    • 请求行中的host
    • 请求头中的Host头部
    • 与一条请求匹配的server name
  • $proxy_host 默认值,即代理的和转发的host
  • $http_host 请求头中读取到的Host

范例1:

curl -X GET \
  http://proxy1.test.com/ \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: proxy1.test.com' \
  -H 'Referer: http://proxy1.test.com/' \
  -H 'cache-control: no-cache'

此时$host的值为proxy1.test.com

范例2:

curl -X GET \
  http://proxy2.test.com/ \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: proxy2.test.com' \
  -H 'Referer: http://proxy1.test.com/' \
  -H 'cache-control: no-cache'

此时$proxy_host的值为app.example.com

范例2:

curl -X GET \
  http://proxy3.test.com/ \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: proxy3.test.com' \
  -H 'Referer: http://proxy1.test.com/' \
  -H 'cache-control: no-cache'

此时$http_host的值为proxy3.test.com

header头中的Host对Nginx代理的影响

Nginx在做代理服务时,通常会启用多个server,请求会根据server name,进入相应的server配置执行流程,而Host就是Nginx进入不同server执行流程的依据,因此,在多server name的配置中,Host的正确至关重要,也要求我们在构建Http请求时,一定规范的使用Host这个header头。

在日常开发使用中经常会使用nginx进行反向代理或转发,因此记录一下:

location 匹配规则

location [=|~|~*|^~] /uri/ { … }

模式含义
location = /uri= 表示精确匹配,只有完全匹配上才能生效
location ^~ /uri^~ 开头对URL路径进行前缀匹配,并且在正则之前
location ~ pattern开头表示区分大小写的正则匹配
location ~* pattern开头表示不区分大小写的正则匹配
location /uri不带任何修饰符,也表示前缀匹配,但是在正则匹配之后
location /通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default

前缀匹配时,Nginx 不对 url 做编码,因此请求为 /static/20%/aa,可以被规则 ^~ /static/ /aa 匹配到(注意是空格)

多个 location 配置的情况下匹配顺序为(参考资料而来,还未实际验证,试试就知道了,不必拘泥,仅供参考):

  • 首先精确匹配 =
  • 其次前缀匹配 ^~
  • 其次是按文件中顺序的正则匹配
  • 然后匹配不带任何修饰的前缀匹配
  • 最后是交给 / 通用匹配
  • 当有匹配成功时候,停止匹配,按当前匹配规则处理请求

注意:前缀匹配,如果有包含关系时,按最大匹配原则进行匹配。比如在前缀匹配:location /dir01与 location /dir01/dir02,如有请求 http://localhost/dir01/dir02/file 将最终匹配到 location /dir01/dir02

例子,有如下匹配规则:

location = / {
   echo "规则A";
}
location = /login {
   echo "规则B";
}
location ^~ /static/ {
   echo "规则C";
}
location ^~ /static/files {
    echo "规则X";
}
location ~ \.(gif|jpg|png|js|css)$ {
   echo "规则D";
}
location ~* \.png$ {
   echo "规则E";
}
location /img {
    echo "规则Y";
}
location / {
   echo "规则F";
}

那么产生的效果如下:

  • 访问根目录 /,比如 http://localhost/ 将匹配 规则A
  • 访问 http://localhost/login 将匹配 规则Bhttp://localhost/register 则匹配 规则F
  • 访问 http://localhost/static/a.html 将匹配 规则C
  • 访问 http://localhost/static/files/a.exe 将匹配 规则X,虽然 规则C 也能匹配到,但因为最大匹配原则,最终选中了 规则X。你可以测试下,去掉规则 X ,则当前 URL 会匹配上 规则C
  • 访问 http://localhost/a.gifhttp://localhost/b.jpg 将匹配 规则D 和 规则 E ,但是 规则 D 顺序优先,规则 E 不起作用,而 http://localhost/static/c.png 则优先匹配到 规则 C
  • 访问 http://localhost/a.PNG 则匹配 规则 E ,而不会匹配 规则 D ,因为 规则 E 不区分大小写。
  • 访问 http://localhost/img/a.gif 会匹配上 规则D,虽然 规则Y 也可以匹配上,但是因为正则匹配优先,而忽略了 规则Y
  • 访问 http://localhost/img/a.tiff 会匹配上 规则Y

访问 http://localhost/category/id/1111 则最终匹配到规则 F ,因为以上规则都不匹配,这个时候应该是 Nginx 转发请求给后端应用服务器,比如 FastCGI(php),tomcat(jsp),Nginx 作为反向代理服务器存在。

Link: https://moonbingbing.gitbooks.io/openresty-best-practices/ngx/nginx_local_pcre.html

Nginx的默认配置是不支持的pathinfo的,要支持path_info也很简单。
原配置如下

      location ~ \.php$ {
            root           /data0/wwwroot/default;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /data0/wwwroot/default$fastcgi_script_name;
            include        fastcgi_params;
      }

修改为:

        location ~ \.php(.*)$ {
            root           /data0/wwwroot/default;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param  SCRIPT_FILENAME  /data0/wwwroot/default$fastcgi_script_name;
            include        fastcgi_params;
        }

修改的地方:
1、将location ~ \.php$ 修改为 location ~ \.php(.*)$
2、添加如下两行

    fastcgi_split_path_info ^(.+\.php)(.*)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;

这个pathinfo的问题碰到好几次了,每一次都是thinkPHP框架所致,远离thinkPHP,幸福一生。

用私钥来做这件事。生成一个解密的key文件,替代原来key文件。
openssl rsa -in www.example.com.key -out www.example.com.key.unsecure

然后修改配置文件
 ssl on; 
 ssl_certificate cert/www.example.com.crt;
 ssl_certificate_key cert/www.example.com.key.unsecure;

这样就可以不用输入密码了

对于nginx来说,如果打开了gzip,会对关闭掉etag。

在我们的应用中etag是后端返回的,关闭了就影响到了逻辑。

修改:

在srv/http/modules/ngx_http_gzip_filter_module.c

ngx_http_gzip_header_filter函数中屏蔽//ngx_http_clear_etag(r);

然后重编

 

转自: http://blog.csdn.net/anghlq/article/details/40042057