
1 定义ngx_http_process_user_agent 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_request.c2 作用ngx_http_process_user_agent 函数负责 解析 User-Agent 头部 识别浏览器类型如 MSIE、Chrome、Firefox 等并在请求中设置相应标志位。3 详解1 函数签名staticngx_int_tngx_http_process_user_agent(ngx_http_request_t*r,ngx_table_elt_t*h,ngx_uint_toffset)1 返回值用于统一表示操作状态码。NGX_OKUser-Agent 头部处理成功。NGX_ERROR处理失败。2 函数名命名空间前缀ngx_Nginx 函数的标准前缀。http表明该函数属于 HTTP 模块。process_user_agent直接揭示了函数的功能——处理User-Agent请求头。User-Agent头部是客户端如浏览器标识自身软件类型和版本的信息Nginx 通过解析该头部来识别特定的浏览器以便后续执行针对性的优化或兼容处理。整体语义该函数是 Nginx 中专门用于处理HTTP User-Agent头部的回调。它在请求头解析阶段被调用负责解析该头部的值并将其转化为请求结构体中易于使用的浏览器标识标志位。3 第一个参数ngx_http_request_t *r代表当前正在处理的 HTTP 请求。4 第二个参数ngx_table_elt_t *h该结构体表示一个已解析的 HTTP 头部。5 第三个参数ngx_uint_t offset表示User-Agent字段在结构体ngx_http_headers_in_t中的偏移量。2 逻辑流程1 保存 2 Internet ExplorerMSIE浏览器 3 Opera 浏览器 4 非 MSIEOpera 5 返回成功{u_char*user_agent,*msie;局部变量声明1 保存if(ngx_http_process_header_line(r,h,offset)!NGX_OK){returnNGX_ERROR;}将当前已解析的 HTTP 头部h保存到请求结构体r中正确的位置。2 Internet ExplorerMSIE浏览器/* check some widespread browsers while the header is in CPU cache */user_agenth-value.data;msiengx_strstrn(user_agent,MSIE ,5-1);if(msiemsie7user_agenth-value.len){r-headers_in.msie1;if(msie[6].){switch(msie[5]){case4:case5:r-headers_in.msie61;break;case6:if(ngx_strstrn(msie8,SV1,3-1)NULL){r-headers_in.msie61;}break;}}#if0/* MSIE ignores the SSL close notify alert */if(c-ssl){c-ssl-no_send_shutdown1;}#endif}3 Opera 浏览器if(ngx_strstrn(user_agent,Opera,5-1)){r-headers_in.opera1;r-headers_in.msie0;r-headers_in.msie60;}4 非 MSIEOperaif(!r-headers_in.msie!r-headers_in.opera){if(ngx_strstrn(user_agent,Gecko/,6-1)){r-headers_in.gecko1;}elseif(ngx_strstrn(user_agent,Chrome/,7-1)){r-headers_in.chrome1;}elseif(ngx_strstrn(user_agent,Safari/,7-1)ngx_strstrn(user_agent,Mac OS X,8-1)){r-headers_in.safari1;}elseif(ngx_strstrn(user_agent,Konqueror,9-1)){r-headers_in.konqueror1;}}只有当请求既没有被识别为 MSIE也没有被识别为 Opera 时才进入下面的浏览器检测。检测除 MSIE 和 Opera 之外的四种主流浏览器Gecko例如 Firefox、Chrome、Safari 和 Konqueror。检测通过用户代理字符串中的特征子串完成并设置请求中相应的标识位。5 返回成功returnNGX_OK;}