- 3.6 处理用户请求
- define NGX_HTTP_OK
- define NGX_HTTP_CREATED
- define NGX_HTTP_ACCEPTED
- define NGX_HTTP_NO_CONTENT
- define NGX_HTTP_PARTIAL_CONTENT
- define NGX_HTTP_SPECIAL_RESPONSE
- define NGX_HTTP_MOVED_PERMANENTLY
- define NGX_HTTP_MOVED_TEMPORARILY
- define NGX_HTTP_SEE_OTHER
- define NGX_HTTP_NOT_MODIFIED
- define NGX_HTTP_TEMPORARY_REDIRECT
- define NGX_HTTP_BAD_REQUEST
- define NGX_HTTP_UNAUTHORIZED
- define NGX_HTTP_FORBIDDEN
- define NGX_HTTP_NOT_FOUND
- define NGX_HTTP_NOT_ALLOWED
- define NGX_HTTP_REQUEST_TIME_OUT
- define NGX_HTTP_CONFLICT
- define NGX_HTTP_LENGTH_REQUIRED
- define NGX_HTTP_PRECONDITION_FAILED
- define NGX_HTTP_REQUEST_ENTITY_TOO_LARGE
- define NGX_HTTP_REQUEST_URI_TOO_LARGE
- define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE
- define NGX_HTTP_RANGE_NOT_SATISFIABLE
- define NGX_HTTP_CLOSE
- define NGX_HTTP_NGINX_CODES
- define NGX_HTTP_REQUEST_HEADER_TOO_LARGE
- define NGX_HTTPS_CERT_ERROR
- define NGX_HTTPS_NO_CERT
- define NGX_HTTP_TO_HTTPS
- define NGX_HTTP_CLIENT_CLOSED_REQUEST
- define NGX_HTTP_INTERNAL_SERVER_ERROR
- define NGX_HTTP_NOT_IMPLEMENTED
- define NGX_HTTP_BAD_GATEWAY
- define NGX_HTTP_SERVICE_UNAVAILABLE
- define NGX_HTTP_GATEWAY_TIME_OUT
- define NGX_HTTP_INSUFFICIENT_STORAGE
- define NGX_OK
- define NGX_ERROR
- define NGX_AGAIN
- define NGX_BUSY
- define NGX_DONE
- define NGX_DECLINED
- define NGX_ABORT
3.6 处理用户请求
本节介绍如何处理一个实际的HTTP请求。回顾一下上文,在出现mytest配置项时,ngx_http_mytest方法会被调用,这时将ngx_http_core_loc_conf_t结构的handler成员指定为ngx_http_mytest_handler,另外,HTTP框架在接收完HTTP请求的头部后,会调用handler指向的方法。下面看一下handler成员的原型ngx_http_handler_pt:
typedef ngx_int_t(ngx_http_handler_pt)(ngx_http_request_tr);
从上面这段代码可以看出,实际处理请求的方法ngx_http_mytest_handler将接收一个ngx_http_request_t类型的参数r,返回一个ngx_int_t(参见3.2.1节)类型的结果。下面先探讨一下ngx_http_mytest_handler方法可以返回什么,再看一下参数r包含了哪些Nginx已经解析完的用户请求信息。
3.6.1 处理方法的返回值
这个返回值可以是HTTP中响应包的返回码,其中包括了HTTP框架已经在/src/http/ngx_http_request.h文件中定义好的宏,如下所示。
define NGX_HTTP_OK
200
define NGX_HTTP_CREATED
201
define NGX_HTTP_ACCEPTED
202
define NGX_HTTP_NO_CONTENT
204
define NGX_HTTP_PARTIAL_CONTENT
206
define NGX_HTTP_SPECIAL_RESPONSE
300
define NGX_HTTP_MOVED_PERMANENTLY
301
define NGX_HTTP_MOVED_TEMPORARILY
302
define NGX_HTTP_SEE_OTHER
303
define NGX_HTTP_NOT_MODIFIED
304
define NGX_HTTP_TEMPORARY_REDIRECT
307
define NGX_HTTP_BAD_REQUEST
400
define NGX_HTTP_UNAUTHORIZED
401
define NGX_HTTP_FORBIDDEN
403
define NGX_HTTP_NOT_FOUND
404
define NGX_HTTP_NOT_ALLOWED
405
define NGX_HTTP_REQUEST_TIME_OUT
408
define NGX_HTTP_CONFLICT
409
define NGX_HTTP_LENGTH_REQUIRED
411
define NGX_HTTP_PRECONDITION_FAILED
412
define NGX_HTTP_REQUEST_ENTITY_TOO_LARGE
413
define NGX_HTTP_REQUEST_URI_TOO_LARGE
414
define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE
415
define NGX_HTTP_RANGE_NOT_SATISFIABLE
416
/The special code to close connection without any response/
define NGX_HTTP_CLOSE
444
define NGX_HTTP_NGINX_CODES
494
define NGX_HTTP_REQUEST_HEADER_TOO_LARGE
494
define NGX_HTTPS_CERT_ERROR
495
define NGX_HTTPS_NO_CERT
496
define NGX_HTTP_TO_HTTPS
497
define NGX_HTTP_CLIENT_CLOSED_REQUEST
499
define NGX_HTTP_INTERNAL_SERVER_ERROR
500
define NGX_HTTP_NOT_IMPLEMENTED
501
define NGX_HTTP_BAD_GATEWAY
502
define NGX_HTTP_SERVICE_UNAVAILABLE
503
define NGX_HTTP_GATEWAY_TIME_OUT
504
define NGX_HTTP_INSUFFICIENT_STORAGE
507
注意 以上返回值除了RFC2616规范中定义的返回码外,还有Nginx自身定义的HTTP返回码。例如,NGX_HTTP_CLOSE就是用于要求HTTP框架直接关闭用户连接的。
在ngx_http_mytest_handler的返回值中,如果是正常的HTTP返回码,Nginx就会按照规范构造合法的响应包发送给用户。例如,假设对于PUT方法暂不支持,那么,在处理方法中发现方法名是PUT时,返回NGX_HTTP_NOT_ALLOWED,这样Nginx也就会构造类似下面的响应包给用户。
http/1.1 405 Not Allowed
Server:nginx/1.0.14
Date:Sat,28 Apr 2012 06:07:17 GMT
Content-Type:text/html
Content-Length:173
Connection:keep-alive
<html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx/1.0.14</center>
</body>
</html>
在处理方法中除了返回HTTP响应码外,还可以返回Nginx全局定义的几个错误码,包括:
define NGX_OK
0
define NGX_ERROR
-1
define NGX_AGAIN
-2
define NGX_BUSY
-3
define NGX_DONE
-4
define NGX_DECLINED
-5
define NGX_ABORT
-6
这些错误码对于Nginx自身提供的大部分方法来说都是通用的。所以,当我们最后调用ngx_http_output_filter(参见3.7节)向用户发送响应包时,可以将ngx_http_output_filter的返回值作为ngx_http_mytest_handler方法的返回值使用。例如:
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t*r)
{
……
ngx_int_t rc=ngx_http_send_header(r);
if(rc==NGX_ERROR||rc>NGX_OK||r->header_only){
return rc;
}
return ngx_http_output_filter(r,&out);
}
当然,直接返回以上7个通用值也是可以的。在不同的场景下,这7个通用返回值代表的含义不尽相同。在mytest的例子中,HTTP框架在NGX_HTTP_CONTENT_PHASE阶段调用ngx_http_mytest_handler后,会将ngx_http_mytest_handler的返回值作为参数传给ngx_http_finalize_request方法,如下所示。
if(r->content_handler){
r->write_event_handler=ngx_http_request_empty_handler;
ngx_http_finalize_request(r,r->content_handler(r));
return NGX_OK;
}
上面的r->content_handler会指向ngx_http_mytest_handler处理方法。也就是说,事实上ngx_http_finalize_request决定了ngx_http_mytest_handler如何起作用。本章不探讨ngx_http_finalize_request的实现(详见11.10节),只简单地说明一下4个通用返回码,另外,在11.10节中介绍这4个返回码引发的Nginx一系列动作。
❑NGX_OK:表示成功。Nginx将会继续执行该请求的后续动作(如执行subrequest或撤销这个请求)。
❑NGX_DECLINED:继续在NGX_HTTP_CONTENT_PHASE阶段寻找下一个对于该请求感兴趣的HTTP模块来再次处理这个请求。
❑NGX_DONE:表示到此为止,同时HTTP框架将暂时不再继续执行这个请求的后续部分。事实上,这时会检查连接的类型,如果是keepalive类型的用户请求,就会保持住HTTP连接,然后把控制权交给Nginx。这个返回码很有用,考虑以下场景:在一个请求中我们必须访问一个耗时极长的操作(比如某个网络调用),这样会阻塞住Nginx,又因为我们没有把控制权交还给Nginx,而是在ngx_http_mytest_handler中让Nginx worker进程休眠了(如等待网络的回包),所以,这就会导致Nginx出现性能问题,该进程上的其他用户请求也得不到响应。可如果我们把这个耗时极长的操作分为上下两个部分(就像Linux内核中对中断处理的划分),上半部分和下半部分都是无阻塞的(耗时很少的操作),这样,在ngx_http_mytest_handler进入时调用上半部分,然后返回NGX_DONE,把控制交还给Nginx,从而让Nginx继续处理其他请求。在下半部分被触发时(这里不探讨具体的实现方式,事实上使用upstream方式做反向代理时用的就是这种思想),再回调下半部分处理方法,这样就可以保证Nginx的高性能特性了。如果需要彻底了解NGX_DONE的意义,那么必须学习第11章内容,其中还涉及请求的引用计数内容。
❑NGX_ERROR:表示错误。这时会调用ngx_http_terminate_request终止请求。如果还有POST子请求,那么将会在执行完POST请求后再终止本次请求。