Nginx perl模块处理post请求
接到一个有点无理的需求,需在nginx中对post的请求连接做逻辑重定向(前提是不增加任何后端动态服务)。
那就使用以下nginx的perl模块了(基本用法已在前些文章介绍过,或看nginx wiki的官网)。
编译一下nginx从而带入perl模块。(If you want to enable this module, is necessary to specify --with-http_perl_module when running configure.)
http://wiki.nginx.org/EmbeddedPerlModule 语法
写个对post的处理代码。
vi hpost.pm
package hpost;
use nginx;
sub handler {
my $r = shift;
if ($r->request_method ne "POST") {//如果不是post请求直接过掉不处理。
return DECLINED;
}
if ($r->has_request_body(\&post)) {//存在request body内容,则对body数据进行处理
return OK;
}
return 400;
}
sub post {
my $r = shift;
my $url = "test.php";
#Test Unit---Start 测试单元
#$r->send_http_header;
#$r->print("request_body: \"", $r->request_body, "\"<br/>");
#$r->print("request_body_file: \"", $r->request_body_file, "\"<br/>\n");
#Test Unit---End
if($r->request_body eq "mytest=1") { //可对body内容进行字符串的相关处理--从而进行逻辑相关的工作,这里只做测试
$url = "test.jsp";
}
$r->internal_redirect($url); //根据相关的post数据进行相关的内部重定向
return OK;
}
1;
nginx配置文件中进行调用:
http {
include mime.types;
default_type application/octet-stream;
perl_modules perl/lib; //引入perl相关类库
perl_require hpost.pm; //与nginx.conf配置文件在同一目录下
……
……
……
server {
listen 81;
server_name localhost;
location ~ .*\.jsp$ {
return 400;
}
location ~ .*\.php$ {
return 401;
}
location / {
#root html;
#index index.html index.htm;
#error_page 405 =200 /;
perl hpost::handler;
}
}
}
可用 curl -d "mytest=1" http://127.0.0.1:81/ 进行测试。
使用了perl模块后,尽量避免进行reload操作(kill -HUP pid 对造成使用perl模块nginx内存泄露--存在这个风险)
使用perl的代码越短越好,尽量降低nginx的性能消耗。
---------------------------------------------------------------------------------------------
今天测试将php的处理location 增加内容
location ~ .*\.php {
#return 402;
#proxy_pass http://127.0.0.1:82;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
expires off;
fastcgi_hide_header X-Powered-By;
include fastcgi_params;
fastcgi_pass US_PHP404;
#fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data1/www/itweb_up$fastcgi_script_name;
}
但发现proxy pass后$uri $host $remote_add 等变量都为空,后端php就不能正确获取到
相应的http资源;经过一大堆测试问题还是没解决,决定换一个nginx版本进行测试(原为0.7
更换后为0.8);更换版本后所有变量回来了。
解决变量丢失问题后,又出现一个问题:proxy pass 过去后 uri还是原来用户请求的uri,
不是经过perl 模块更改的uri。
问题解决方法:
在pass 前增加rewrite (.*) $1 break;作用为将内部跳转后所得的uri重写
到proxy pass中。
location ~ .*\.php {
#return 402;
#proxy_pass http://127.0.0.1:82;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
rewrite (.*) $1 break;
expires off;
fastcgi_hide_header X-Powered-By;
include fastcgi_params;
fastcgi_pass US_PHP404;
#fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data1/www/itweb_up$fastcgi_script_name;
}