- 3.6.2 获取URI和参数
- define NGX_HTTP_UNKNOWN
- define NGX_HTTP_GET
- define NGX_HTTP_HEAD
- define NGX_HTTP_POST
- define NGX_HTTP_PUT
- define NGX_HTTP_DELETE
- define NGX_HTTP_MKCOL
- define NGX_HTTP_COPY
- define NGX_HTTP_MOVE
- define NGX_HTTP_OPTIONS
- define NGX_HTTP_PROPFIND
- define NGX_HTTP_PROPPATCH
- define NGX_HTTP_LOCK
- define NGX_HTTP_UNLOCK
- define NGX_HTTP_TRACE
- define NGX_HTTP_VERSION_9
- define NGX_HTTP_VERSION_10
- define NGX_HTTP_VERSION_11
3.6.2 获取URI和参数
请求的所有信息(如方法、URI、协议版本号和头部等)都可以在传入的ngx_http_request_t类型参数r中取得。ngx_http_request_t结构体的内容很多,本节不会探讨ngx_http_request_t中所有成员的意义(ngx_http_request_t结构体中的许多成员只有HTTP框架才感兴趣,在11.3.1节会更详细的说明),只介绍一下获取URI和参数的方法,这非常简单,因为Nginx提供了多种方法得到这些信息。下面先介绍相关成员的定义。
typedef struct ngx_http_request_s
ngx_http_request_t;
struct ngx_http_request_s{
……
ngx_uint_t
method;
ngx_uint_t
http_version;
ngx_str_t
request_line;
ngx_str_t
uri;
ngx_str_t
args;
ngx_str_t
exten;
ngx_str_t
unparsed_uri;
ngx_str_t
method_name;
ngx_str_t
http_protocol;
u_char
*uri_start;
u_char
*uri_end;
u_char
*uri_ext;
u_char
*args_start;
u_char
*request_start;
u_char
*request_end;
u_char
*method_end;
u_char
*schema_start;
u_char
*schema_end;
……
};
在对一个用户请求行进行解析时,可以得到下列4类信息。
(1)方法名
method的类型是ngx_uint_t(无符号整型),它是Nginx忽略大小写等情形时解析完用户请求后得到的方法类型,其取值范围如下所示。
define NGX_HTTP_UNKNOWN
0x0001
define NGX_HTTP_GET
0x0002
define NGX_HTTP_HEAD
0x0004
define NGX_HTTP_POST
0x0008
define NGX_HTTP_PUT
0x0010
define NGX_HTTP_DELETE
0x0020
define NGX_HTTP_MKCOL
0x0040
define NGX_HTTP_COPY
0x0080
define NGX_HTTP_MOVE
0x0100
define NGX_HTTP_OPTIONS
0x0200
define NGX_HTTP_PROPFIND
0x0400
define NGX_HTTP_PROPPATCH
0x0800
define NGX_HTTP_LOCK
0x1000
define NGX_HTTP_UNLOCK
0x2000
define NGX_HTTP_TRACE
0x4000
当需要了解用户请求中的HTTP方法时,应该使用r->method这个整型成员与以上15个宏进行比较,这样速度是最快的(如果使用method_name成员与字符串做比较,那么效率会差很多),大部分情况下推荐使用这种方式。除此之外,还可以用method_name取得用户请求中的方法名字符串,或者联合request_start与method_end指针取得方法名。method_name是ngx_str_t类型,按照3.2.2节中介绍的方法使用即可。
request_start与method_end的用法也很简单,其中request_start指向用户请求的首地址,同时也是方法名的地址,method_end指向方法名的最后一个字符(注意,这点与其他xxx_end指针不同)。获取方法名时可以从request_start开始向后遍历,直到地址与method_end相同为止,这段内存存储着方法名。
注意 Nginx中对内存的控制相当严格,为了避免不必要的内存开销,许多需要用到的成员都不是重新分配内存后存储的,而是直接指向用户请求中的相应地址。例如,method_name.data、request_start这两个指针实际指向的都是同一个地址。而且,因为它们是简单的内存指针,不是指向字符串的指针,所以,在大部分情况下,都不能将这些u_char*指针当做字符串使用。
(2)URI
ngx_str_t类型的uri成员指向用户请求中的URI。同理,u_char类型的uri_start和uri_end也与request_start、method_end的用法相似,唯一不同的是,method_end指向方法名的最后一个字符,而uri_end指向URI结束后的下一个地址,也就是最后一个字符的下一个字符地址(HTTP框架的行为),这是大部分u_char类型指针对"xxx_start"和"xxx_end"变量的用法。
ngx_str_t类型的extern成员指向用户请求的文件扩展名。例如,在访问"GET/a.txt HTTP/1.1"时,extern的值是{len=3,data="txt"},而在访问"GET/a HTTP/1.1"时,extern的值为空,也就是{len=0,data=0x0}。
uri_ext指针指向的地址与extern.data相同。
unparsed_uri表示没有进行URL解码的原始请求。例如,当uri为"/a b"时,unparsed_uri是"/a%20b"(空格字符做完编码后是%20)。
(3)URL参数
arg指向用户请求中的URL参数。
args_start指向URL参数的起始地址,配合uri_end使用也可以获得URL参数。
(4)协议版本
http_protocol指向用户请求中HTTP的起始地址。
http_version是Nginx解析过的协议版本,它的取值范围如下:
define NGX_HTTP_VERSION_9
9
define NGX_HTTP_VERSION_10
1000
define NGX_HTTP_VERSION_11
1001
建议使用http_version分析HTTP的协议版本。
最后,使用request_start和request_end可以获取原始的用户请求行。