comparison src/http/ngx_http_header_filter.c @ 96:a23d010f356d

nginx-0.0.1-2003-05-27-16:18:54 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 27 May 2003 12:18:54 +0000
parents 637625a2acdb
children c9b243802a17
comparison
equal deleted inserted replaced
95:b48066122884 96:a23d010f356d
17 static int ngx_http_header_filter_init(ngx_pool_t *pool); 17 static int ngx_http_header_filter_init(ngx_pool_t *pool);
18 static int ngx_http_header_filter(ngx_http_request_t *r); 18 static int ngx_http_header_filter(ngx_http_request_t *r);
19 19
20 20
21 static ngx_http_module_t ngx_http_header_filter_module_ctx = { 21 static ngx_http_module_t ngx_http_header_filter_module_ctx = {
22 NGX_HTTP_MODULE,
23
24 NULL, /* create main configuration */ 22 NULL, /* create main configuration */
25 NULL, /* init main configuration */ 23 NULL, /* init main configuration */
26 24
27 NULL, /* create server configuration */ 25 NULL, /* create server configuration */
28 NULL, /* merge server configuration */ 26 NULL, /* merge server configuration */
31 NULL, /* merge location configuration */ 29 NULL, /* merge location configuration */
32 }; 30 };
33 31
34 32
35 ngx_module_t ngx_http_header_filter_module = { 33 ngx_module_t ngx_http_header_filter_module = {
34 NGX_MODULE,
36 &ngx_http_header_filter_module_ctx, /* module context */ 35 &ngx_http_header_filter_module_ctx, /* module context */
37 0, /* module index */
38 NULL, /* module directives */ 36 NULL, /* module directives */
39 NGX_HTTP_MODULE_TYPE, /* module type */ 37 NGX_HTTP_MODULE, /* module type */
40 ngx_http_header_filter_init /* init module */ 38 ngx_http_header_filter_init /* init module */
41 }; 39 };
42 40
43 41
44 static char server_string[] = "Server: " NGINX_VER CRLF; 42 static char server_string[] = "Server: " NGINX_VER CRLF;
45 43
46 44
47 static ngx_str_t http_codes[] = { 45 static ngx_str_t http_codes[] = {
48 46
49 ngx_string("200 OK"), 47 ngx_string("200 OK"),
48 ngx_null_string, /* "201 Created" */
49 ngx_null_string, /* "202 Accepted" */
50 ngx_null_string, /* "203 Non-Authoritative Information" */
51 ngx_null_string, /* "204 No Content" */
52 ngx_null_string, /* "205 Reset Content" */
53 ngx_string("206 Partial Content"),
54 ngx_null_string, /* "207 Multi-Status" */
55
56 #if 0
57 ngx_null_string, /* "300 Multiple Choices" */
58 #endif
50 59
51 ngx_string("301 Moved Permanently"), 60 ngx_string("301 Moved Permanently"),
52 ngx_string("302 Moved Temporarily"), 61 ngx_string("302 Moved Temporarily"),
53 ngx_null_string, /* 303 */ 62 ngx_null_string, /* "303 See Other" */
54 ngx_string("304 Not Modified"), 63 ngx_string("304 Not Modified"),
55 64
56 ngx_string("400 Bad Request"), 65 ngx_string("400 Bad Request"),
57 ngx_null_string, /* 401 */ 66 ngx_string("401 Unauthorized"),
58 ngx_null_string, /* 402 */ 67 ngx_null_string, /* "402 Payment Required" */
59 ngx_string("403 Forbidden"), 68 ngx_string("403 Forbidden"),
60 ngx_string("404 Not Found"), 69 ngx_string("404 Not Found"),
61 ngx_null_string, /* 405 */ 70 ngx_string("405 Not Allowed"),
62 ngx_null_string, /* 406 */ 71 ngx_null_string, /* "406 Not Acceptable" */
63 ngx_null_string, /* 407 */ 72 ngx_null_string, /* "407 Proxy Authentication Required" */
64 ngx_string("408 Request Time-out"), 73 ngx_string("408 Request Time-out"),
65 ngx_null_string, /* 409 */ 74 ngx_null_string, /* "409 Conflict" */
66 ngx_null_string, /* 410 */ 75 ngx_null_string, /* "410 Gone" */
67 ngx_string("411 Length Required"), 76 ngx_string("411 Length Required"),
68 ngx_null_string, /* 412 */ 77 ngx_null_string, /* "412 Precondition Failed" */
69 ngx_string("413 Request Entity Too Large"), 78 ngx_string("413 Request Entity Too Large"),
70 ngx_null_string, /* "414 Request-URI Too Large" but we never send it 79 ngx_null_string, /* "414 Request-URI Too Large" but we never send it
71 because we treat such requests as the HTTP/0.9 requests 80 because we treat such requests as the HTTP/0.9 requests
72 and send only the body without the header */ 81 and send only the body without the header */
73 ngx_null_string, /* 415 */ 82 ngx_null_string, /* "415 Unsupported Media Type" */
74 ngx_string("416 Requested Range Not Satisfiable"), 83 ngx_string("416 Requested Range Not Satisfiable"),
75 84
76 ngx_string("500 Internal Server Error"), 85 ngx_string("500 Internal Server Error"),
77 ngx_string("501 Method Not Implemented"), 86 ngx_string("501 Method Not Implemented"),
78 ngx_string("502 Bad Gateway"), 87 ngx_string("502 Bad Gateway"),
82 91
83 92
84 93
85 static int ngx_http_header_filter(ngx_http_request_t *r) 94 static int ngx_http_header_filter(ngx_http_request_t *r)
86 { 95 {
87 int len, status, i; 96 int len, status, text, i;
88 time_t ims; 97 time_t ims;
89 ngx_hunk_t *h; 98 ngx_hunk_t *h;
90 ngx_chain_t *ch; 99 ngx_chain_t *ch;
91 ngx_table_elt_t *header; 100 ngx_table_elt_t *header;
92 101
93 if (r->http_version < NGX_HTTP_VERSION_10) { 102 if (r->http_version < NGX_HTTP_VERSION_10) {
94 return NGX_OK; 103 return NGX_OK;
104 }
105
106 if (r->method == NGX_HTTP_HEAD) {
107 r->header_only = 1;
95 } 108 }
96 109
97 /* 9 is for "HTTP/1.x ", 2 is for trailing "\r\n" 110 /* 9 is for "HTTP/1.x ", 2 is for trailing "\r\n"
98 and 2 is for end of header */ 111 and 2 is for end of header */
99 len = 9 + 2 + 2; 112 len = 9 + 2 + 2;
130 /* 2XX */ 143 /* 2XX */
131 status = r->headers_out.status - NGX_HTTP_OK; 144 status = r->headers_out.status - NGX_HTTP_OK;
132 145
133 } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) { 146 } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) {
134 /* 3XX */ 147 /* 3XX */
135 status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 1; 148 status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 8;
136 r->header_only = 1; 149 r->header_only = 1;
137 150
138 } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) { 151 } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) {
139 /* 4XX */ 152 /* 4XX */
140 status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 1 + 4; 153 status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 8 + 4;
141 154
142 } else { 155 } else {
143 /* 5XX */ 156 /* 5XX */
144 status = r->headers_out.status 157 status = r->headers_out.status
145 - NGX_HTTP_INTERNAL_SERVER_ERROR + 1 + 4 + 17; 158 - NGX_HTTP_INTERNAL_SERVER_ERROR + 8 + 4 + 17;
146 } 159 }
147 160
148 len += http_codes[status].len; 161 len += http_codes[status].len;
149 } 162 }
150 163
157 170
158 if (r->headers_out.date && r->headers_out.date->key.len) { 171 if (r->headers_out.date && r->headers_out.date->key.len) {
159 len += r->headers_out.date->key.len 172 len += r->headers_out.date->key.len
160 + r->headers_out.date->value.len + 2; 173 + r->headers_out.date->value.len + 2;
161 } else { 174 } else {
162 /* "Date: ... \r\n"; */ 175 /* "Date: ... \r\n" */
163 len += 37; 176 len += 37;
164 } 177 }
165 178
166 /* 2^64 is 20 characters */
167 if (r->headers_out.content_length >= 0) { 179 if (r->headers_out.content_length >= 0) {
180 /* "Content-Length: ... \r\n", 2^64 is 20 characters */
168 len += 48; 181 len += 48;
169 } 182 }
170 183
171 #if 0 184 text = 0;
172 if (r->headers_out.content_type.len) 185 if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
173 len += r->headers_out.content_type.len + 16; 186 r->headers_out.content_type->key.len = 0;
174 #endif 187 len += 16 + r->headers_out.content_type->value.len;
188 if (ngx_strncasecmp(r->headers_out.content_type->value.data,
189 "text/", 5) == 0) {
190 text = 1;
191 /* "; charset=koi8-r" */
192 len += 16;
193 }
194 }
195
196 if (r->headers_out.location
197 && r->headers_out.location->value.len
198 && r->headers_out.location->value.data[0] == '/')
199 {
200 r->headers_out.location->key.len = 0;
201 /* "Location: http:// ... \r\n" */
202 len += 17 + r->server_name->len
203 + r->headers_out.location->value.len + 2;
204
205 if (r->port != 80) {
206 len += r->port_name->len;
207 }
208 }
175 209
176 if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) { 210 if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) {
177 len += r->headers_out.last_modified->key.len 211 len += r->headers_out.last_modified->key.len
178 + r->headers_out.last_modified->value.len + 2; 212 + r->headers_out.last_modified->value.len + 2;
213
179 } else if (r->headers_out.last_modified_time != -1) { 214 } else if (r->headers_out.last_modified_time != -1) {
180 /* "Last-Modified: ... \r\n"; */ 215 /* "Last-Modified: ... \r\n" */
181 len += 46; 216 len += 46;
182 } 217 }
183 218
184 if (r->keepalive == 0) { 219 if (r->keepalive == 0) {
220 /* "Connection: close\r\n" */
185 len += 19; 221 len += 19;
186 } else { 222 } else {
223 /* "Connection: keep-alive\r\n" */
187 len += 24; 224 len += 24;
188 } 225 }
189 226
190 header = (ngx_table_elt_t *) r->headers_out.headers->elts; 227 header = (ngx_table_elt_t *) r->headers_out.headers->elts;
191 for (i = 0; i < r->headers_out.headers->nelts; i++) { 228 for (i = 0; i < r->headers_out.headers->nelts; i++) {
197 } 234 }
198 235
199 ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 64), NGX_ERROR); 236 ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 64), NGX_ERROR);
200 237
201 /* "HTTP/1.x " */ 238 /* "HTTP/1.x " */
202 ngx_memcpy(h->last, "HTTP/1.1 ", 9); 239 h->last = ngx_cpymem(h->last, "HTTP/1.1 ", 9);
203 h->last += 9;
204 240
205 /* status line */ 241 /* status line */
206 if (r->headers_out.status_line.len) { 242 if (r->headers_out.status_line.len) {
207 ngx_memcpy(h->last, r->headers_out.status_line.data, 243 h->last = ngx_cpymem(h->last, r->headers_out.status_line.data,
208 r->headers_out.status_line.len); 244 r->headers_out.status_line.len);
209 h->last += r->headers_out.status_line.len; 245
210 246 } else {
211 } else { 247 h->last = ngx_cpymem(h->last, http_codes[status].data,
212 ngx_memcpy(h->last, http_codes[status].data, 248 http_codes[status].len);
213 http_codes[status].len);
214 h->last += http_codes[status].len;
215 } 249 }
216 *(h->last++) = CR; *(h->last++) = LF; 250 *(h->last++) = CR; *(h->last++) = LF;
217 251
218 if (!(r->headers_out.server && r->headers_out.server->key.len)) { 252 if (!(r->headers_out.server && r->headers_out.server->key.len)) {
219 ngx_memcpy(h->last, server_string, sizeof(server_string) - 1); 253 h->last = ngx_cpymem(h->last, server_string, sizeof(server_string) - 1);
220 h->last += sizeof(server_string) - 1;
221 } 254 }
222 255
223 if (!(r->headers_out.date && r->headers_out.date->key.len)) { 256 if (!(r->headers_out.date && r->headers_out.date->key.len)) {
224 ngx_memcpy(h->last, "Date: ", 6); 257 h->last = ngx_cpymem(h->last, "Date: ", 6);
225 h->last += 6;
226 h->last += ngx_http_get_time(h->last, time(NULL)); 258 h->last += ngx_http_get_time(h->last, time(NULL));
227 *(h->last++) = CR; *(h->last++) = LF; 259 *(h->last++) = CR; *(h->last++) = LF;
228 } 260 }
229 261
230 /* 2^64 is 20 characters */ 262 /* 2^64 is 20 characters */
231 if (r->headers_out.content_length >= 0) { 263 if (r->headers_out.content_length >= 0) {
232 h->last += ngx_snprintf(h->last, 49, 264 h->last += ngx_snprintf(h->last, 49,
233 "Content-Length: " OFF_FMT CRLF, 265 "Content-Length: " OFF_FMT CRLF,
234 r->headers_out.content_length); 266 r->headers_out.content_length);
235 } 267 }
236 268
237 #if 0 269 if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
238 if (r->headers_out.content_type.len) { 270 h->last = ngx_cpymem(h->last, "Content-Type: ", 14);
239 ngx_memcpy(h->last, "Content-Type: ", 14); 271 h->last = ngx_cpymem(h->last, r->headers_out.content_type->value.data,
240 h->last += 14; 272 r->headers_out.content_type->value.len);
241 ngx_memcpy(h->last, r->headers_out.content_type.data, 273
242 r->headers_out.content_type.len); 274 if (text) {
243 h->last += r->headers_out.content_type.len; 275 h->last = ngx_cpymem(h->last, "; charset=koi8-r", 16);
244 *(h->last++) = CR; *(h->last++) = LF; 276 }
245 } 277
246 #endif 278 *(h->last++) = CR; *(h->last++) = LF;
247 279 }
248 if (!(r->headers_out.last_modified 280
249 && r->headers_out.last_modified->key.len) 281 if (r->headers_out.location
282 && r->headers_out.location->value.len
283 && r->headers_out.location->value.data[0] == '/')
284 {
285 h->last = ngx_cpymem(h->last, "Location: http://", 17);
286 h->last = ngx_cpymem(h->last, r->server_name->data,
287 r->server_name->len);
288 if (r->port != 80) {
289 h->last = ngx_cpymem(h->last, r->port_name->data,
290 r->port_name->len);
291 }
292
293 h->last = ngx_cpymem(h->last, r->headers_out.location->value.data,
294 r->headers_out.location->value.len);
295
296 *(h->last++) = CR; *(h->last++) = LF;
297 }
298
299 if (!(r->headers_out.last_modified && r->headers_out.last_modified->key.len)
250 && r->headers_out.last_modified_time != -1) 300 && r->headers_out.last_modified_time != -1)
251 { 301 {
252 ngx_memcpy(h->last, "Last-Modified: ", 15); 302 h->last = ngx_cpymem(h->last, "Last-Modified: ", 15);
253 h->last += 15;
254 h->last += ngx_http_get_time(h->last, 303 h->last += ngx_http_get_time(h->last,
255 r->headers_out.last_modified_time); 304 r->headers_out.last_modified_time);
256 *(h->last++) = CR; *(h->last++) = LF; 305 *(h->last++) = CR; *(h->last++) = LF;
257 } 306 }
258 307
259 if (r->keepalive == 0) { 308 if (r->keepalive == 0) {
260 ngx_memcpy(h->last, "Connection: close" CRLF, 19); 309 h->last = ngx_cpymem(h->last, "Connection: close" CRLF, 19);
261 h->last += 19; 310
262 311 } else {
263 } else { 312 h->last = ngx_cpymem(h->last, "Connection: keep-alive" CRLF, 24);
264 ngx_memcpy(h->last, "Connection: keep-alive" CRLF, 24);
265 h->last += 24;
266 } 313 }
267 314
268 for (i = 0; i < r->headers_out.headers->nelts; i++) { 315 for (i = 0; i < r->headers_out.headers->nelts; i++) {
269 if (header[i].key.len == 0) { 316 if (header[i].key.len == 0) {
270 continue; 317 continue;
271 } 318 }
272 319
273 ngx_memcpy(h->last, header[i].key.data, header[i].key.len); 320 h->last = ngx_cpymem(h->last, header[i].key.data, header[i].key.len);
274 h->last += header[i].key.len;
275 *(h->last++) = ':' ; *(h->last++) = ' ' ; 321 *(h->last++) = ':' ; *(h->last++) = ' ' ;
276 322
277 ngx_memcpy(h->last, header[i].value.data, header[i].value.len); 323 h->last = ngx_cpymem(h->last, header[i].value.data,
278 h->last += header[i].value.len; 324 header[i].value.len);
279 *(h->last++) = CR; *(h->last++) = LF; 325 *(h->last++) = CR; *(h->last++) = LF;
280 } 326 }
281 327
282 /* STUB */ 328 /* STUB */
283 *(h->last) = '\0'; 329 *(h->last) = '\0';
284 ngx_log_debug(r->connection->log, "%s\n" _ h->pos); 330 ngx_log_debug(r->connection->log, "%s\n" _ h->pos);
285 /**/ 331 /**/
286 332
287 /* end of HTTP header */ 333 /* the end of HTTP header */
288 *(h->last++) = CR; *(h->last++) = LF; 334 *(h->last++) = CR; *(h->last++) = LF;
289 335
290 if (r->header_only) { 336 if (r->header_only) {
291 h->type |= NGX_HUNK_LAST; 337 h->type |= NGX_HUNK_LAST;
292 } 338 }