3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
14 } ngx_http_gzip_static_conf_t;
17 static ngx_int_t ngx_http_gzip_static_handler(ngx_http_request_t *r);
18 static void *ngx_http_gzip_static_create_conf(ngx_conf_t *cf);
19 static char *ngx_http_gzip_static_merge_conf(ngx_conf_t *cf, void *parent,
21 static ngx_int_t ngx_http_gzip_static_init(ngx_conf_t *cf);
24 static ngx_command_t ngx_http_gzip_static_commands[] = {
26 { ngx_string("gzip_static"),
27 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
28 ngx_conf_set_flag_slot,
29 NGX_HTTP_LOC_CONF_OFFSET,
30 offsetof(ngx_http_gzip_static_conf_t, enable),
37 ngx_http_module_t ngx_http_gzip_static_module_ctx = {
38 NULL, /* preconfiguration */
39 ngx_http_gzip_static_init, /* postconfiguration */
41 NULL, /* create main configuration */
42 NULL, /* init main configuration */
44 NULL, /* create server configuration */
45 NULL, /* merge server configuration */
47 ngx_http_gzip_static_create_conf, /* create location configuration */
48 ngx_http_gzip_static_merge_conf /* merge location configuration */
52 ngx_module_t ngx_http_gzip_static_module = {
54 &ngx_http_gzip_static_module_ctx, /* module context */
55 ngx_http_gzip_static_commands, /* module directives */
56 NGX_HTTP_MODULE, /* module type */
57 NULL, /* init master */
58 NULL, /* init module */
59 NULL, /* init process */
60 NULL, /* init thread */
61 NULL, /* exit thread */
62 NULL, /* exit process */
63 NULL, /* exit master */
69 ngx_http_gzip_static_handler(ngx_http_request_t *r)
80 ngx_open_file_info_t of;
81 ngx_http_core_loc_conf_t *clcf;
82 ngx_http_gzip_static_conf_t *gzcf;
84 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
88 if (r->uri.data[r->uri.len - 1] == '/') {
97 gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);
99 if (!gzcf->enable || ngx_http_gzip_ok(r) != NGX_OK) {
103 log = r->connection->log;
105 p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1);
107 return NGX_HTTP_INTERNAL_SERVER_ERROR;
115 path.len = p - path.data;
117 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
118 "http filename: \"%s\"", path.data);
120 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
122 ngx_memzero(&of, sizeof(ngx_open_file_info_t));
124 of.directio = clcf->directio;
125 of.valid = clcf->open_file_cache_valid;
126 of.min_uses = clcf->open_file_cache_min_uses;
127 of.errors = clcf->open_file_cache_errors;
128 of.events = clcf->open_file_cache_events;
130 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
136 return NGX_HTTP_INTERNAL_SERVER_ERROR;
140 case NGX_ENAMETOOLONG:
151 level = NGX_LOG_CRIT;
155 ngx_log_error(level, log, of.err,
156 ngx_open_file_n " \"%s\" failed", path.data);
161 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
164 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
168 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
171 ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
172 "\"%s\" is not a regular file", path.data);
174 return NGX_HTTP_NOT_FOUND;
179 r->root_tested = !r->error_page;
181 rc = ngx_http_discard_request_body(r);
187 log->action = "sending response to client";
189 r->headers_out.status = NGX_HTTP_OK;
190 r->headers_out.content_length_n = of.size;
191 r->headers_out.last_modified_time = of.mtime;
193 if (ngx_http_set_content_type(r) != NGX_OK) {
194 return NGX_HTTP_INTERNAL_SERVER_ERROR;
197 h = ngx_list_push(&r->headers_out.headers);
203 h->key.len = sizeof("Content-Encoding") - 1;
204 h->key.data = (u_char *) "Content-Encoding";
205 h->value.len = sizeof("gzip") - 1;
206 h->value.data = (u_char *) "gzip";
208 r->headers_out.content_encoding = h;
210 /* we need to allocate all before the header would be sent */
212 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
214 return NGX_HTTP_INTERNAL_SERVER_ERROR;
217 b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
218 if (b->file == NULL) {
219 return NGX_HTTP_INTERNAL_SERVER_ERROR;
222 rc = ngx_http_send_header(r);
224 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
229 b->file_last = of.size;
231 b->in_file = b->file_last ? 1 : 0;
233 b->last_in_chain = 1;
236 b->file->name = path;
238 b->file->directio = of.is_directio;
243 return ngx_http_output_filter(r, &out);
248 ngx_http_gzip_static_create_conf(ngx_conf_t *cf)
250 ngx_http_gzip_static_conf_t *conf;
252 conf = ngx_palloc(cf->pool, sizeof(ngx_http_gzip_static_conf_t));
254 return NGX_CONF_ERROR;
257 conf->enable = NGX_CONF_UNSET;
264 ngx_http_gzip_static_merge_conf(ngx_conf_t *cf, void *parent, void *child)
266 ngx_http_gzip_static_conf_t *prev = parent;
267 ngx_http_gzip_static_conf_t *conf = child;
269 ngx_conf_merge_value(conf->enable, prev->enable, 0);
276 ngx_http_gzip_static_init(ngx_conf_t *cf)
278 ngx_http_handler_pt *h;
279 ngx_http_core_main_conf_t *cmcf;
281 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
283 h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
288 *h = ngx_http_gzip_static_handler;