在HTTP >= 1.0的版本中,读取处理完HTTP请求行后,紧接着就应该是读取处理HTTP请求头了,Nginx使用ngx_http_process_request_headers来完成这个工作。
/* http/ngx_http_request.c */
/* 处理HTTP请求头
* param r: 待处理的HTTP请求
* return :
*/
static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r)
{
u_char *ua, *user_agent;
size_t len;
ngx_uint_t i;
ngx_http_server_name_t *name;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_loc_conf_t *clcf;
if (r->headers_in.host) {
// 如果r->headers_in的host成员变量不为空
// 从Host头部字段的值中找出主机名
// 由于值中可能包含端口号, 所以需要将端口号排除在外
for (len = 0; len < r->headers_in.host->value.len; len++) {
if (r->headers_in.host->value.data[len] == ':') {
break;
}
}
// len就是主机名的长度
r->headers_in.host_name_len = len;
// 找到基于虚拟主机名称的server配置
name = r->virtual_names->elts;
// 对请求r对应的虚拟主机名称数组进行遍历查找
for (i = 0; i < r->virtual_names->nelts; i++) {
if (r->headers_in.host_name_len != name[i].name.len) {
// 如果长度不等, 那么字符串必不相等, 也就不需要进行字符串比较, 直接跳过
continue;
}
if (ngx_strncasecmp(r->headers_in.host->value.data,
name[i].name.data,
r->headers_in.host_name_len) == 0)
{
// 对虚拟主机名称和Host头部字段提供的主机名进行不区分大小写的字符串比较, 如果相等,
// 那么这就是我们要找的虚拟主机名称
// 记录虚拟主机名称对应的server配置
r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
// 记录请求r的主机名称
r->server_name = &name[i].name;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
r->connection->log->file = clcf->err_log->file;
if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION))
{
r->connection->log->log_level = clcf->err_log->log_level;
}
break;
}
}
if (i == r->virtual_names->nelts) {
// 如果i等于r->virtual_names的元素个数, 说明没有找到匹配的虚拟主机名称
// 获取ngx_http_core_module模块的server层次配置上下文cscf
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
if (cscf->restrict_host_names != NGX_HTTP_RESTRICT_HOST_OFF) {
// 如果restrict_host_names不为off
// 说明这是个无效的主机名, 返回NGX_HTTP_PARSE_INVALID_HOST
return NGX_HTTP_PARSE_INVALID_HO