04 访问 /staticTryFiles 或者 /staticTryFiles/ 的一些具体行为体现
Posted 蓝风9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了04 访问 /staticTryFiles 或者 /staticTryFiles/ 的一些具体行为体现相关的知识,希望对你有一定的参考价值。
前言
之前曾经做过一个测试, 测试结果如下
nginx 访问文件
如果文件存在, 获取文件
如果文件不存在, 文件夹存在, 获取文件夹的 index
如果都不存在 响应 403/404
然后 后面更加详细的测试了一下, 梳理了一下 结论
请求 匹配到 /staticTryFiles 的时候, 查找是否有文件, 如果 有文件, 响应文件
如果没有文件, 有文件夹, 跳转到 /staticTryFiles/, 如果有 index 文件, 响应 index
如果没有 index 文件, 响应 403
如果有文件夹, 跳转到 "/staticTryFiles/", 这个的处理是在 ngx_http_static_module.ngx_http_static_handler 中, 响应了一个 sendRedirect "/staticTryFiles/"
如果没有文件夹, 响应 404
ngx_http_static_module.ngx_http_static_handler 中响应错误码 NGX_HTTP_NOT_FOUND, 外层 ngx_http_core_content_phase 发现错误码不是 NGX_DECLINED, 发送响应给客户端
请求 匹配到 /staticTryFiles/ 的时候, 如果有 index 文件, 响应 index
如果没有 index 文件, 响应 403
这里是所有的 index 尝试完毕之后, 所有的 phase_checker 都处理完成之后
最后一个 static_handler 的结果依然为 DECLINED, 走的 ngx_http_core_module.ngx_http_core_content_phase 之后响应的 FORBIDDEN
这个处理是在 ngx_http_index_module 中, 需要确保 r.uri 以 "/" 结尾, 确保 method 为 HEAD/GET/POST
获取 index 的相关配置, 然后遍历 index 列表
尝试添加 index 到 uri, 然后尝试 打开文件, 如果 打开没有问题, 直接 内部跳转 获取给定的文件返回
这个内部跳转是在当前请求的基础上, 更新了 r.uri 之后, 递归走 handler chain
如果文件存在, 但是存在其他问题, 权限, 文件名过长 响应 相应的错误信息
EMLINK : too many links, 响应 403 - FORBIDDEN
ELOOP : too many symbolic links encountered, 响应 403 - FORBIDDEN
ENOTDIR : not directory, 响应 404 - NOTFOUND
ENAMETOOLONG : file name too long, 响应 404 - NOTFOUND
EACCESS : permission denied, 响应 403 - FORBIDDEN
ENOENT : 如果是 index文件 不存在, 则 continue 下一个 index
以下截图, 调试基于 nginx-1.18.0
请求 /staticTryFiles 的相关处理
根据上下文 uri 以及 root 拼接完整的请求文件路径的地方
(gdb) list
72 /*
73 * ngx_http_map_uri_to_path() allocates memory for terminating '\\0'
74 * so we do not need to reserve memory for '/' for possible redirect
75 */
76
77 last = ngx_http_map_uri_to_path(r, &path, &root, 0);
78 if (last == NULL)
79 return NGX_HTTP_INTERNAL_SERVER_ERROR;
80
81
(gdb) print r.uri
$4 = len = 15, data = 0x7ff9f8800004 "/staticTryFiles HTTP/1.1\\r\\nHost"
(gdb) print path
$5 = len = 140711584440536,
data = 0xf801a118 <error: Cannot access memory at address 0xf801a118>
(gdb) next
78 if (last == NULL)
(gdb) print path
$7 = len = 44,
data = 0x7ff9f8801148 "/usr/local/nginx/html/static/staticTryFiles"
case1 文件存在 并且 能够正常打开文件
直接 响应文件内容给客户端, contentType 的配置参见 nginx 是如何自动推导文件的 content-type 的
调试查看运行时的信息, 文件为 "/usr/local/nginx/html/static/staticTryFiles", 大小为 25b
根据后缀推导 contentType 没有找到合适的, 使用的默认的 application/octet-stream
Breakpoint 3, ngx_http_static_handler (r=0x7ff9f8800450)
at src/http/modules/ngx_http_static_module.c:268
268 return ngx_http_output_filter(r, &out);
(gdb) print b->file->name
$11 = len = 43,
data = 0x7ff9f8801148 "/usr/local/nginx/html/static/staticTryFiles"
(gdb) b->file_pos
Undefined command: "b->file_pos". Try "help".
(gdb) print b->file_pos
$12 = 0
(gdb) print b->file_last
$13 = 25
(gdb) print r->headers_out
$14 = headers = last = 0x7ff9f8800638, part = elts = 0x7ff9f8800a00,
nelts = 2, next = 0x0, size = 48, nalloc = 20, pool = 0x7ff9f8800400,
trailers = last = 0x7ff9f8800670, part = elts = 0x7ff9f8800dc0, nelts = 0,
next = 0x0, size = 48, nalloc = 4, pool = 0x7ff9f8800400,
status = 200, status_line = len = 0, data = 0x0, server = 0x0, date = 0x0,
content_length = 0x0, content_encoding = 0x0, location = 0x0, refresh = 0x0,
last_modified = 0x0, content_range = 0x0, accept_ranges = 0x7ff9f8800a30,
www_authenticate = 0x0, expires = 0x0, etag = 0x7ff9f8800a00,
override_charset = 0x0, content_type_len = 24, content_type = len = 24,
data = 0x7ff9f8012495 "application/octet-stream", charset = len = 0,
data = 0x0, content_type_lowcase = 0x0, content_type_hash = 0,
cache_control = elts = 0x0, nelts = 0, size = 0, nalloc = 0, pool = 0x0,
link = elts = 0x0, nelts = 0, size = 0, nalloc = 0, pool = 0x0,
content_length_n = 25, content_offset = 0, date_time = 0,
last_modified_time = 1656808030
查看一下 html/static/staticTryFiles 的文件大小, 确实为 25b
master:nginx jerry$ ll html/static/
total 16
-rw-r--r-- 1 jerry wheel 21 Jun 22 22:42 index.html
-rw-r--r-- 1 jerry wheel 25 Jul 3 08:27 staticTryFiles
浏览器的默认行为为 下载给定的文件
case2 没有找到文件, 但是找到文件夹 转发到文件夹
如果是存在 staticTryFiles 的文件夹, ngx_open_cached_file 正常
然后 走了后面的 staticTryFiles 文件夹的相关操作, 是一个 302 跳转到 "/staticTryFiles/"
Breakpoint 4, ngx_http_static_handler (r=0x7ff9f8009450)
at src/http/modules/ngx_http_static_module.c:102
102 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
103 != NGX_OK)
(gdb) next
102 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
105 switch (of.err)
(gdb) next
114 level = NGX_LOG_ERR;
(gdb) next
115 rc = NGX_HTTP_NOT_FOUND;
(gdb) next
116 break;
(gdb) next
135 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found)
(gdb) next
136 ngx_log_error(level, log, of.err,
(gdb) next
138
(gdb) next
140 return rc;
(gdb) next
269
(gdb) c
Continuing.
Breakpoint 2, ngx_http_static_handler (r=0x7ff9f9004e50)
at src/http/modules/ngx_http_static_module.c:77
77 last = ngx_http_map_uri_to_path(r, &path, &root, 0);
(gdb) c
Continuing.
Breakpoint 4, ngx_http_static_handler (r=0x7ff9f9004e50)
at src/http/modules/ngx_http_static_module.c:102
102 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
103 != NGX_OK)
(gdb) next
102 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
143 r->root_tested = !r->error_page;
(gdb) next
147 if (of.is_dir)
(gdb) next
151 ngx_http_clear_location(r);
(gdb) br ngx_http_static_module.c:191
Breakpoint 5 at 0x106b03d3d: file src/http/modules/ngx_http_static_module.c, line 191.
(gdb) c
Continuing.
Breakpoint 5, ngx_http_static_handler (r=0x7ff9f9004e50)
at src/http/modules/ngx_http_static_module.c:191
191 return NGX_HTTP_MOVED_PERMANENTLY;
(gdb) delete 5
(gdb) print location
$15 = (u_char *) 0x7ff9f9005b64 "/staticTryFiles/"
(gdb) print r.headers_out
$16 = headers = last = 0x7ff9f9005038, part = elts = 0x7ff9f9005400,
nelts = 1, next = 0x0, size = 48, nalloc = 20, pool = 0x7ff9f9004e00,
trailers = last = 0x7ff9f9005070, part = elts = 0x7ff9f90057c0, nelts = 0,
next = 0x0, size = 48, nalloc = 4, pool = 0x7ff9f9004e00, status = 0,
status_line = len = 0, data = 0x0, server = 0x0, date = 0x0,
content_length = 0x0, content_encoding = 0x0, location = 0x7ff9f9005400,
refresh = 0x0, last_modified = 0x0, content_range = 0x0,
accept_ranges = 0x0, www_authenticate = 0x0, expires = 0x0, etag = 0x0,
override_charset = 0x0, content_type_len = 0, content_type = len = 0,
data = 0x0, charset = len = 0, data = 0x0, content_type_lowcase = 0x0,
content_type_hash = 0, cache_control = elts = 0x0, nelts = 0, size = 0,
nalloc = 0, pool = 0x0, link = elts = 0x0, nelts = 0, size = 0,
nalloc = 0, pool = 0x0, content_length_n = -1, content_offset = 0,
date_time = 0, last_modified_time = -1
(gdb)
case3 文件 和 文件夹均不存在
打开文件的时候 发现文件不存在, 响应 404 错误码
外部 http_core_content_phase 发送 404 的响应给客户端
Breakpoint 2, ngx_http_static_handler (r=0x7ff9fa000450)
at src/http/modules/ngx_http_static_module.c:77
77 last = ngx_http_map_uri_to_path(r, &path, &root, 0);
(gdb) c
Continuing.
Breakpoint 4, ngx_http_static_handler (r=0x7ff9fa000450)
at src/http/modules/ngx_http_static_module.c:102
102 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
103 != NGX_OK)
(gdb) next
102 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
105 switch (of.err)
(gdb) next
114 level = NGX_LOG_ERR;
(gdb) next
115 rc = NGX_HTTP_NOT_FOUND;
(gdb) next
116 break;
(gdb) next
135 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found)
(gdb) next
136 ngx_log_error(level, log, of.err,
(gdb) next
138
(gdb) next
140 return rc;
(gdb) print rc
$19 = 404
(gdb) b ngx_http_core_module.c:1257
Breakpoint 6 at 0x106ab0043: file src/http/ngx_http_core_module.c, line 1257.
(gdb) c
Continuing.
Breakpoint 6, ngx_http_core_content_phase (r=0x7ff9fa000450, ph=0x7ff9f801eb60)
at src/http/ngx_http_core_module.c:1257
warning: Source file is more recent than executable.
1257 ngx_http_finalize_request(r, rc);
(gdb) print rc
$20 = 404
请求 /staticTryFiles/ 的相关处理
case1 存在某一个 index 文件
这个处理是在 ngx_http_index_module 中, 需要确保 r.uri 以 "/" 结尾, 确保 method 为 HEAD/GET/POST 获取 index 的相关配置, 然后遍历 index 列表 尝试添加 index 到 uri, 然后尝试 打开文件, 如果 打开没有问题, 直接 内部跳转 获取给定的文件返回 这个内部跳转是在当前请求的基础上, 更新了 r.uri 之后, 递归走 handler chain 如果文件存在, 但是存在其他问题, 权限, 文件名过长 响应 相应的错误信息 EMLINK : too many links, 响应 403 - FORBIDDEN ELOOP : too many symbolic links encountered, 响应 403 - FORBIDDEN ENOTDIR : not directory, 响应 404 - NOTFOUND ENAMETOOLONG : file name too long, 响应 404 - NOTFOUND EACCESS : permission denied, 响应 403 - FORBIDDEN ENOENT : 如果是 index文件 不存在, 则 continue 下一个 index
Breakpoint 7, ngx_http_index_handler (r=0x7ff9fa000450)
at src/http/modules/ngx_http_index_module.c:130
130 index = ilcf->indices->elts;
(gdb) next
131 for (i = 0; i < ilcf->indices->nelts; i++)
(gdb) next
133 if (index[i].lengths == NULL)
(gdb) print index[0]
$24 = name = len = 12, data = 0x7ff9f801b05e "index1.html", lengths = 0x0,
values = 0x0
(gdb) print index[1]
$26 = name = len = 11, data = 0x7ff9f801b06a "index1.htm", lengths = 0x0,
values = 0x0
(gdb) next
135 if (index[i].name.data[0] == '/')
(gdb) next
139 reserve = ilcf->max_index_len;
(gdb) next
140 len = index[i].name.len;
(gdb) next
142 else
(gdb) next
162 if (reserve > allocated)
(gdb) next
164 name = ngx_http_map_uri_to_path(r, &path, &root, reserve);
(gdb) next
165 if (name == NULL)
(gdb) print name
$27 = (u_char *) 0x7ff9fa001174 ""
(gdb) print path
$28 = len = 56,
data = 0x7ff9fa001148 "/usr/local/nginx/html/static/staticTryFiles/"
(gdb) next
169 allocated = path.data + path.len - name;
(gdb) next
172 if (index[i].values == NULL)
(gdb) next
176 ngx_memcpy(name, index[i].name.data, index[i].name.len);
(gdb) next
178 path.len = (name + index[i].name.len - 1) - path.data;
(gdb) next
180 else
(gdb) next
203 ngx_memzero(&of, sizeof(ngx_open_file_info_t));
(gdb) next
205 of.read_ahead = clcf->read_ahead;
(gdb) next
206 of.directio = clcf->directio;
(gdb) print name
$29 = (u_char *) 0x7ff9fa001174 "index1.html"
(gdb) print path
$30 = len = 55,
data = 0x7ff9fa001148 "/usr/local/nginx/html/static/staticTryFiles/index1.html"
(gdb) next
207 of.valid = clcf->open_file_cache_valid;
(gdb) next
208 of.min_uses = clcf->open_file_cache_min_uses;
(gdb) next
209 of.test_only = 1;
(gdb) next
210 of.errors = clcf->open_file_cache_errors;
(gdb) next
211 of.events = clcf->open_file_cache_events;
(gdb) next
213 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK)
(gdb) next
217 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
218 != NGX_OK)
(gdb) next
217 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
(gdb) next
262 uri.len = r->uri.len + len - 1;
(gdb) next
264 if (!clcf->alias)
(gdb) next
265 uri.data = path.data + root;
(gdb) next
267 else
(gdb) next
277 return ngx_http_internal_redirect(r, &uri, &r->args);
(gdb) print uri
$31 = len = 27, data = 0x7ff9fa001164 "/staticTryFiles/index1.html"
case2 所有 index 文件均不存在
如果所有的 index 文件均不存在, ngx_http_core_content_phase 最后响应一个 HTTP_FORBIDDEN
Breakpoint 7, ngx_http_index_handler (r=0x7ff9f7810050)
at src/http/modules/ngx_http_index_module.c:130
130 index = ilcf->indices->elts;
(gdb) b ngx_http_core_module.c:1279
Breakpoint 8 at 0x106ab0129: file src/http/ngx_http_core_module.c, line 1279.
(gdb) c
Continuing.
Breakpoint 8, ngx_http_core_content_phase (r=0x7ff9f7810050, ph=0x7ff9f801eb78)
at src/http/ngx_http_core_module.c:1279
1279 ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
(gdb) list
1274 if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL)
1275 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1276 "directory index of \\"%s\\" is forbidden", path.data);
1277
1278
1279 ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
1280 return NGX_OK;
1281
1282
1283 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
完
以上是关于04 访问 /staticTryFiles 或者 /staticTryFiles/ 的一些具体行为体现的主要内容,如果未能解决你的问题,请参考以下文章
2021-06-04:给定三个参数:二叉树的头节点head,树上某个节点target,正数K,从target开始,可以向上走或者