3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
13 #define NGX_HTTP_GZIP_STATIC_OFF 0
14 #define NGX_HTTP_GZIP_STATIC_ON 1
15 #define NGX_HTTP_GZIP_STATIC_ALWAYS 2
20 } ngx_http_gzip_static_conf_t
;
23 static ngx_int_t
ngx_http_gzip_static_handler(ngx_http_request_t
*r
);
24 static void *ngx_http_gzip_static_create_conf(ngx_conf_t
*cf
);
25 static char *ngx_http_gzip_static_merge_conf(ngx_conf_t
*cf
, void *parent
,
27 static ngx_int_t
ngx_http_gzip_static_init(ngx_conf_t
*cf
);
30 static ngx_conf_enum_t ngx_http_gzip_static
[] = {
31 { ngx_string("off"), NGX_HTTP_GZIP_STATIC_OFF
},
32 { ngx_string("on"), NGX_HTTP_GZIP_STATIC_ON
},
33 { ngx_string("always"), NGX_HTTP_GZIP_STATIC_ALWAYS
},
34 { ngx_null_string
, 0 }
38 static ngx_command_t ngx_http_gzip_static_commands
[] = {
40 { ngx_string("gzip_static"),
41 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
42 ngx_conf_set_enum_slot
,
43 NGX_HTTP_LOC_CONF_OFFSET
,
44 offsetof(ngx_http_gzip_static_conf_t
, enable
),
45 &ngx_http_gzip_static
},
51 ngx_http_module_t ngx_http_gzip_static_module_ctx
= {
52 NULL
, /* preconfiguration */
53 ngx_http_gzip_static_init
, /* postconfiguration */
55 NULL
, /* create main configuration */
56 NULL
, /* init main configuration */
58 NULL
, /* create server configuration */
59 NULL
, /* merge server configuration */
61 ngx_http_gzip_static_create_conf
, /* create location configuration */
62 ngx_http_gzip_static_merge_conf
/* merge location configuration */
66 ngx_module_t ngx_http_gzip_static_module
= {
68 &ngx_http_gzip_static_module_ctx
, /* module context */
69 ngx_http_gzip_static_commands
, /* module directives */
70 NGX_HTTP_MODULE
, /* module type */
71 NULL
, /* init master */
72 NULL
, /* init module */
73 NULL
, /* init process */
74 NULL
, /* init thread */
75 NULL
, /* exit thread */
76 NULL
, /* exit process */
77 NULL
, /* exit master */
83 ngx_http_gzip_static_handler(ngx_http_request_t
*r
)
94 ngx_open_file_info_t of
;
95 ngx_http_core_loc_conf_t
*clcf
;
96 ngx_http_gzip_static_conf_t
*gzcf
;
98 if (!(r
->method
& (NGX_HTTP_GET
|NGX_HTTP_HEAD
))) {
102 if (r
->uri
.data
[r
->uri
.len
- 1] == '/') {
106 gzcf
= ngx_http_get_module_loc_conf(r
, ngx_http_gzip_static_module
);
108 if (gzcf
->enable
== NGX_HTTP_GZIP_STATIC_OFF
) {
112 if (gzcf
->enable
== NGX_HTTP_GZIP_STATIC_ON
) {
113 rc
= ngx_http_gzip_ok(r
);
120 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
122 if (!clcf
->gzip_vary
&& rc
!= NGX_OK
) {
126 log
= r
->connection
->log
;
128 p
= ngx_http_map_uri_to_path(r
, &path
, &root
, sizeof(".gz") - 1);
130 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
138 path
.len
= p
- path
.data
;
140 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, log
, 0,
141 "http filename: \"%s\"", path
.data
);
143 ngx_memzero(&of
, sizeof(ngx_open_file_info_t
));
145 of
.read_ahead
= clcf
->read_ahead
;
146 of
.directio
= clcf
->directio
;
147 of
.valid
= clcf
->open_file_cache_valid
;
148 of
.min_uses
= clcf
->open_file_cache_min_uses
;
149 of
.errors
= clcf
->open_file_cache_errors
;
150 of
.events
= clcf
->open_file_cache_events
;
152 if (ngx_http_set_disable_symlinks(r
, clcf
, &path
, &of
) != NGX_OK
) {
153 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
156 if (ngx_open_cached_file(clcf
->open_file_cache
, &path
, &of
, r
->pool
)
162 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
166 case NGX_ENAMETOOLONG
:
171 #if (NGX_HAVE_OPENAT)
181 level
= NGX_LOG_CRIT
;
185 ngx_log_error(level
, log
, of
.err
,
186 "%s \"%s\" failed", of
.failed
, path
.data
);
191 if (gzcf
->enable
== NGX_HTTP_GZIP_STATIC_ON
) {
199 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, log
, 0, "http static fd: %d", of
.fd
);
202 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, log
, 0, "http dir");
206 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
209 ngx_log_error(NGX_LOG_CRIT
, log
, 0,
210 "\"%s\" is not a regular file", path
.data
);
212 return NGX_HTTP_NOT_FOUND
;
217 r
->root_tested
= !r
->error_page
;
219 rc
= ngx_http_discard_request_body(r
);
225 log
->action
= "sending response to client";
227 r
->headers_out
.status
= NGX_HTTP_OK
;
228 r
->headers_out
.content_length_n
= of
.size
;
229 r
->headers_out
.last_modified_time
= of
.mtime
;
231 if (ngx_http_set_etag(r
) != NGX_OK
) {
232 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
235 if (ngx_http_set_content_type(r
) != NGX_OK
) {
236 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
239 h
= ngx_list_push(&r
->headers_out
.headers
);
245 ngx_str_set(&h
->key
, "Content-Encoding");
246 ngx_str_set(&h
->value
, "gzip");
247 r
->headers_out
.content_encoding
= h
;
249 r
->ignore_content_encoding
= 1;
251 /* we need to allocate all before the header would be sent */
253 b
= ngx_pcalloc(r
->pool
, sizeof(ngx_buf_t
));
255 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
258 b
->file
= ngx_pcalloc(r
->pool
, sizeof(ngx_file_t
));
259 if (b
->file
== NULL
) {
260 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
263 rc
= ngx_http_send_header(r
);
265 if (rc
== NGX_ERROR
|| rc
> NGX_OK
|| r
->header_only
) {
270 b
->file_last
= of
.size
;
272 b
->in_file
= b
->file_last
? 1 : 0;
273 b
->last_buf
= (r
== r
->main
) ? 1 : 0;
274 b
->last_in_chain
= 1;
277 b
->file
->name
= path
;
279 b
->file
->directio
= of
.is_directio
;
284 return ngx_http_output_filter(r
, &out
);
289 ngx_http_gzip_static_create_conf(ngx_conf_t
*cf
)
291 ngx_http_gzip_static_conf_t
*conf
;
293 conf
= ngx_palloc(cf
->pool
, sizeof(ngx_http_gzip_static_conf_t
));
298 conf
->enable
= NGX_CONF_UNSET_UINT
;
305 ngx_http_gzip_static_merge_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
307 ngx_http_gzip_static_conf_t
*prev
= parent
;
308 ngx_http_gzip_static_conf_t
*conf
= child
;
310 ngx_conf_merge_uint_value(conf
->enable
, prev
->enable
,
311 NGX_HTTP_GZIP_STATIC_OFF
);
318 ngx_http_gzip_static_init(ngx_conf_t
*cf
)
320 ngx_http_handler_pt
*h
;
321 ngx_http_core_main_conf_t
*cmcf
;
323 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
325 h
= ngx_array_push(&cmcf
->phases
[NGX_HTTP_CONTENT_PHASE
].handlers
);
330 *h
= ngx_http_gzip_static_handler
;