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/ 的一些具体行为体现的主要内容,如果未能解决你的问题,请参考以下文章

批量判断网址能否访问 2018-10-04

2021-06-04:给定三个参数:二叉树的头节点head,树上某个节点target,正数K,从target开始,可以向上走或者

Ubuntu18.04安装mysql并配置远程访问

Java语言中的-----访问修饰符

Java语言中的-----访问修饰符

04: gitlab安装与使用