comparison src/http/modules/ngx_http_not_modified_filter_module.c @ 4743:84cc73e01aa8

Not modified filter: tests separated from actions. This makes code more extendable. The only functional change is when If-Modified-Since and If-Unmodified-Since are specified together, the case which is explicitly left undefined by RFC 2616. The new behaviour is to respect them both, which seems better.
author Maxim Dounin <mdounin@mdounin.ru>
date Sat, 07 Jul 2012 21:18:30 +0000
parents d620f497c50f
children 5b93a9ac60ed
comparison
equal deleted inserted replaced
4742:3cb5cf1e1439 4743:84cc73e01aa8
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_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf); 15 static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
16 16
17 17
18 static ngx_http_module_t ngx_http_not_modified_filter_module_ctx = { 18 static ngx_http_module_t ngx_http_not_modified_filter_module_ctx = {
19 NULL, /* preconfiguration */ 19 NULL, /* preconfiguration */
57 || r->headers_out.last_modified_time == -1) 57 || r->headers_out.last_modified_time == -1)
58 { 58 {
59 return ngx_http_next_header_filter(r); 59 return ngx_http_next_header_filter(r);
60 } 60 }
61 61
62 if (r->headers_in.if_unmodified_since) { 62 if (r->headers_in.if_unmodified_since
63 return ngx_http_test_precondition(r); 63 && !ngx_http_test_if_unmodified(r))
64 {
65 return ngx_http_filter_finalize_request(r, NULL,
66 NGX_HTTP_PRECONDITION_FAILED);
64 } 67 }
65 68
66 if (r->headers_in.if_modified_since) { 69 if (r->headers_in.if_modified_since
67 return ngx_http_test_not_modified(r); 70 && !ngx_http_test_if_modified(r))
71 {
72 /* not modified */
73
74 r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
75 r->headers_out.status_line.len = 0;
76 r->headers_out.content_type.len = 0;
77 ngx_http_clear_content_length(r);
78 ngx_http_clear_accept_ranges(r);
79
80 if (r->headers_out.content_encoding) {
81 r->headers_out.content_encoding->hash = 0;
82 r->headers_out.content_encoding = NULL;
83 }
84
85 return ngx_http_next_header_filter(r);
68 } 86 }
69 87
70 return ngx_http_next_header_filter(r); 88 return ngx_http_next_header_filter(r);
71 } 89 }
72 90
73 91
74 static ngx_int_t 92 static ngx_uint_t
75 ngx_http_test_precondition(ngx_http_request_t *r) 93 ngx_http_test_if_unmodified(ngx_http_request_t *r)
76 { 94 {
77 time_t iums; 95 time_t iums;
78 96
79 iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data, 97 iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data,
80 r->headers_in.if_unmodified_since->value.len); 98 r->headers_in.if_unmodified_since->value.len);
81 99
82 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 100 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
83 "http iums:%d lm:%d", iums, r->headers_out.last_modified_time); 101 "http iums:%d lm:%d", iums, r->headers_out.last_modified_time);
84 102
85 if (iums >= r->headers_out.last_modified_time) { 103 if (iums >= r->headers_out.last_modified_time) {
86 return ngx_http_next_header_filter(r); 104 return 1;
87 } 105 }
88 106
89 return ngx_http_filter_finalize_request(r, NULL, 107 return 0;
90 NGX_HTTP_PRECONDITION_FAILED);
91 } 108 }
92 109
93 110
94 static ngx_int_t 111 static ngx_uint_t
95 ngx_http_test_not_modified(ngx_http_request_t *r) 112 ngx_http_test_if_modified(ngx_http_request_t *r)
96 { 113 {
97 time_t ims; 114 time_t ims;
98 ngx_http_core_loc_conf_t *clcf; 115 ngx_http_core_loc_conf_t *clcf;
99 116
100 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 117 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
101 118
102 if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) { 119 if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
103 return ngx_http_next_header_filter(r); 120 return 1;
104 } 121 }
105 122
106 ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data, 123 ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
107 r->headers_in.if_modified_since->value.len); 124 r->headers_in.if_modified_since->value.len);
108 125
109 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 126 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
110 "http ims:%d lm:%d", ims, r->headers_out.last_modified_time); 127 "http ims:%d lm:%d", ims, r->headers_out.last_modified_time);
111 128
112 if (ims != r->headers_out.last_modified_time) { 129 if (ims == r->headers_out.last_modified_time) {
113 130 return 0;
114 if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
115 || ims < r->headers_out.last_modified_time)
116 {
117 return ngx_http_next_header_filter(r);
118 }
119 } 131 }
120 132
121 r->headers_out.status = NGX_HTTP_NOT_MODIFIED; 133 if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
122 r->headers_out.status_line.len = 0; 134 || ims < r->headers_out.last_modified_time)
123 r->headers_out.content_type.len = 0; 135 {
124 ngx_http_clear_content_length(r); 136 return 1;
125 ngx_http_clear_accept_ranges(r);
126
127 if (r->headers_out.content_encoding) {
128 r->headers_out.content_encoding->hash = 0;
129 r->headers_out.content_encoding = NULL;
130 } 137 }
131 138
132 return ngx_http_next_header_filter(r); 139 return 0;
133 } 140 }
134 141
135 142
136 static ngx_int_t 143 static ngx_int_t
137 ngx_http_not_modified_filter_init(ngx_conf_t *cf) 144 ngx_http_not_modified_filter_init(ngx_conf_t *cf)