ngx_http_read_client_request_body
HTTP包体的长度有可能非常大,如果试图一次性调用并读取完所有的包体,那么多半会阻塞Nginx进程。HTTP框架提供了一种方法来异步地接收包体:
ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler);接收完请求的包体后,可以在r->request_body->temp_file->file中获取临时文件(假定将r->request_body_in_file_only标志位设为1,那就一定可以在这个变量获取到包体。更复杂的接收包体的方式本节暂不讨论)。file是一个ngx_file_t类型。这里,我们可以从r->request_body->temp_file->file.name中获取Nginx接收到的请求包体所在文件的名称(包括路径)。
返回值的意义
每个阶段都有一个与之相关的handler的列表。一旦把handler注册到对应的阶段,那么handler就会返回某个下面的值:
NGX_OK:请求已经成功处理,请求将会传到下一个阶段。
NGX_DECLINED:请求需要被转发到本阶段的下一个handler
NGX_AGAIN,NGX_DONE:请求已经被正确处理,同时请求被挂起,直到某个事件(子请求结束、socket可写或超时等)到来,handler才会再次被调用。
//函数功能:解析请求行。
static void ngx_http_process_request_line(ngx_event_t *rev)
{
。。。
rc = NGX_AGAIN;
for ( ;; ) {
if (rc == NGX_AGAIN) { // NO.1
n = ngx_http_read_request_header(r);
//recv()读取请求头信息
if (n == NGX_AGAIN || n == NGX_ERROR) {
return;
}
}
//记录请求行中的请求方法(Method),请求uri以及http协议版本在缓冲区中的起始位置
rc = ngx_http_parse_request_line(r, r->header_in);
if (rc == NGX_OK) {
…
c->log->action = "reading client request headers";
rev->handler = ngx_http_process_request_headers;
ngx_http_process_request_headers(rev);
return;
}
。。。
}
}
//函数功能:处理HTTP请求头。
static void ngx_http_process_request_headers(ngx_event_t *rev)
{
。。。
if (rev->timedout) { // 是否超时
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
c->timedout = 1;
ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
return;
}
。。。
rc = NGX_AGAIN;
for ( ;; ) {
if (rc == NGX_AGAIN) {
if (r->header_in->pos == r->header_in->end) { //一般不需要
rv = ngx_http_alloc_large_header_buffer(r, 0);
。。。
}
n = ngx_http_read_request_header(r); //快速返回了,因为已经读过
if (n == NGX_AGAIN || n == NGX_ERROR) {
return;
}
}
rc = ngx_http_parse_header_line(r, r->header_in,
cscf->underscores_in_headers); //解析HTTP头部
if (rc == NGX_OK) {
if (r->invalid_header && cscf->ignore_invalid_headers) {
。。。
//以key 和value的格式保存HTTP头
h = ngx_list_push(&r->headers_in.headers); //ngx_http_headers_in_t ,存放key,value
if (h == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
h->hash = r->header_hash;
h->key.len = r->header_name_end - r->header_name_start;
h->key.data = r->header_name_start; // "User-Agent",host
h->key.data[h->key.len] = '\0';
h->value.len = r->header_end - r->header_start;
h->value.data = r->header_start;
。。。
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { //检验函数
return;
}
continue;
}
if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
/* a whole header has been parsed successfully */
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http header done");
r->request_length += r->header_in->pos - r->header_in->start;
r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
rc = ngx_http_process_request_header(r); //检验头信息如1.1协议需要host信息?
if (rc != NGX_OK) {
return;
}
ngx_http_process_request(r);
return;
}
。。。。
}
}
//函数功能:处理请求。
static voidngx_http_process_request(ngx_http_request_t *r)
{
。。。
if (c->read->timer_set) { // 超时,过了一会儿,就在这里了
ngx_del_timer(c->read); //here
}
c->read->handler = ngx_http_request_handler;
c->write->handler = ngx_http_request_handler;
r->read_event_handler = ngx_http_block_reading;
ngx_http_handler(r); //核心是ngx_http_core_run_phases,进入各阶段处理函数
ngx_http_run_posted_requests(c);
}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务