今天在配置一个站点的时候,出现点击会直接下载PHP文件,从而直接看到PHP源码。在网上搜罗了一番,找到了解决的方法。
在使用rewrite模块进行uri重写时,我们先看一下,rewrite的几个变量。
nginx常用的变量
推荐给nginx安装一个Echo Module,能够非常方便的将我们的请求产生的变量打印出来,nginx选用nginx/1.11.10版本最好,再高一点的版本编译Echo模块会报错。nginx编译成功后添加如下配置。
erver { root /usr/local/nginx/html/; listen 80; server_name test.com; access_log logs/test.com.access.log main; error_log logs/test.error.log; location /path/ { echo "args:" $args; echo "query_string:" $query_string; echo "uri:" $uri; echo "host:" $host; echo "request_filename:" $request_filename; echo "request_uri:" $request_uri; } } curl http://test.com/path/file.php?a=1&b=2 args: a=1&b=2 query_string: a=1&b=2 uri: /path/file.php host: test.com request_filename: /usr/local/nginx/html/path/file.php request_uri: /path/file.php?a=1&b=2
rewrite 指令
语法: rewrite regex replacement [flag]
1,第一个注意的地方就是 regex正则表达是的匹配对象是上文的$uri变量,即不带host和参数的。
rewrite /index.html\?(a=1) index.php?$1 last; curl test.com/index.html?a=1 是匹配不到不会跳转的
2,默认的情况下请求的参数会跟在replacement的后面,如果重定向后的地址想省略原始请求参数在替换的replacement 后面加上?即可
#请求 test.com/post-21.html?a=1&b=2 会被重定向为 test.com/post.php?page=21&a=1&b=2 rewrite /post-(\d+).html /post.php?page=&1 permanent; #如果想去掉重定向后的a=1&b=2参数,在replacement加上? rewrite /post-(\d+).html /post.php?page=&1? permanent;
3,flag:确定重定向的动作
last:停止下面的执行下面的ngx_http_rewrite_module 指令集(包括rewrite,if,return,set这些指令),并开始用重写后新的uri去匹配location。
break:停止下面的执行下面的ngx_http_rewrite_module 指令集。
redirect:服务器发起302临时重定向请求重写的地址
permanent:服务器发起301永久重定向请求重写的地址
last 和 break 当出现在location 之外时,两者的作用是一致的没有任何差异。当出现在location 内部时,两者就存在了差异。
last: 使用了last 指令,rewrite 后会跳出location 作用域,重新开始再走一次刚刚的行为
break: 使用了break 指令,rewrite后不会跳出location 作用域。它的生命也在这个location中终结。
非ngx_http_rewrite_module 任然可以执行,比如proxy_pass ,fastcgi_pass
对用户使用浏览器访问的url来说,last,break都不会改变地址栏的地址。并且不执行后续的rewrite指令,但是last会开始用重写后新的uri去匹配location,如何理解?下面这个例子可以帮助理解。
rewrite /test/.* /index.html break; location /test/ { return 508; } location /break/ { rewrite ^/break/(.*) /test/$1 break; return 402; } location /last/ { rewrite ^/last/(.*) /test/$1 last; return 403; }
请求: http://test.com/break/*
返回:404
请求: http://test.com/last/*
返回:508
请求: http://test.com/test/*
返回:200 (返回index.html)
原因:根据上述内容,break与last都停止处理后续rewrite指令集,不同之处在与last会重新发起新的请求,而break不会。当请求break时,如匹配内容存在的话,可以直接请求成功,返回200;而如果请求内容不存在,则返回404。当请求为last的时候,会对重写的新uri重新发起请求,只是重新查找location匹配,如上例则返回508。
4,location与rewrite一些想法
4.1 $uri 与 $request_filename在last,break改变uri后重新查找匹配是变化,但是$request_uri不会变。接着
上例,在请求: http://test.com/last/* 变成新的uri后重新查找时:
uri: /test/*
request_filename: /usr/local/nginx/html/test/*
request_uri: /last/* (不变)
4.2 location 匹配的是$uri,但是rewrite匹配的是request_uri
4.3 rewrite 匹配的优先级高于location
以下是填的坑!!!
错误写法
#使用此写法由于未添加break,会出现继续请求下载PHP文件。 location ~ \.php$ { fastcgi_pass unix:/dev/shm/php-cgi.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }
更改后,在最后加上break
location ~ \.php$ { fastcgi_pass unix:/dev/shm/php-cgi.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; break; }