HTTP 请求行正确处理完成后,针对 HTTP/1.0 及以上版本紧接着要做的就是请求 HEADER 的处理与解析了
/**
* 用于处理http的header数据
* 请求头:
* Host: localhost
* User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
* Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
* Accept-Language: zh-cn,zh;q=0.5
* Accept-Encoding: gzip, deflate
*
copy from https://techlog.cn/article/list
/*
用于处理http的header数据
GET /sample.jsp HTTP/1.1
* 请求头:
* Host: localhost
* User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
* Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
* Accept-Language: zh-cn,zh;q=0.5
* Accept-Encoding: gzip, deflate
*/ //解析上面的GET /sample.jsp HTTP/1.1以外的配置
ngx_http_parse_request_line解析请求行, ngx_http_process_request_headers(ngx_http_parse_header_line)解析头部行(请求头部)
接收包体ngx_http_read_client_request_body
static void
ngx_http_process_request_headers(ngx_event_t *rev)
{
u_char *p;
size_t len;
ssize_t n;
ngx_int_t rc, rv;
ngx_table_elt_t *h;
ngx_connection_t *c;
ngx_http_header_t *hh;
ngx_http_request_t *r;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_main_conf_t *cmcf;
c = rev->data;
r = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"http process request header line");
if (rev->timedout) {//如果tcp连接建立后,等了client_header_timeout秒一直没有收到客户端的数据包过来,则关闭连接
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;
}
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
rc = NGX_AGAIN;
for ( ;; ) {
if (rc == NGX_AGAIN) {
if (r->header_in->pos == r->header_in->end) {
//说明header_in空间已经用完了,无法继续存储recv的数据,则重新分配大空间-------buf太小,则扩大buf */
rv = ngx_http_alloc_large_header_buffer(r, 0);
if (rv == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
if (rv == NGX_DECLINED) {
p = r->header_name_start;
r->lingering_close = 1;
if (p == NULL) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent too large request");
ngx_http_finalize_request(r,
NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
return;
}
len = r->header_in->end - p;
if (len > NGX_MAX_ERROR_STR - 300) {
len = NGX_MAX_ERROR_STR - 300;
}
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent too long header line: "%*s..."",
len, r->header_name_start);
ngx_http_finalize_request(r,
NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
return;
}
}
//这里至少读一次----------读取请求数据 调用方法:os/ngx_recv.c文件夹中的 ngx_unix_recv */
n = ngx_http_read_request_header(r); //说明内存中的数据还没有读完,需要读完后继续解析
if (n == NGX_AGAIN || n == NGX_ERROR) {
return;
}
}
/* the host header could change the server configuration context */
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
/* 处理HTTP请求头数据/* 处理HTTP请求头数据 **/
rc = ngx_http_parse_header_line(r, r->header_in,
cscf->underscores_in_headers);
/* 处理成功,则继续解析下一个http header数据 */
if (rc == NGX_OK) {
r->request_length += r->header_in->pos - r->header_name_start; //request_length增加一行字符长度
if (r->invalid_header && cscf->ignore_invalid_headers) {
/* there was error while a header line parsing */
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent invalid header line: "%*s"",
r->header_end - r->header_name_start,
r->header_name_start);
continue;
}
/* a header line has been parsed successfully */
/* 解析的头不会KEY:VALUE存入到headers_in中 */
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
h->hash = r->header_hash;
//拷贝name:value中的name到key中,name后面的冒号被用 替换了
h->key.len = r->header_name_end - r->header_name_start;
h->key.data = r->header_name_start;
h->key.data[h->key.len] = '