comparison src/http/ngx_http_header_filter_module.c @ 517:8fbdd980b527

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 13 Jul 2009 23:56:24 +0400
parents 98143f74eb3d
children e19e5f542878
comparison
equal deleted inserted replaced
424:44a61c599bb2 517:8fbdd980b527
59 ngx_null_string, /* "205 Reset Content" */ 59 ngx_null_string, /* "205 Reset Content" */
60 ngx_string("206 Partial Content"), 60 ngx_string("206 Partial Content"),
61 61
62 /* ngx_null_string, */ /* "207 Multi-Status" */ 62 /* ngx_null_string, */ /* "207 Multi-Status" */
63 63
64 #define NGX_HTTP_LEVEL_200 7 64 #define NGX_HTTP_LAST_LEVEL_200 207
65 #define NGX_HTTP_LEVEL_200 (NGX_HTTP_LAST_LEVEL_200 - 200)
65 66
66 /* ngx_null_string, */ /* "300 Multiple Choices" */ 67 /* ngx_null_string, */ /* "300 Multiple Choices" */
67 68
68 ngx_string("301 Moved Permanently"), 69 ngx_string("301 Moved Permanently"),
69 ngx_string("302 Moved Temporarily"), 70 ngx_string("302 Moved Temporarily"),
72 73
73 /* ngx_null_string, */ /* "305 Use Proxy" */ 74 /* ngx_null_string, */ /* "305 Use Proxy" */
74 /* ngx_null_string, */ /* "306 unused" */ 75 /* ngx_null_string, */ /* "306 unused" */
75 /* ngx_null_string, */ /* "307 Temporary Redirect" */ 76 /* ngx_null_string, */ /* "307 Temporary Redirect" */
76 77
77 #define NGX_HTTP_LEVEL_300 4 78 #define NGX_HTTP_LAST_LEVEL_300 305
79 #define NGX_HTTP_LEVEL_300 (NGX_HTTP_LAST_LEVEL_300 - 301)
78 80
79 ngx_string("400 Bad Request"), 81 ngx_string("400 Bad Request"),
80 ngx_string("401 Unauthorized"), 82 ngx_string("401 Unauthorized"),
81 ngx_string("402 Payment Required"), 83 ngx_string("402 Payment Required"),
82 ngx_string("403 Forbidden"), 84 ngx_string("403 Forbidden"),
104 /* ngx_null_string, */ /* "421 unused" */ 106 /* ngx_null_string, */ /* "421 unused" */
105 /* ngx_null_string, */ /* "422 Unprocessable Entity" */ 107 /* ngx_null_string, */ /* "422 Unprocessable Entity" */
106 /* ngx_null_string, */ /* "423 Locked" */ 108 /* ngx_null_string, */ /* "423 Locked" */
107 /* ngx_null_string, */ /* "424 Failed Dependency" */ 109 /* ngx_null_string, */ /* "424 Failed Dependency" */
108 110
109 #define NGX_HTTP_LEVEL_400 17 111 #define NGX_HTTP_LAST_LEVEL_400 417
112 #define NGX_HTTP_LEVEL_400 (NGX_HTTP_LAST_LEVEL_400 - 400)
110 113
111 ngx_string("500 Internal Server Error"), 114 ngx_string("500 Internal Server Error"),
112 ngx_string("501 Method Not Implemented"), 115 ngx_string("501 Method Not Implemented"),
113 ngx_string("502 Bad Gateway"), 116 ngx_string("502 Bad Gateway"),
114 ngx_string("503 Service Temporarily Unavailable"), 117 ngx_string("503 Service Temporarily Unavailable"),
118 ngx_null_string, /* "506 Variant Also Negotiates" */ 121 ngx_null_string, /* "506 Variant Also Negotiates" */
119 ngx_string("507 Insufficient Storage"), 122 ngx_string("507 Insufficient Storage"),
120 /* ngx_null_string, */ /* "508 unused" */ 123 /* ngx_null_string, */ /* "508 unused" */
121 /* ngx_null_string, */ /* "509 unused" */ 124 /* ngx_null_string, */ /* "509 unused" */
122 /* ngx_null_string, */ /* "510 Not Extended" */ 125 /* ngx_null_string, */ /* "510 Not Extended" */
126
127 #define NGX_HTTP_LAST_LEVEL_500 508
128
123 }; 129 };
124 130
125 131
126 ngx_http_header_out_t ngx_http_headers_out[] = { 132 ngx_http_header_out_t ngx_http_headers_out[] = {
127 { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) }, 133 { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) },
151 static ngx_int_t 157 static ngx_int_t
152 ngx_http_header_filter(ngx_http_request_t *r) 158 ngx_http_header_filter(ngx_http_request_t *r)
153 { 159 {
154 u_char *p; 160 u_char *p;
155 size_t len; 161 size_t len;
156 ngx_str_t host; 162 ngx_str_t host, *status_line;
157 ngx_buf_t *b; 163 ngx_buf_t *b;
158 ngx_uint_t status, i; 164 ngx_uint_t status, i, port;
159 ngx_chain_t out; 165 ngx_chain_t out;
160 ngx_list_part_t *part; 166 ngx_list_part_t *part;
161 ngx_table_elt_t *header; 167 ngx_table_elt_t *header;
168 ngx_connection_t *c;
162 ngx_http_core_loc_conf_t *clcf; 169 ngx_http_core_loc_conf_t *clcf;
163 ngx_http_core_srv_conf_t *cscf; 170 ngx_http_core_srv_conf_t *cscf;
164 /* AF_INET only */ 171 struct sockaddr_in *sin;
165 u_char addr[NGX_INET_ADDRSTRLEN]; 172 #if (NGX_HAVE_INET6)
173 struct sockaddr_in6 *sin6;
174 #endif
175 u_char addr[NGX_SOCKADDR_STRLEN];
166 176
167 r->header_sent = 1; 177 r->header_sent = 1;
168 178
169 if (r != r->main) { 179 if (r != r->main) {
170 return NGX_OK; 180 return NGX_OK;
194 204
195 /* status line */ 205 /* status line */
196 206
197 if (r->headers_out.status_line.len) { 207 if (r->headers_out.status_line.len) {
198 len += r->headers_out.status_line.len; 208 len += r->headers_out.status_line.len;
209 status_line = &r->headers_out.status_line;
199 #if (NGX_SUPPRESS_WARN) 210 #if (NGX_SUPPRESS_WARN)
200 status = NGX_INVALID_ARRAY_INDEX; 211 status = 0;
201 #endif 212 #endif
202 213
203 } else { 214 } else {
204 215
205 if (r->headers_out.status < NGX_HTTP_MOVED_PERMANENTLY) { 216 status = r->headers_out.status;
217
218 if (status >= NGX_HTTP_OK
219 && status < NGX_HTTP_LAST_LEVEL_200)
220 {
206 /* 2XX */ 221 /* 2XX */
207 status = r->headers_out.status - NGX_HTTP_OK; 222
208 223 if (status == NGX_HTTP_NO_CONTENT) {
209 if (r->headers_out.status == NGX_HTTP_NO_CONTENT) {
210 r->header_only = 1; 224 r->header_only = 1;
211 r->headers_out.content_type.len = 0; 225 r->headers_out.content_type.len = 0;
212 r->headers_out.content_type.data = NULL; 226 r->headers_out.content_type.data = NULL;
213 r->headers_out.last_modified_time = -1; 227 r->headers_out.last_modified_time = -1;
214 r->headers_out.last_modified = NULL; 228 r->headers_out.last_modified = NULL;
215 r->headers_out.content_length = NULL; 229 r->headers_out.content_length = NULL;
216 r->headers_out.content_length_n = -1; 230 r->headers_out.content_length_n = -1;
217 } 231 }
218 232
219 } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) { 233 status -= NGX_HTTP_OK;
234 status_line = &ngx_http_status_lines[status];
235 len += ngx_http_status_lines[status].len;
236
237 } else if (status >= NGX_HTTP_MOVED_PERMANENTLY
238 && status < NGX_HTTP_LAST_LEVEL_300)
239 {
220 /* 3XX */ 240 /* 3XX */
221 status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY 241
222 + NGX_HTTP_LEVEL_200; 242 if (status == NGX_HTTP_NOT_MODIFIED) {
223
224 if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
225 r->header_only = 1; 243 r->header_only = 1;
226 } 244 }
227 245
228 } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) { 246 status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200;
247 status_line = &ngx_http_status_lines[status];
248 len += ngx_http_status_lines[status].len;
249
250 } else if (status >= NGX_HTTP_BAD_REQUEST
251 && status < NGX_HTTP_LAST_LEVEL_400)
252 {
229 /* 4XX */ 253 /* 4XX */
230 status = r->headers_out.status - NGX_HTTP_BAD_REQUEST 254 status = status - NGX_HTTP_BAD_REQUEST
231 + NGX_HTTP_LEVEL_200 255 + NGX_HTTP_LEVEL_200
232 + NGX_HTTP_LEVEL_300; 256 + NGX_HTTP_LEVEL_300;
257
258 status_line = &ngx_http_status_lines[status];
259 len += ngx_http_status_lines[status].len;
260
261 } else if (status >= NGX_HTTP_INTERNAL_SERVER_ERROR
262 && status < NGX_HTTP_LAST_LEVEL_500)
263 {
264 /* 5XX */
265 status = status - NGX_HTTP_INTERNAL_SERVER_ERROR
266 + NGX_HTTP_LEVEL_200
267 + NGX_HTTP_LEVEL_300
268 + NGX_HTTP_LEVEL_400;
269
270 status_line = &ngx_http_status_lines[status];
271 len += ngx_http_status_lines[status].len;
233 272
234 } else { 273 } else {
235 /* 5XX */ 274 len += NGX_INT_T_LEN;
236 status = r->headers_out.status - NGX_HTTP_INTERNAL_SERVER_ERROR 275 status_line = NULL;
237 + NGX_HTTP_LEVEL_200 276 }
238 + NGX_HTTP_LEVEL_300
239 + NGX_HTTP_LEVEL_400;
240 }
241
242 len += ngx_http_status_lines[status].len;
243 } 277 }
244 278
245 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 279 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
246 280
247 if (r->headers_out.server == NULL) { 281 if (r->headers_out.server == NULL) {
273 if (r->headers_out.last_modified == NULL 307 if (r->headers_out.last_modified == NULL
274 && r->headers_out.last_modified_time != -1) 308 && r->headers_out.last_modified_time != -1)
275 { 309 {
276 len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; 310 len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
277 } 311 }
312
313 c = r->connection;
278 314
279 if (r->headers_out.location 315 if (r->headers_out.location
280 && r->headers_out.location->value.len 316 && r->headers_out.location->value.len
281 && r->headers_out.location->value.data[0] == '/') 317 && r->headers_out.location->value.data[0] == '/')
282 { 318 {
288 324
289 } else if (r->headers_in.server.len) { 325 } else if (r->headers_in.server.len) {
290 host = r->headers_in.server; 326 host = r->headers_in.server;
291 327
292 } else { 328 } else {
329 host.len = NGX_SOCKADDR_STRLEN;
293 host.data = addr; 330 host.data = addr;
294 331
295 if (ngx_http_server_addr(r, &host) != NGX_OK) { 332 if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) {
296 return NGX_ERROR; 333 return NGX_ERROR;
297 } 334 }
298 } 335 }
299 336
337 switch (c->local_sockaddr->sa_family) {
338
339 #if (NGX_HAVE_INET6)
340 case AF_INET6:
341 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
342 port = ntohs(sin6->sin6_port);
343 break;
344 #endif
345 default: /* AF_INET */
346 sin = (struct sockaddr_in *) c->local_sockaddr;
347 port = ntohs(sin->sin_port);
348 break;
349 }
350
351 len += sizeof("Location: https://") - 1
352 + host.len
353 + r->headers_out.location->value.len + 2;
354
355 if (clcf->port_in_redirect) {
356
300 #if (NGX_HTTP_SSL) 357 #if (NGX_HTTP_SSL)
301 if (r->connection->ssl) { 358 if (c->ssl)
302 len += sizeof("Location: https://") - 1 359 port = (port == 443) ? 0 : port;
303 + host.len 360 else
304 + r->headers_out.location->value.len + 2; 361 #endif
305 362 port = (port == 80) ? 0 : port;
306 if (clcf->port_in_redirect && r->port != 443) { 363
307 len += r->port_text->len; 364 } else {
308 } 365 port = 0;
309 366 }
310 } else 367
311 #endif 368 if (port) {
312 { 369 len += sizeof(":65535") - 1;
313 len += sizeof("Location: http://") - 1
314 + host.len
315 + r->headers_out.location->value.len + 2;
316
317 if (clcf->port_in_redirect && r->port != 80) {
318 len += r->port_text->len;
319 }
320 } 370 }
321 371
322 } else { 372 } else {
323 host.len = 0; 373 host.len = 0;
324 host.data = NULL; 374 host.data = NULL;
375 port = 0;
325 } 376 }
326 377
327 if (r->chunked) { 378 if (r->chunked) {
328 len += sizeof("Transfer-Encoding: chunked" CRLF) - 1; 379 len += sizeof("Transfer-Encoding: chunked" CRLF) - 1;
329 } 380 }
383 434
384 /* "HTTP/1.x " */ 435 /* "HTTP/1.x " */
385 b->last = ngx_cpymem(b->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1); 436 b->last = ngx_cpymem(b->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1);
386 437
387 /* status line */ 438 /* status line */
388 if (r->headers_out.status_line.len) { 439 if (status_line) {
389 b->last = ngx_copy(b->last, r->headers_out.status_line.data, 440 b->last = ngx_copy(b->last, status_line->data, status_line->len);
390 r->headers_out.status_line.len);
391 441
392 } else { 442 } else {
393 b->last = ngx_copy(b->last, ngx_http_status_lines[status].data, 443 b->last = ngx_sprintf(b->last, "%ui", status);
394 ngx_http_status_lines[status].len);
395 } 444 }
396 *b->last++ = CR; *b->last++ = LF; 445 *b->last++ = CR; *b->last++ = LF;
397 446
398 if (r->headers_out.server == NULL) { 447 if (r->headers_out.server == NULL) {
399 if (clcf->server_tokens) { 448 if (clcf->server_tokens) {
463 512
464 b->last = ngx_cpymem(b->last, "Location: http", 513 b->last = ngx_cpymem(b->last, "Location: http",
465 sizeof("Location: http") - 1); 514 sizeof("Location: http") - 1);
466 515
467 #if (NGX_HTTP_SSL) 516 #if (NGX_HTTP_SSL)
468 if (r->connection->ssl) { 517 if (c->ssl) {
469 *b->last++ ='s'; 518 *b->last++ ='s';
470 } 519 }
471 #endif 520 #endif
472 521
473 *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/'; 522 *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/';
474 b->last = ngx_copy(b->last, host.data, host.len); 523 b->last = ngx_copy(b->last, host.data, host.len);
475 524
476 if (clcf->port_in_redirect) { 525 if (port) {
477 #if (NGX_HTTP_SSL) 526 b->last = ngx_sprintf(b->last, ":%ui", port);
478 if (r->connection->ssl) {
479 if (r->port != 443) {
480 b->last = ngx_copy(b->last, r->port_text->data,
481 r->port_text->len);
482 }
483 } else
484 #endif
485 {
486 if (r->port != 80) {
487 b->last = ngx_copy(b->last, r->port_text->data,
488 r->port_text->len);
489 }
490 }
491 } 527 }
492 528
493 b->last = ngx_copy(b->last, r->headers_out.location->value.data, 529 b->last = ngx_copy(b->last, r->headers_out.location->value.data,
494 r->headers_out.location->value.len); 530 r->headers_out.location->value.len);
495 531
553 589
554 b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); 590 b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len);
555 *b->last++ = CR; *b->last++ = LF; 591 *b->last++ = CR; *b->last++ = LF;
556 } 592 }
557 593
558 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 594 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
559 "%*s\n", (size_t) (b->last - b->pos), b->pos); 595 "%*s", (size_t) (b->last - b->pos), b->pos);
560 596
561 /* the end of HTTP header */ 597 /* the end of HTTP header */
562 *b->last++ = CR; *b->last++ = LF; 598 *b->last++ = CR; *b->last++ = LF;
563 599
564 r->header_size = b->last - b->pos; 600 r->header_size = b->last - b->pos;