参考:http://www.imooc.com/wiki/nginxlesson/httpmodule01.html
11个阶段
typedef enum {
NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_TRY_FILES_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE
} ngx_http_phases;
POST_READ 阶段 (预备阶段) POST_READ 阶段是 Nginx 接收到 Http 请求完整头部后的处理阶段,这里主要使用的是 realip 模块获取用户的真实地址,方便后续对该 IP 进行限速或者过滤其请求等。SERVER_REWRITE 和 REWRITE 阶段(重定向) SERVER_REWRITE 和后面的 REWRITE 阶段一般是使用 rewrite 模块修改 Http请求的 uri,实现请求的控制。FIND_CONFIG 阶段 FIND_CONFIG 阶段只是做 location 的匹配项。PREACCESS、ACCESS 和 POST_ACCESS 阶段(权限相关)
PREACCESS 阶段是在连接之前要做的访问控制, 这个阶段有 limit_conn 和 limit_req 等模块工作。ACCESS 阶段是解决用户能不能访问,比如根据用户名、密码限制用户访问(auth_basic 模块)、根据 ip 限制用户访问(access 模块)以及第三方模块认证限制用户的访问(auth_request模块)。POST_ACCESS 是在 ACCESS 之后要做的一些工作。 TRY_FILES 阶段 TRY_FILES 阶段为访问静态文件资源而设置的。有时候又称之为 PRECONTENT 阶段,即在 CONTENT 阶段之前做的事情。主要是 try_files 模块在此阶段工作。CONTENT 最重要的 CONTENT 是处理 Http 请求内容的阶段,大部分 HTTP 模块介入这个阶段,比如 index、autoindex、concat 以及反向代理的模块都是在这里生效的。LOG 阶段 LOG 是处理完请求后的日志记录阶段,如 access_log 模块。
Tips:
所有的 Http请求必须都是从上到下,一个接一个阶段执行的。
涉及到的模块
realip 模块
realip 模块是在 postread 阶段生效的,它的作用是:当本机的 nginx 处于一个反向代理的后端时获取到真实的用户 ip。 如果没有 realip 模块,Nginx 中的 $remote_addr 可能就不是客户端的真实 ip 了,而是代理主机的 ip。
#指定我们信任的后端代理服务器
set_real_ip_from 10.10.10.10;
#为 off 时,nginx 会把 real_ip_header 指定的 Http头中的最后一个 ip 当成真实 ip;
#为 on 时,nginx 会把最后一个不是信任服务器的 ip (前面设置的set_real_ip_from)当成真实 ip。
real_ip_recursive on;
#告诉 nginx 真正的用户 ip 是存在 X-Forwarded-For 请求头中的。
real_ip_header X-Forwarded-For;
rewrite 模块
rewrite 模块的主要功能是改写请求的 uri。 它是 Nginx 默认安装的模块。rewrite 模块会根据正则匹配重写 uri,然后发起内部跳转再匹配 location, 或者直接做30x重定向返回客户端。rewrite 模块的指令有 break, if, return, rewrite, set 等,这些都是我们常用到的。
return 指令
Syntax: return code [text];
# return code URL;
# return URL;
Default: —
Context: server, location, if
return 指令返回后,Http 请求将在 return 的阶段终止,后续阶段将无法进行,所以许多模块得不到执行。
return 200 "hello, world"
rewrite 指令
Syntax: rewrite regex replacement [flag]; Default: – Context: server, location, if
1、将 regex 指定的 url 替换成 replacement 这个新的 url,可以使用正则表达式及变量提取。 2、当 replacement 以 http:// 或者 https:// 或者 $schema 开头,则直接返回 302 重定向 3、替换后的 url 根据 flag 指定的方式进行处理
last: 用 replacement 这个 url 进行新的 location 匹配break: break 指令停止当前脚本指令的执行redirect:返回 302 重定向permanent: 返回 301 重定向
if 指令
Syntax: if (condition) { ... }
Default: —
Context: server, location
if 指令的条件表达式:
检查变量是否为空或者为 0将变量与字符串做匹配,使用 = 或者 !=将变量与正则表达式做匹配:
~ 或者 !~ 大小写敏感~* 或者 !~* 大小写不敏感 检查文件是否存在 -f 或者 !-f检查目录是否存在 -d 或者 !-d检查文件、目录、软链接是否存在 -e !-e是否为可执行文件 -x 或者 !-x
实例
if ($request_medthod = POST){
return 405;
}
if($invalid_refer){
return 403;
}
location 匹配
server {
server_name location.test.com;
listen 8010;
location = / {
return 200 "精确匹配/";
}
location ~* /ma.*ch {
return 200 "正则匹配/ma.*ch";
}
location ~ /mat.*ch {
return 200 "正则匹配/match.*";
}
location = /test {
return 200 "精确匹配/test";
}
location ^~ /test/ {
return 200 "前缀匹配/test";
}
location ~ /test/he*o {
return 200 "正则匹配/test/he*o";
}
location / {
return 200 "通配/";
}
}