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                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
0173             }
0174 
0175             last = ngx_copy(location, r->uri.data, r->uri.len);
0176 
0177             *last = '/';
0178 
0179             if (r->args.len) {
0180                 *++last = '?';
0181                 ngx_memcpy(++last, r->args.data, r->args.len);
0182             }
0183         }
0184 
0185         r->headers_out.location->hash = 1;
0186         ngx_str_set(&r->headers_out.location->key, "Location");
0187         r->headers_out.location->value.len = len;
0188         r->headers_out.location->value.data = location;
0189 
0190         return NGX_HTTP_MOVED_PERMANENTLY;
0191     }
0192 
0193 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
0194 
0195     if (!of.is_file) {
0196         ngx_log_error(NGX_LOG_CRIT, log, 0,
0197                       "\"%s\" is not a regular file", path.data);
0198 
0199         return NGX_HTTP_NOT_FOUND;
0200     }
0201 
0202 #endif
0203 
0204     if (r->method == NGX_HTTP_POST) {
0205         return NGX_HTTP_NOT_ALLOWED;
0206     }
0207 
0208     rc = ngx_http_discard_request_body(r);
0209 
0210     if (rc != NGX_OK) {
0211         return rc;
0212     }
0213 
0214     log->action = "sending response to client";
0215 
0216     r->headers_out.status = NGX_HTTP_OK;
0217     r->headers_out.content_length_n = of.size;
0218     r->headers_out.last_modified_time = of.mtime;
0219 
0220     if (ngx_http_set_etag(r) != NGX_OK) {
0221         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0222     }
0223 
0224     if (ngx_http_set_content_type(r) != NGX_OK) {
0225         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0226     }
0227 
0228     if (r != r->main && of.size == 0) {
0229         return ngx_http_send_header(r);
0230     }
0231 
0232     r->allow_ranges = 1;
0233 
0234     /* we need to allocate all before the header would be sent */
0235 
0236     b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
0237     if (b == NULL) {
0238         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0239     }
0240 
0241     b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
0242     if (b->file == NULL) {
0243         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0244     }
0245 
0246     rc = ngx_http_send_header(r);
0247 
0248     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
0249         return rc;
0250     }
0251 
0252     b->file_pos = 0;
0253     b->file_last = of.size;
0254 
0255     b->in_file = b->file_last ? 1: 0;
0256     b->last_buf = (r == r->main) ? 1: 0;
0257     b->last_in_chain = 1;
0258 
0259     b->file->fd = of.fd;
0260     b->file->name = path;
0261     b->file->log = log;
0262     b->file->directio = of.is_directio;
0263 
0264     out.buf = b;
0265     out.next = NULL;
0266 
0267     return ngx_http_output_filter(r, &out);
0268 }
0269 
0270 
0271 static ngx_int_t
0272 ngx_http_static_init(ngx_conf_t *cf)
0273 {
0274     ngx_http_handler_pt        *h;
0275     ngx_http_core_main_conf_t  *cmcf;
0276 
0277     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
0278 
0279     h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
0280     if (h == NULL) {
0281         return NGX_ERROR;
0282     }
0283 
0284     *h = ngx_http_static_handler;
0285 
0286     return NGX_OK;
0287 }