Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
0014 static ngx_int_t ngx_http_static_init(ngx_conf_t *cf);
0015 
0016 
0017 static ngx_http_module_t  ngx_http_static_module_ctx = {
0018     NULL,                                  /* preconfiguration */
0019     ngx_http_static_init,                  /* postconfiguration */
0020 
0021     NULL,                                  /* create main configuration */
0022     NULL,                                  /* init main configuration */
0023 
0024     NULL,                                  /* create server configuration */
0025     NULL,                                  /* merge server configuration */
0026 
0027     NULL,                                  /* create location configuration */
0028     NULL                                   /* merge location configuration */
0029 };
0030 
0031 
0032 ngx_module_t  ngx_http_static_module = {
0033     NGX_MODULE_V1,
0034     &ngx_http_static_module_ctx,           /* module context */
0035     NULL,                                  /* module directives */
0036     NGX_HTTP_MODULE,                       /* module type */
0037     NULL,                                  /* init master */
0038     NULL,                                  /* init module */
0039     NULL,                                  /* init process */
0040     NULL,                                  /* init thread */
0041     NULL,                                  /* exit thread */
0042     NULL,                                  /* exit process */
0043     NULL,                                  /* exit master */
0044     NGX_MODULE_V1_PADDING
0045 };
0046 
0047 
0048 static ngx_int_t
0049 ngx_http_static_handler(ngx_http_request_t *r)
0050 {
0051     u_char                    *last, *location;
0052     size_t                     root, len;
0053     ngx_str_t                  path;
0054     ngx_int_t                  rc;
0055     ngx_uint_t                 level;
0056     ngx_log_t                 *log;
0057     ngx_buf_t                 *b;
0058     ngx_chain_t                out;
0059     ngx_open_file_info_t       of;
0060     ngx_http_core_loc_conf_t  *clcf;
0061 
0062     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
0063         return NGX_HTTP_NOT_ALLOWED;
0064     }
0065 
0066     if (r->uri.data[r->uri.len - 1] == '/') {
0067         return NGX_DECLINED;
0068     }
0069 
0070     log = r->connection->log;
0071 
0072     /*
0073      * ngx_http_map_uri_to_path() allocates memory for terminating '\0'
0074      * so we do not need to reserve memory for '/' for possible redirect
0075      */
0076 
0077     last = ngx_http_map_uri_to_path(r, &path, &root, 0);
0078     if (last == NULL) {
0079         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0080     }
0081 
0082     path.len = last - path.data;
0083 
0084     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
0085                    "http filename: \"%s\"", path.data);
0086 
0087     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0088 
0089     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
0090 
0091     of.read_ahead = clcf->read_ahead;
0092     of.directio = clcf->directio;
0093     of.valid = clcf->open_file_cache_valid;
0094     of.min_uses = clcf->open_file_cache_min_uses;
0095     of.errors = clcf->open_file_cache_errors;
0096     of.events = clcf->open_file_cache_events;
0097 
0098     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
0099         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0100     }
0101 
0102     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
0103         != NGX_OK)
0104     {
0105         switch (of.err) {
0106 
0107         case 0:
0108             return NGX_HTTP_INTERNAL_SERVER_ERROR;
0109 
0110         case NGX_ENOENT:
0111         case NGX_ENOTDIR:
0112         case NGX_ENAMETOOLONG:
0113 
0114             level = NGX_LOG_ERR;
0115             rc = NGX_HTTP_NOT_FOUND;
0116             break;
0117 
0118         case NGX_EACCES:
0119 #if (NGX_HAVE_OPENAT)
0120         case NGX_EMLINK:
0121         case NGX_ELOOP:
0122 #endif
0123 
0124             level = NGX_LOG_ERR;
0125             rc = NGX_HTTP_FORBIDDEN;
0126             break;
0127 
0128         default:
0129 
0130             level = NGX_LOG_CRIT;
0131             rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
0132             break;
0133         }
0134 
0135         if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
0136             ngx_log_error(level, log, of.err,
0137                           "%s \"%s\" failed", of.failed, path.data);
0138         }
0139 
0140         return rc;
0141     }
0142 
0143     r->root_tested = !r->error_page;
0144 
0145     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
0146 
0147     if (of.is_dir) {
0148 
0149         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
0150 
0151         ngx_http_clear_location(r);
0152 
0153         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
0154         if (r->headers_out.location == NULL) {
0155             return NGX_HTTP_INTERNAL_SERVER_ERROR;
0156         }
0157 
0158         len = r->uri.len + 1;
0159 
0160         if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
0161             location = path.data + clcf->root.len;
0162 
0163             *last = '/';
0164 
0165         } else {
0166             if (r->args.len) {
0167                 len += r->args.len + 1;
0168             }
0169 
0170             location = ngx_pnalloc(r->pool, len);
0171             if (location == NULL) {
0172                 ngx_http_clear_location(r);
0173                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
0174             }
0175 
0176             last = ngx_copy(location, r->uri.data, r->uri.len);
0177 
0178             *last = '/';
0179 
0180             if (r->args.len) {
0181                 *++last = '?';
0182                 ngx_memcpy(++last, r->args.data, r->args.len);
0183             }
0184         }
0185 
0186         r->headers_out.location->hash = 1;
0187         ngx_str_set(&r->headers_out.location->key, "Location");
0188         r->headers_out.location->value.len = len;
0189         r->headers_out.location->value.data = location;
0190 
0191         return NGX_HTTP_MOVED_PERMANENTLY;
0192     }
0193 
0194 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
0195 
0196     if (!of.is_file) {
0197         ngx_log_error(NGX_LOG_CRIT, log, 0,
0198                       "\"%s\" is not a regular file", path.data);
0199 
0200         return NGX_HTTP_NOT_FOUND;
0201     }
0202 
0203 #endif
0204 
0205     if (r->method == NGX_HTTP_POST) {
0206         return NGX_HTTP_NOT_ALLOWED;
0207     }
0208 
0209     rc = ngx_http_discard_request_body(r);
0210 
0211     if (rc != NGX_OK) {
0212         return rc;
0213     }
0214 
0215     log->action = "sending response to client";
0216 
0217     r->headers_out.status = NGX_HTTP_OK;
0218     r->headers_out.content_length_n = of.size;
0219     r->headers_out.last_modified_time = of.mtime;
0220 
0221     if (ngx_http_set_etag(r) != NGX_OK) {
0222         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0223     }
0224 
0225     if (ngx_http_set_content_type(r) != NGX_OK) {
0226         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0227     }
0228 
0229     if (r != r->main && of.size == 0) {
0230         return ngx_http_send_header(r);
0231     }
0232 
0233     r->allow_ranges = 1;
0234 
0235     /* we need to allocate all before the header would be sent */
0236 
0237     b = ngx_calloc_buf(r->pool);
0238     if (b == NULL) {
0239         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0240     }
0241 
0242     b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
0243     if (b->file == NULL) {
0244         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0245     }
0246 
0247     rc = ngx_http_send_header(r);
0248 
0249     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
0250         return rc;
0251     }
0252 
0253     b->file_pos = 0;
0254     b->file_last = of.size;
0255 
0256     b->in_file = b->file_last ? 1: 0;
0257     b->last_buf = (r == r->main) ? 1: 0;
0258     b->last_in_chain = 1;
0259 
0260     b->file->fd = of.fd;
0261     b->file->name = path;
0262     b->file->log = log;
0263     b->file->directio = of.is_directio;
0264 
0265     out.buf = b;
0266     out.next = NULL;
0267 
0268     return ngx_http_output_filter(r, &out);
0269 }
0270 
0271 
0272 static ngx_int_t
0273 ngx_http_static_init(ngx_conf_t *cf)
0274 {
0275     ngx_http_handler_pt        *h;
0276     ngx_http_core_main_conf_t  *cmcf;
0277 
0278     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
0279 
0280     h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
0281     if (h == NULL) {
0282         return NGX_ERROR;
0283     }
0284 
0285     *h = ngx_http_static_handler;
0286 
0287     return NGX_OK;
0288 }