您的位置:首页 > 健康 > 养生 > 装修设计师要学多久_uiapp界面设计模板_微信营销的方法和技巧_西安seo招聘

装修设计师要学多久_uiapp界面设计模板_微信营销的方法和技巧_西安seo招聘

2025/4/2 3:57:32 来源:https://blog.csdn.net/weixin_41812346/article/details/146526626  浏览:    关键词:装修设计师要学多久_uiapp界面设计模板_微信营销的方法和技巧_西安seo招聘
装修设计师要学多久_uiapp界面设计模板_微信营销的方法和技巧_西安seo招聘

定义在 src\http\ngx_http_core_module.c

static char *
ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ngx_http_core_loc_conf_t *clcf = conf;u_char                            *p;ngx_int_t                          overwrite;ngx_str_t                         *value, uri, args;ngx_uint_t                         i, n;ngx_http_err_page_t               *err;ngx_http_complex_value_t           cv;ngx_http_compile_complex_value_t   ccv;if (clcf->error_pages == NULL) {clcf->error_pages = ngx_array_create(cf->pool, 4,sizeof(ngx_http_err_page_t));if (clcf->error_pages == NULL) {return NGX_CONF_ERROR;}}value = cf->args->elts;i = cf->args->nelts - 2;if (value[i].data[0] == '=') {if (i == 1) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid value \"%V\"", &value[i]);return NGX_CONF_ERROR;}if (value[i].len > 1) {overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);if (overwrite == NGX_ERROR) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid value \"%V\"", &value[i]);return NGX_CONF_ERROR;}} else {overwrite = 0;}n = 2;} else {overwrite = -1;n = 1;}uri = value[cf->args->nelts - 1];ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));ccv.cf = cf;ccv.value = &uri;ccv.complex_value = &cv;if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {return NGX_CONF_ERROR;}ngx_str_null(&args);if (cv.lengths == NULL && uri.len && uri.data[0] == '/') {p = (u_char *) ngx_strchr(uri.data, '?');if (p) {cv.value.len = p - uri.data;cv.value.data = uri.data;p++;args.len = (uri.data + uri.len) - p;args.data = p;}}for (i = 1; i < cf->args->nelts - n; i++) {err = ngx_array_push(clcf->error_pages);if (err == NULL) {return NGX_CONF_ERROR;}err->status = ngx_atoi(value[i].data, value[i].len);if (err->status == NGX_ERROR || err->status == 499) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid value \"%V\"", &value[i]);return NGX_CONF_ERROR;}if (err->status < 300 || err->status > 599) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"value \"%V\" must be between 300 and 599",&value[i]);return NGX_CONF_ERROR;}err->overwrite = overwrite;if (overwrite == -1) {switch (err->status) {case NGX_HTTP_TO_HTTPS:case NGX_HTTPS_CERT_ERROR:case NGX_HTTPS_NO_CERT:case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:err->overwrite = NGX_HTTP_BAD_REQUEST;}}err->value = cv;err->args = args;}return NGX_CONF_OK;
}

ngx_http_core_error_page 函数是 Nginx 中用于解析和配置自定义错误页面的核心函数


    if (clcf->error_pages == NULL) {clcf->error_pages = ngx_array_create(cf->pool, 4,sizeof(ngx_http_err_page_t));if (clcf->error_pages == NULL) {return NGX_CONF_ERROR;}}

检查当前配置块(clcf)的 error_pages 数组是否已初始化

如果 error_pages 未初始化(NULL),说明这是第一次为此配置块设置错误页面规则,需要创建数组

ngx_http_core_loc_conf_t-CSDN博客

clcf->error_pages 是 Nginx 中 ngx_http_core_loc_conf_t 结构体的一个字段,用于存储当前配置块中定义的所有 error_page 规则

ngx_http_err_page_t-CSDN博客

每个元素是一个 ngx_http_err_page_t 结构体,记录了以下信息:

  • 错误状态码 (如 404500
  • 重写后的响应状态码 
  • 目标 URI 
  • URI 的查询参数 
    value = cf->args->elts;i = cf->args->nelts - 2;if (value[i].data[0] == '=') {if (i == 1) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid value \"%V\"", &value[i]);return NGX_CONF_ERROR;}if (value[i].len > 1) {overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);if (overwrite == NGX_ERROR) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid value \"%V\"", &value[i]);return NGX_CONF_ERROR;}} else {overwrite = 0;}n = 2;} else {overwrite = -1;n = 1;}
value = cf->args->elts;

获取当前配置指令的所有参数列表

i = cf->args->nelts - 2;

cf->args->nelts 是参数总数

i 的值为 参数总数 - 2,即最后一个参数前的参数索引

此时 i=4

if (value[i].data[0] == '=') {

检查当前参数是否以 = 开头(即是否为覆盖状态码的语法)

  • 若参数以 = 开头(如 =200),则进入覆盖状态码的解析流程。
  • 否则,跳转到 else 分支,表示不覆盖状态码

此时条件不成立

else { overwrite = -1; n = 1; }

处理不覆盖状态码的情况

overwrite = -1:表示不覆盖原始错误码

n = 1:仅需跳过 uri 参数,后续处理所有错误码参数

    uri = value[cf->args->nelts - 1];ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));ccv.cf = cf;ccv.value = &uri;ccv.complex_value = &cv;
uri = value[cf->args->nelts - 1];

提取 error_page 指令的最后一个参数(即目标 URI)


ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));

初始化 ngx_http_compile_complex_value_t 结构体

ngx_http_compile_complex_value_t-CSDN博客


ccv.cf = cf;

将当前配置解析上下文(cf)关联到编译器结构体

  • ccv 是编译复杂值的上下文结构体。
  • cf 包含配置解析的内存池、日志等关键信息

ccv.value = &uri;
  • uri 是用户配置的字符串(如 "/404.html"
  • ccv.value 是编译器的输入参数。

ccv.complex_value = &cv;

  • cvngx_http_complex_value_t 类型的变量,用于存储编译后的动态值。
  • ccv.complex_value 是编译器的输出目标。
    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {return NGX_CONF_ERROR;}

调用 ngx_http_compile_complex_value 函数,并检查返回值

error_page 的 URI 可能包含变量(如 /error_$status.html),需要通过 ngx_http_compile_complex_value 函数将其编译为运行时可解析的结构体。若编译失败,需终止配置解析

ngx_http_compile_complex_value-CSDN博客

ngx_str_null(&args);

 将 args 字符串(ngx_str_t 类型)初始化为空字符串

    if (cv.lengths == NULL && uri.len && uri.data[0] == '/') {p = (u_char *) ngx_strchr(uri.data, '?');if (p) {cv.value.len = p - uri.data;cv.value.data = uri.data;p++;args.len = (uri.data + uri.len) - p;args.data = p;}}
if (cv.lengths == NULL && uri.len && uri.data[0] == '/') {

检查 URI 是否为静态路径(无变量)且以 / 开头

  • cv.lengths == NULL:表示 URI 不含变量(如 $variable),是纯静态字符串。
  • uri.len:确保 URI 非空。
  • uri.data[0] == '/':URI 必须以 / 开头(本地路径)。

此时 条件成立

p = (u_char *) ngx_strchr(uri.data, '?');

在 URI 中查找 ? 的位置,用于分割路径和查询参数 

此时 p=NULL

    for (i = 1; i < cf->args->nelts - n; i++) {err = ngx_array_push(clcf->error_pages);if (err == NULL) {return NGX_CONF_ERROR;}

 

for (i = 1; i < cf->args->nelts - n; i++) {

遍历用户配置的错误码参数

i = 1:从第二个参数开始(第一个参数是 error_page 指令本身)

cf->args->nelts:配置指令的总参数个数

n:表示后续参数占用的槽位数

循环条件 i < 总参数数 - n,即处理所有状态码参数,跳过覆盖码和 URI 参数。

  • 示例
    • 配置 error_page 404 500 =200 /error.html;
      • cf->args->nelts = 5(参数列表:error_page, 404, 500, =200, /error.html)。
      • n = 2(覆盖码 =200 和 URI /error.html 占用 2 个槽位)。
      • 循环次数:i < 5 - 2i < 3i=1(处理 404)、i=2(处理 500)。

err = ngx_array_push(clcf->error_pages);

为当前错误码分配一个 ngx_http_err_page_t 结构,并添加到 clcf->error_pages 数组

ngx_http_err_page_t-CSDN博客


 

        err->status = ngx_atoi(value[i].data, value[i].len);if (err->status == NGX_ERROR || err->status == 499) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid value \"%V\"", &value[i]);return NGX_CONF_ERROR;}if (err->status < 300 || err->status > 599) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"value \"%V\" must be between 300 and 599",&value[i]);return NGX_CONF_ERROR;}

 

err->status = ngx_atoi(value[i].data, value[i].len);

将用户配置的字符串形式的状态码(如 "404")转换为整数

if (err->status == NGX_ERROR || err->status == 499) {

验证状态码的合法性

NGX_ERROR:表示字符串转换失败

499:Nginx 内部使用的特殊状态码(客户端主动关闭连接),禁止用户配置

if (err->status < 300 || err->status > 599) {

确保状态码在 HTTP 标准的错误码范围内。

HTTP 状态码规则:

3xx:重定向。

4xx:客户端错误。

5xx:服务器端错误。

Nginx 要求 error_page 仅处理 300-599 的状态码。

禁止配置非错误码(如 200 OK)或无效范围值。

        err->overwrite = overwrite;if (overwrite == -1) {switch (err->status) {case NGX_HTTP_TO_HTTPS:case NGX_HTTPS_CERT_ERROR:case NGX_HTTPS_NO_CERT:case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:err->overwrite = NGX_HTTP_BAD_REQUEST;}}err->value = cv;err->args = args;

 

err->overwrite = overwrite;

将用户配置的覆盖码(或默认值 -1)赋值给错误页结构体

if (overwrite == -1) {

当用户未显式指定覆盖码时,检查是否需要为某些特殊状态码设置默认覆盖值

switch (err->status) {case NGX_HTTP_TO_HTTPS:case NGX_HTTPS_CERT_ERROR:case NGX_HTTPS_NO_CERT:case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:err->overwrite = NGX_HTTP_BAD_REQUEST;
}

为特定状态码设置默认覆盖码 400 Bad Request

匹配的状态码

NGX_HTTP_TO_HTTPS(497):客户端通过 HTTP 请求 HTTPS 服务。

NGX_HTTPS_CERT_ERROR(495):客户端证书验证失败。

NGX_HTTPS_NO_CERT(496):需要客户端证书但未提供。

NGX_HTTP_REQUEST_HEADER_TOO_LARGE(494):请求头过大。

覆盖逻辑 :将响应码改为 400 Bad Request,隐藏内部实现细节。

意义

安全性 :避免暴露敏感状态码(如 495、496)给客户端。

标准化 :统一返回标准 HTTP 状态码,符合 RFC 规范。

err->value = cv;

将处理后的 URI 存储到错误页结构体

cvngx_http_complex_value_t 类型,包含静态或动态 URI(如 /404.html 或包含变量的 /error_$status.html)。

在错误发生时,Nginx 会根据 cv 的值执行内部跳转或返回静态文件。

err->args = args;

将查询参数保存到错误页结构体。

args 是从 URI 中解析出的查询参数(如 code=404)。

在重定向或内部跳转时,携带参数传递给目标资源。

return NGX_CONF_OK;

 返回 NGX_CONF_OK;


版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com