comparison src/http/modules/ngx_http_not_modified_filter_module.c @ 680:597573166f34 NGINX_1_3_3

nginx 1.3.3 *) Feature: entity tags support and the "etag" directive. *) Bugfix: trailing dot in a source value was not ignored if the "map" directive was used with the "hostnames" parameter. *) Bugfix: incorrect location might be used to process a request if a URI was changed via a "rewrite" directive before an internal redirect to a named location.
author Igor Sysoev <http://sysoev.ru>
date Tue, 10 Jul 2012 00:00:00 +0400
parents d0f7a625f27c
children
comparison
equal deleted inserted replaced
679:cad34cec7d3b 680:597573166f34
8 #include <ngx_config.h> 8 #include <ngx_config.h>
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11 11
12 12
13 static ngx_int_t ngx_http_test_precondition(ngx_http_request_t *r); 13 static ngx_uint_t ngx_http_test_if_unmodified(ngx_http_request_t *r);
14 static ngx_int_t ngx_http_test_not_modified(ngx_http_request_t *r); 14 static ngx_uint_t ngx_http_test_if_modified(ngx_http_request_t *r);
15 static ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
16 ngx_table_elt_t *header);
15 static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf); 17 static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
16 18
17 19
18 static ngx_http_module_t ngx_http_not_modified_filter_module_ctx = { 20 static ngx_http_module_t ngx_http_not_modified_filter_module_ctx = {
19 NULL, /* preconfiguration */ 21 NULL, /* preconfiguration */
57 || r->headers_out.last_modified_time == -1) 59 || r->headers_out.last_modified_time == -1)
58 { 60 {
59 return ngx_http_next_header_filter(r); 61 return ngx_http_next_header_filter(r);
60 } 62 }
61 63
62 if (r->headers_in.if_unmodified_since) { 64 if (r->headers_in.if_unmodified_since
63 return ngx_http_test_precondition(r); 65 && !ngx_http_test_if_unmodified(r))
64 } 66 {
65 67 return ngx_http_filter_finalize_request(r, NULL,
66 if (r->headers_in.if_modified_since) { 68 NGX_HTTP_PRECONDITION_FAILED);
67 return ngx_http_test_not_modified(r); 69 }
70
71 if (r->headers_in.if_match
72 && !ngx_http_test_if_match(r, r->headers_in.if_match))
73 {
74 return ngx_http_filter_finalize_request(r, NULL,
75 NGX_HTTP_PRECONDITION_FAILED);
76 }
77
78 if (r->headers_in.if_modified_since || r->headers_in.if_none_match) {
79
80 if (r->headers_in.if_modified_since
81 && ngx_http_test_if_modified(r))
82 {
83 return ngx_http_next_header_filter(r);
84 }
85
86 if (r->headers_in.if_none_match
87 && !ngx_http_test_if_match(r, r->headers_in.if_none_match))
88 {
89 return ngx_http_next_header_filter(r);
90 }
91
92 /* not modified */
93
94 r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
95 r->headers_out.status_line.len = 0;
96 r->headers_out.content_type.len = 0;
97 ngx_http_clear_content_length(r);
98 ngx_http_clear_accept_ranges(r);
99
100 if (r->headers_out.content_encoding) {
101 r->headers_out.content_encoding->hash = 0;
102 r->headers_out.content_encoding = NULL;
103 }
104
105 return ngx_http_next_header_filter(r);
68 } 106 }
69 107
70 return ngx_http_next_header_filter(r); 108 return ngx_http_next_header_filter(r);
71 } 109 }
72 110
73 111
74 static ngx_int_t 112 static ngx_uint_t
75 ngx_http_test_precondition(ngx_http_request_t *r) 113 ngx_http_test_if_unmodified(ngx_http_request_t *r)
76 { 114 {
77 time_t iums; 115 time_t iums;
78 116
79 iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data, 117 iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data,
80 r->headers_in.if_unmodified_since->value.len); 118 r->headers_in.if_unmodified_since->value.len);
81 119
82 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 120 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
83 "http iums:%d lm:%d", iums, r->headers_out.last_modified_time); 121 "http iums:%d lm:%d", iums, r->headers_out.last_modified_time);
84 122
85 if (iums >= r->headers_out.last_modified_time) { 123 if (iums >= r->headers_out.last_modified_time) {
86 return ngx_http_next_header_filter(r); 124 return 1;
87 } 125 }
88 126
89 return ngx_http_filter_finalize_request(r, NULL, 127 return 0;
90 NGX_HTTP_PRECONDITION_FAILED); 128 }
91 } 129
92 130
93 131 static ngx_uint_t
94 static ngx_int_t 132 ngx_http_test_if_modified(ngx_http_request_t *r)
95 ngx_http_test_not_modified(ngx_http_request_t *r)
96 { 133 {
97 time_t ims; 134 time_t ims;
98 ngx_http_core_loc_conf_t *clcf; 135 ngx_http_core_loc_conf_t *clcf;
99 136
100 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 137 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
101 138
102 if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) { 139 if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
103 return ngx_http_next_header_filter(r); 140 return 1;
104 } 141 }
105 142
106 ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data, 143 ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
107 r->headers_in.if_modified_since->value.len); 144 r->headers_in.if_modified_since->value.len);
108 145
109 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 146 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
110 "http ims:%d lm:%d", ims, r->headers_out.last_modified_time); 147 "http ims:%d lm:%d", ims, r->headers_out.last_modified_time);
111 148
112 if (ims != r->headers_out.last_modified_time) { 149 if (ims == r->headers_out.last_modified_time) {
113 150 return 0;
114 if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT 151 }
115 || ims < r->headers_out.last_modified_time) 152
116 { 153 if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
117 return ngx_http_next_header_filter(r); 154 || ims < r->headers_out.last_modified_time)
118 } 155 {
119 } 156 return 1;
120 157 }
121 r->headers_out.status = NGX_HTTP_NOT_MODIFIED; 158
122 r->headers_out.status_line.len = 0; 159 return 0;
123 r->headers_out.content_type.len = 0; 160 }
124 ngx_http_clear_content_length(r); 161
125 ngx_http_clear_accept_ranges(r); 162
126 163 static ngx_uint_t
127 if (r->headers_out.content_encoding) { 164 ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
128 r->headers_out.content_encoding->hash = 0; 165 {
129 r->headers_out.content_encoding = NULL; 166 u_char *start, *end, ch;
130 } 167 ngx_str_t *etag, *list;
131 168
132 return ngx_http_next_header_filter(r); 169 list = &header->value;
170
171 if (list->len == 1 && list->data[0] == '*') {
172 return 1;
173 }
174
175 if (r->headers_out.etag == NULL) {
176 return 0;
177 }
178
179 etag = &r->headers_out.etag->value;
180
181 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
182 "http im:\"%V\" etag:%V", list, etag);
183
184 start = list->data;
185 end = list->data + list->len;
186
187 while (start < end) {
188
189 if (etag->len > (size_t) (end - start)) {
190 return 0;
191 }
192
193 if (ngx_strncmp(start, etag->data, etag->len) != 0) {
194 goto skip;
195 }
196
197 start += etag->len;
198
199 while (start < end) {
200 ch = *start;
201
202 if (ch == ' ' || ch == '\t') {
203 start++;
204 continue;
205 }
206
207 break;
208 }
209
210 if (start == end || *start == ',') {
211 return 1;
212 }
213
214 skip:
215
216 while (start < end && *start != ',') { start++; }
217 while (start < end) {
218 ch = *start;
219
220 if (ch == ' ' || ch == '\t' || ch == ',') {
221 start++;
222 continue;
223 }
224
225 break;
226 }
227 }
228
229 return 0;
133 } 230 }
134 231
135 232
136 static ngx_int_t 233 static ngx_int_t
137 ngx_http_not_modified_filter_init(ngx_conf_t *cf) 234 ngx_http_not_modified_filter_init(ngx_conf_t *cf)