
1 定义ngx_http_update_location_config 函数 定义在 src/http/ngx_http_core_module.c2 作用ngx_http_update_location_config 函数的作用是 将请求已匹配到的 location 配置应用到请求对象 r 上 使其在运行时生效。3 详解1 函数签名voidngx_http_update_location_config(ngx_http_request_t*r)1. 返回值类型 void函数不返回任何值调用者无法获得操作成功与否的直接反馈。2. 函数名 ngx_http_update_location_configngx_http_表明该函数属于 HTTP 核心模块处理的是 HTTP 协议相关的逻辑。update动词准确地描述了函数的行为——“更新”。它不是“创建”或“初始化”而是将已经确定的 location 配置刷新到请求的运行时状态中。这种更新可能发生多次比如在内部重定向后重新匹配 location 时会再次调用。location_config宾语指明了更新的对象是“location 配置”。在 Nginx 中一个请求在通过FIND_CONFIG阶段匹配到具体的 location 块后就获得了该块下所有模块的配置集合本函数负责把这些静态配置转化为请求动态运行时的参数。整体语义该函数是连接“静态 location 配置”与“动态请求处理”的桥梁。每当请求匹配到一个新的 location都需要调用此函数将对应的配置参数 应用到请求对象上确保后续处理严格遵循该 location 的指令。3. 参数ngx_http_request_t *r指向 当前请求的 上下文结构体2 逻辑流程1 获取配置 2 更新各个配置 2-1 方法限制 2-2 更新连接错误日志仅主请求 2-3 配置 sendfile 2-4 请求体文件存储 2-5 设置请求体单缓冲区标志 2-6 Keep-Alive 2-7 配置 TCP_NOPUSH 2-8 设置内容处理器1 获取配置{ngx_http_core_loc_conf_t*clcf;clcfngx_http_get_module_loc_conf(r,ngx_http_core_module);2 更新各配置2-1 方法限制if(r-methodclcf-limit_except){r-loc_confclcf-limit_except_loc_conf;clcfngx_http_get_module_loc_conf(r,ngx_http_core_module);}r-method是当前 HTTP 请求的方法它以位掩码的形式存储limit_except字段也是一个位掩码记录着被limit_except指令禁止的方法集合。r-method clcf-limit_except是按位与操作。如果结果非零说明当前请求的 HTTP 方法恰好属于被限制的方法之一条件成立。r-loc_conf clcf-limit_except_loc_conf;clcf-limit_except_loc_conf是limit_except指令块内部的独立配置数组指针。这个配置数组包含了limit_except块内所有指令如 allow、deny、以及可能嵌套的其他模块指令所对应的模块配置。这行赋值语句的作用是将请求的配置上下文整体切换为limit_except块内部的配置。这意味着从此刻起所有后续模块看到的配置都将是limit_except块内部定义的规则而不是原 location 块的规则。clcf ngx_http_get_module_loc_conf(r, ngx_http_core_module);由于r-loc_conf刚刚被替换成了新的配置数组原先的 clcf 指针现在可能已经不指向当前生效的核心模块配置了因为配置数组已经改变。根据请求当前最新的r-loc_conf重新取出 HTTP 核心模块在 location 级别的配置并将这个新的指针赋值给 clcf。这样做是为了保证后续代码使用的是limit_except块内部可能重新定义的核心配置。如果不更新 clcf后续代码将继续读取原 location 的核心配置这可能导致行为与预期不符。2-2 更新连接错误日志仅主请求if(rr-main){ngx_set_connection_log(r-connection,clcf-error_log);}2-3 配置 sendfileif((ngx_io.flagsNGX_IO_SENDFILE)clcf-sendfile){r-connection-sendfile1;}else{r-connection-sendfile0;}据操作系统能力和当前 location 的配置决定是否为该连接启用 sendfile 功能。2-4 请求体文件存储if(clcf-client_body_in_file_only){r-request_body_in_file_only1;r-request_body_in_persistent_file1;r-request_body_in_clean_fileclcf-client_body_in_file_onlyNGX_HTTP_REQUEST_BODY_FILE_CLEAN;r-request_body_file_log_levelNGX_LOG_NOTICE;}else{r-request_body_file_log_levelNGX_LOG_WARN;}根据 location 的配置设置请求对象中关于“客户端请求体文件存储”的相关标志和日志级别2-5 设置请求体单缓冲区标志r-request_body_in_single_bufclcf-client_body_in_single_buffer;用于控制后续读取客户端请求体时的内存缓冲策略。2-6 Keep-Aliveif(r-keepalive){只有当r-keepalive当前为 1即初步允许长连接时才进入该代码块进行更细致的检查。如果基础条件就不满足例如客户端明确要求 Connection: close后续检查就没有必要直接跳过。if(clcf-keepalive_timeout0){r-keepalive0;keepalive_timeout对应指令keepalive_timeout的第一个参数。该指令控制服务器在长连接上等待下一个请求的空闲超时时间单位秒内部转换为毫秒。当该值被显式设置为 0 时表示完全禁用长连接。因此如果 location 配置了 keepalive_timeout 0;那么无论客户端如何请求服务器都会在本次响应后关闭连接。动作将 r-keepalive 置为 0本函数后面不再重新设置它后续的连接管理逻辑会据此关闭连接。}elseif(r-connection-requestsclcf-keepalive_requests){r-keepalive0;r-connection-requests记录了当前连接上已经处理过的请求总数。每完成一个请求该计数就会增加。clcf-keepalive_requests对应指令keepalive_requests指定了单个长连接上允许处理的最大请求数。达到该数量后服务器会主动关闭连接强制客户端重新建立连接以平衡负载和资源。比较如果已处理的请求数已经达到或超过了配置的上限则强制关闭长连接。设计意义防止单个连接处理过多请求确保连接能够被及时回收避免一个连接长时间占用服务器资源。}elseif(ngx_current_msec-r-connection-start_timeclcf-keepalive_time){r-keepalive0;ngx_current_msecNginx 缓存的当前时间单位毫秒。r-connection-start_time连接建立时的起始时间毫秒戳。clcf-keepalive_time对应指令keepalive_time指定了一个长连接从建立开始所允许的最大存活时间毫秒。计算当前时间减去连接建立时间即为连接已经存活的总时长。如果超过了keepalive_time则关闭长连接。设计意义限制连接的总生命周期避免连接因频繁复用而长期不释放有助于平滑升级或资源回收}elseif(r-headers_in.msie6r-methodNGX_HTTP_POST(clcf-keepalive_disableNGX_HTTP_KEEPALIVE_DISABLE_MSIE6)){/* * MSIE may wait for some time if an response for * a POST request was sent over a keepalive connection */r-keepalive0;检查是否对 MSIE 6 禁用 Keep-Aliver-headers_in.msie6一个请求标志当 User-Agent 头部表明客户端是旧版 MSIE 6 时被设置为 1。这些旧版本浏览器在处理 Keep-Alive 时存在已知问题。}elseif(r-headers_in.safari(clcf-keepalive_disableNGX_HTTP_KEEPALIVE_DISABLE_SAFARI)){/* * Safari may send a POST request to a closed keepalive * connection and may stall for some time, see * https://bugs.webkit.org/show_bug.cgi?id5760 */r-keepalive0;}}检查是否对 Safari 禁用 Keep-Alive2-7 配置 TCP_NOPUSHif(!clcf-tcp_nopush){/* disable TCP_NOPUSH/TCP_CORK use */r-connection-tcp_nopushNGX_TCP_NOPUSH_DISABLED;}clcf-tcp_nopush就是tcp_nopush指令的值如果配置了tcp_nopush on;它为非零值如果是tcp_nopush off;或者没配置它通常为 0。r-connection-tcp_nopush这个字段位于连接对象上而不是请求对象。它表示当前连接是否启用 TCP 层面的推送优化。Nginx 在发送静态文件时会调用操作系统提供的选项先将数据攒起来等数据块足够大后再一起发送这样可以减少网络上小包的数量提高传输效率。NGX_TCP_NOPUSH_DISABLED这是一个 Nginx 内部定义的特殊常量表示“明确禁用TCP_NOPUSH/TCP_CORK”。把它赋给r-connection-tcp_nopush就相当于告诉后续的发送逻辑不要使用这个优化数据应该尽快发送不要故意延迟等待更多数据。2-8 设置内容处理器if(clcf-handler){r-content_handlerclcf-handler;}}把当前 location 指定的“内容处理器”绑定到请求对象上。