Nginx除了能对UA进行处理,乃能对特殊的Query String进行处理。
最典型的应用就是,location进行路径匹配的时候,是没办法是用正则表达一起捕获这个路径和querstring的。那么我想真的URL里面的Query String进行不同的rewrite,应该如何处理呢?答案就是$arg变量。
Nginx里面$query_string 与$args相同,存储了所提交的所有$query_string
比如&p=2887&q=test
如果想要在nginx里面单独访问这些变量。可以这样
比如$p变量可以这样访问 $arg_p
下面是用这样一个实例讲述一下。
我准备停用WAP-T-WAP插件,但是发现Google对我站点的wap收录比较多,为了保留SEO,对wap目录进行301重定向。
要求是 如果请求中的$query_string包含"q=数字",301重新定向到首页交由index.php处理。
否则只是301重新定向到首页。
1 2 3 4 5 6 7 8 9 |
location ~* ^/wap/ { # if ( $http_user_agent ~* "(MSIE|bot|Spider|Slurp)" ) { # } if ($args ~* "p=\d+$") { rewrite ^ $scheme://$host/?p=$arg_p? permanent; } #Rewrite 后面带一个?表示在重定向中使用query_tring rewrite ^/(.*)$ $scheme://$host/? permanent; } |
效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
curl --head https://ihipop.info/wap/index-wap2.php?p=2 -k HTTP/1.1 301 Moved Permanently Server: nginx/0.8.54 Date: Tue, 10 Jan 2012 08:31:40 GMT Content-Type: text/html Content-Length: 185 Connection: keep-alive Location: https://ihipop.info/?p=2 curl --head https://ihipop.info/wap/index-wap2.php?p=test -k HTTP/1.1 301 Moved Permanently Server: nginx/0.8.54 Date: Tue, 10 Jan 2012 08:31:36 GMT Content-Type: text/html Content-Length: 185 Connection: keep-alive Location: https://ihipop.info/ |
关于rewrite后面的问号,其作用是去除后面的qrerystring,不加?的话,就是这样的
比如原来的query_string是p=2887,不加问号的话 是重新定向到
http://ihipop.info/?2887&p=2887
多了一个&p=2887这样产生的 URI 不是很美观。
详见Remove query string on rewrite :http://forum.nginx.org/read.php?2,118933,118933
Nginx 内置变量表( ngx_http_variables) | ||
变量名 | 版本 | 简要说明 |
$args | 1.0.8 | 请求中的参数; |
$binary_remote_addr | 1.0.8 | 远程地址的二进制表示 |
$body_bytes_sent | 1.0.8 | 已发送的消息体字节数 |
$content_length | 1.0.8 | HTTP请求信息里的"Content-Length"; |
$content_type | 1.0.8 | 请求信息里的"Content-Type"; |
$document_root | 1.0.8 | 针对当前请求的根路径设置值; |
$document_uri | 1.0.8 | 与$uri相同; |
$host | 1.0.8 | 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名; |
$hostname | 1.0.8 | |
$http_cookie | 1.0.8 | cookie 信息 |
$http_post | 1.0.8 | |
$http_referer | 1.0.8 | 引用地址 |
$http_user_agent | 1.0.8 | 客户端代理信息 |
$http_via | 1.0.8 | 最后一个访问服务器的Ip地址。 |
$http_x_forwarded_for | 1.0.8 | 相当于网络访问路径。 |
$is_args | 1.0.8 | |
$limit_rate | 1.0.8 | 对连接速率的限制; |
$nginx_version | 1.0.8 | |
$pid | 1.0.8 | |
$query_string | 1.0.8 | 与$args相同; |
$realpath_root | 1.0.8 | |
$remote_addr | 1.0.8 | 客户端地址; |
$remote_port | 1.0.8 | 客户端端口号; |
$remote_user | 1.0.8 | 客户端用户名,认证用; |
$request | 1.0.8 | 用户请求 |
$request_body | 1.0.8 | |
$request_body_file | 1.0.8 | 发往后端的本地文件名称 |
$request_completion | 1.0.8 | |
$request_filename | 1.0.8 | 当前请求的文件路径名 |
$request_method | 1.0.8 | 请求的方法,比如"GET"、"POST"等; |
$request_uri | 1.0.8 | 请求的URI,带参数; |
$scheme | 1.0.8 | 所用的协议,比如http或者是https,比如rewrite^(.+)$$scheme://example.com$1redirect; |
$sent_http_cache_control | 1.0.8 | |
$sent_http_connection | 1.0.8 | |
$sent_http_content_length | 1.0.8 | |
$sent_http_content_type | 1.0.8 | |
$sent_http_keep_alive | 1.0.8 | |
$sent_http_last_modified | 1.0.8 | |
$sent_http_location | 1.0.8 | |
$sent_http_transfer_encoding | 1.0.8 | |
$server_addr | 1.0.8 | 服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费); |
$server_name | 1.0.8 | 请求到达的服务器名; |
$server_port | 1.0.8 | 请求到达的服务器端口号; |
$server_protocol | 1.0.8 | 请求的协议版本,"HTTP/1.0"或"HTTP/1.1"; |
$uri | 1.0.8 | 请求的URI,可能和最初的值有不同,比如经过重定向之类的。 |
[download id="33" format="2"]
楼主 我想问下 下面代码nginx 如何写伪静态
伪静态后地址
http://www.rekfan.com/index.php?js/view/1170.html
动态地址
http://www.rekfan.com/index.php?m=js&c=index&a=init&jid=1170
问号不好处理呀 !
用
location / {
try_files $uri $uri/ /index.php?$args;
}
看你的代码应该都是mcv的框架写的。大多数这样的框架会自动转换path info
比如index.php/js/view/1170.html
我是搜nginx $args过来的,博主的博客部分已在墙外了啊。
我这有个问题,没搞定,想请教一下,嘿嘿。
我想把链接 .com/?id=xxx 重写成.com/entries/xxx/ 使用rewrite ^/entries/(\d+)/$ /?id=$1 last;搞定了。
然后想把Google已经收录的.com/?id=xxx 重定向到 .com/entries/xxx/ 使用
if ($query_string ~* "id=(\d+)$") {
set $id $1;
rewrite / /entries/$id/? permanent;
}
也可以实现了。
但是这两条不管那个放在前面都会出现重定向循环,不知道该怎么解决。
需要将 .com/?id=xxx 重写成.com/entries/xxx/ 并且重定向到.com/entries/xxx/
在墙外?啥意思?我打开正常啊
另外你这个就是一个死循环嚒。
第一个rewrite就会产生一个$query_string包含"id=(\d+)$"的请求
第二个又会匹配到第一个去
你这样 你把第二个放到第一个,然后你把原来的第一个里面的last改成break试试
哇,神了。按你说的改完真好屎了。谢谢。
昨天打开这个页面样式什么的都没有,挂了代理才显示全。我就以为是被墙了。