nginx替换响应头(重点:如何在替换时加上if判断)
在实现微信小程序内嵌非业务域名时,通过nginx做镜像网站绕过小程序业务域名检测,但有一些表单页面提交后会返回一个302状态,由响应头Location的值决定提交成功后的跳转地址。那么问题来了,这个地址也是属于非业务域名,这个时候我们就需要将这个响应头也替换掉,那么nginx如何替换响应头呢,请看下面教程:
一、安装使用ngx_headers_more模块定制响应头:
ngx_headers_more 用于添加、设置和清除输入和输出的头信息。nginx没有内置该模块,需要另行添加。
(1)下载地址:https://github.com/openresty/headers-more-nginx-module/tags
(2)平滑升级nginx(参考上篇为nginx平滑添加SSL模块的文章:http://www.cnblogs.com/kenwar/p/8295907.html 添加参数add-module=/解压缩后文件路径)
(3)指令说明(我这边只用到设置响应头的指令,所以只介绍一个指令,如有兴趣请自行查找其使用说明):
more_set_headers
语法:more_set_headers [-t <content-type list>]... [-s <status-code list>]... <new-header>...
默认值:no
配置段:http, server, location, location if
阶段:输出报头过滤器
替换(如有)或增加(如果不是所有)指定的输出头时响应状态代码与-s选项相匹配和响应的内容类型的-t选项指定的类型相匹配的。
如果没有指定-s或-t,或有一个空表值,无需匹配。因此,对于下面的指定,任何状态码和任何内容类型都讲设置。
more_set_headers "Server: my_server"; more_set_headers "Server: my_server";
具有相同名称的响应头总是覆盖。如果要添加头,可以使用标准的add_header指令代替。
单个指令可以设置/添加多个输出头。如:
more_set_headers 'Foo: bar' 'Baz: bah'; more_set_headers 'Foo: bar' 'Baz: bah';
在单一指令中,选项可以多次出现,如:
more_set_headers -s 404 -s '500 503' 'Foo: bar'; more_set_headers -s 404 -s '500 503' 'Foo: bar';
等同于:
more_set_headers -s '404 500 503' 'Foo: bar'; more_set_headers -s '404 500 503' 'Foo: bar';
新的头是下面形式之一:
Name: Value
Name:
Name
最后两个有效清除的头名称的值。Nginx的变量允许是头值,如:
set $my_var "dog"; more_set_headers "Server: $my_var"; set $my_var "dog"; more_set_headers "Server: $my_var";
注意:more_set_headers允许在location的if块中,但不允许在server的if块中。下面的配置就报语法错误:
# This is NOT allowed! server { if ($args ~ 'download') { more_set_headers 'Foo: Bar'; } ... }
二、简单替换302状态下的响应头Location:
location /{ more_set_header "Location" "https://www.demo.com/xxx/index.html" }
三、(重点)使用正则表达式有选择的替换Location:
我们如果需要根据响应头里的内容来选择何种替换方式,该怎么做?
需求:在location中判断响应头Location字段如果值为a(假设值),则将Location设置为b,其他忽略
(1)初步尝试:
location /{ if($upstream_http_Location ~ a){ more_set_header "Location" "https://www.demo.com/xxx/index.html" } }
然而这里的if怎么都进不去,通过google得知是因为,在请求传递到后端之前,if就已经判断了,所以$upstream_http_Location是没有值的,这里可以使用一个map来有根据响应头的值有条件的执行操作:
map $upstream_http_Location $location{ ~a https://www.democom/xxx/success.html; default $upstream_http_Location; } server{ listen 80; listen 443 ssl; ssl_certificate /usr/local/nginx/ssl/www3.xiaolintong.net.cn/www3.xiaolintong.net.cn-ca-bundle.crt; ssl_certificate_key /usr/local/nginx/ssl/www3.xiaolintong.net.cn/www3.xiaolintong.net.cn.key; autoindex on; #开启读取非nginx标准的用户自定义header(开启header的下划线支持) underscores_in_headers on; server_name xxxxxxxxx; access_log /usr/local/nginx/logs/access.log combined; index index.html index.htm index.jsp index.php; #error_page 404 /404.html; ........ location ^~/f/ { more_set_headers -s '302' 'Location $location'; } ....... }
这里仅提供一个思路,请根据自己的需求灵活的使用map