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 #define NGX_HTTP_GZIP_STATIC_OFF     0
0014 #define NGX_HTTP_GZIP_STATIC_ON      1
0015 #define NGX_HTTP_GZIP_STATIC_ALWAYS  2
0016 
0017 
0018 typedef struct {
0019     ngx_uint_t  enable;
0020 } ngx_http_gzip_static_conf_t;
0021 
0022 
0023 static ngx_int_t ngx_http_gzip_static_handler(ngx_http_request_t *r);
0024 static void *ngx_http_gzip_static_create_conf(ngx_conf_t *cf);
0025 static char *ngx_http_gzip_static_merge_conf(ngx_conf_t *cf, void *parent,
0026     void *child);
0027 static ngx_int_t ngx_http_gzip_static_init(ngx_conf_t *cf);
0028 
0029 
0030 static ngx_conf_enum_t  ngx_http_gzip_static[] = {
0031     { ngx_string("off"), NGX_HTTP_GZIP_STATIC_OFF },
0032     { ngx_string("on"), NGX_HTTP_GZIP_STATIC_ON },
0033     { ngx_string("always"), NGX_HTTP_GZIP_STATIC_ALWAYS },
0034     { ngx_null_string, 0 }
0035 };
0036 
0037 
0038 static ngx_command_t  ngx_http_gzip_static_commands[] = {
0039 
0040     { ngx_string("gzip_static"),
0041       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0042       ngx_conf_set_enum_slot,
0043       NGX_HTTP_LOC_CONF_OFFSET,
0044       offsetof(ngx_http_gzip_static_conf_t, enable),
0045       &ngx_http_gzip_static },
0046 
0047       ngx_null_command
0048 };
0049 
0050 
0051 static ngx_http_module_t  ngx_http_gzip_static_module_ctx = {
0052     NULL,                                  /* preconfiguration */
0053     ngx_http_gzip_static_init,             /* postconfiguration */
0054 
0055     NULL,                                  /* create main configuration */
0056     NULL,                                  /* init main configuration */
0057 
0058     NULL,                                  /* create server configuration */
0059     NULL,                                  /* merge server configuration */
0060 
0061     ngx_http_gzip_static_create_conf,      /* create location configuration */
0062     ngx_http_gzip_static_merge_conf        /* merge location configuration */
0063 };
0064 
0065 
0066 ngx_module_t  ngx_http_gzip_static_module = {
0067     NGX_MODULE_V1,
0068     &ngx_http_gzip_static_module_ctx,      /* module context */
0069     ngx_http_gzip_static_commands,         /* module directives */
0070     NGX_HTTP_MODULE,                       /* module type */
0071     NULL,                                  /* init master */
0072     NULL,                                  /* init module */
0073     NULL,                                  /* init process */
0074     NULL,                                  /* init thread */
0075     NULL,                                  /* exit thread */
0076     NULL,                                  /* exit process */
0077     NULL,                                  /* exit master */
0078     NGX_MODULE_V1_PADDING
0079 };
0080 
0081 
0082 static ngx_int_t
0083 ngx_http_gzip_static_handler(ngx_http_request_t *r)
0084 {
0085     u_char                       *p;
0086     size_t                        root;
0087     ngx_str_t                     path;
0088     ngx_int_t                     rc;
0089     ngx_uint_t                    level;
0090     ngx_log_t                    *log;
0091     ngx_buf_t                    *b;
0092     ngx_chain_t                   out;
0093     ngx_table_elt_t              *h;
0094     ngx_open_file_info_t          of;
0095     ngx_http_core_loc_conf_t     *clcf;
0096     ngx_http_gzip_static_conf_t  *gzcf;
0097 
0098     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
0099         return NGX_DECLINED;
0100     }
0101 
0102     if (r->uri.data[r->uri.len - 1] == '/') {
0103         return NGX_DECLINED;
0104     }
0105 
0106     gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);
0107 
0108     if (gzcf->enable == NGX_HTTP_GZIP_STATIC_OFF) {
0109         return NGX_DECLINED;
0110     }
0111 
0112     if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {
0113         rc = ngx_http_gzip_ok(r);
0114 
0115     } else {
0116         /* always */
0117         rc = NGX_OK;
0118     }
0119 
0120     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0121 
0122     if (!clcf->gzip_vary && rc != NGX_OK) {
0123         return NGX_DECLINED;
0124     }
0125 
0126     log = r->connection->log;
0127 
0128     p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1);
0129     if (p == NULL) {
0130         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0131     }
0132 
0133     *p++ = '.';
0134     *p++ = 'g';
0135     *p++ = 'z';
0136     *p = '\0';
0137 
0138     path.len = p - path.data;
0139 
0140     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
0141                    "http filename: \"%s\"", path.data);
0142 
0143     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
0144 
0145     of.read_ahead = clcf->read_ahead;
0146     of.directio = clcf->directio;
0147     of.valid = clcf->open_file_cache_valid;
0148     of.min_uses = clcf->open_file_cache_min_uses;
0149     of.errors = clcf->open_file_cache_errors;
0150     of.events = clcf->open_file_cache_events;
0151 
0152     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
0153         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0154     }
0155 
0156     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
0157         != NGX_OK)
0158     {
0159         switch (of.err) {
0160 
0161         case 0:
0162             return NGX_HTTP_INTERNAL_SERVER_ERROR;
0163 
0164         case NGX_ENOENT:
0165         case NGX_ENOTDIR:
0166         case NGX_ENAMETOOLONG:
0167 
0168             return NGX_DECLINED;
0169 
0170         case NGX_EACCES:
0171 #if (NGX_HAVE_OPENAT)
0172         case NGX_EMLINK:
0173         case NGX_ELOOP:
0174 #endif
0175 
0176             level = NGX_LOG_ERR;
0177             break;
0178 
0179         default:
0180 
0181             level = NGX_LOG_CRIT;
0182             break;
0183         }
0184 
0185         ngx_log_error(level, log, of.err,
0186                       "%s \"%s\" failed", of.failed, path.data);
0187 
0188         return NGX_DECLINED;
0189     }
0190 
0191     if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {
0192         r->gzip_vary = 1;
0193 
0194         if (rc != NGX_OK) {
0195             return NGX_DECLINED;
0196         }
0197     }
0198 
0199     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
0200 
0201     if (of.is_dir) {
0202         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
0203         return NGX_DECLINED;
0204     }
0205 
0206 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
0207 
0208     if (!of.is_file) {
0209         ngx_log_error(NGX_LOG_CRIT, log, 0,
0210                       "\"%s\" is not a regular file", path.data);
0211 
0212         return NGX_HTTP_NOT_FOUND;
0213     }
0214 
0215 #endif
0216 
0217     r->root_tested = !r->error_page;
0218 
0219     rc = ngx_http_discard_request_body(r);
0220 
0221     if (rc != NGX_OK) {
0222         return rc;
0223     }
0224 
0225     log->action = "sending response to client";
0226 
0227     r->headers_out.status = NGX_HTTP_OK;
0228     r->headers_out.content_length_n = of.size;
0229     r->headers_out.last_modified_time = of.mtime;
0230 
0231     if (ngx_http_set_etag(r) != NGX_OK) {
0232         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0233     }
0234 
0235     if (ngx_http_set_content_type(r) != NGX_OK) {
0236         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0237     }
0238 
0239     h = ngx_list_push(&r->headers_out.headers);
0240     if (h == NULL) {
0241         return NGX_ERROR;
0242     }
0243 
0244     h->hash = 1;
0245     ngx_str_set(&h->key, "Content-Encoding");
0246     ngx_str_set(&h->value, "gzip");
0247     r->headers_out.content_encoding = h;
0248 
0249     /* we need to allocate all before the header would be sent */
0250 
0251     b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
0252     if (b == NULL) {
0253         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0254     }
0255 
0256     b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
0257     if (b->file == NULL) {
0258         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0259     }
0260 
0261     rc = ngx_http_send_header(r);
0262 
0263     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
0264         return rc;
0265     }
0266 
0267     b->file_pos = 0;
0268     b->file_last = of.size;
0269 
0270     b->in_file = b->file_last ? 1 : 0;
0271     b->last_buf = (r == r->main) ? 1 : 0;
0272     b->last_in_chain = 1;
0273 
0274     b->file->fd = of.fd;
0275     b->file->name = path;
0276     b->file->log = log;
0277     b->file->directio = of.is_directio;
0278 
0279     out.buf = b;
0280     out.next = NULL;
0281 
0282     return ngx_http_output_filter(r, &out);
0283 }
0284 
0285 
0286 static void *
0287 ngx_http_gzip_static_create_conf(ngx_conf_t *cf)
0288 {
0289     ngx_http_gzip_static_conf_t  *conf;
0290 
0291     conf = ngx_palloc(cf->pool, sizeof(ngx_http_gzip_static_conf_t));
0292     if (conf == NULL) {
0293         return NULL;
0294     }
0295 
0296     conf->enable = NGX_CONF_UNSET_UINT;
0297 
0298     return conf;
0299 }
0300 
0301 
0302 static char *
0303 ngx_http_gzip_static_merge_conf(ngx_conf_t *cf, void *parent, void *child)
0304 {
0305     ngx_http_gzip_static_conf_t *prev = parent;
0306     ngx_http_gzip_static_conf_t *conf = child;
0307 
0308     ngx_conf_merge_uint_value(conf->enable, prev->enable,
0309                               NGX_HTTP_GZIP_STATIC_OFF);
0310 
0311     return NGX_CONF_OK;
0312 }
0313 
0314 
0315 static ngx_int_t
0316 ngx_http_gzip_static_init(ngx_conf_t *cf)
0317 {
0318     ngx_http_handler_pt        *h;
0319     ngx_http_core_main_conf_t  *cmcf;
0320 
0321     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
0322 
0323     h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
0324     if (h == NULL) {
0325         return NGX_ERROR;
0326     }
0327 
0328     *h = ngx_http_gzip_static_handler;
0329 
0330     return NGX_OK;
0331 }