Klaus Demo nginx / e430ab4
divide special response handling into several functions fix "?" escaping introduced in r1467 Igor Sysoev 14 years ago
1 changed file(s) with 321 addition(s) and 257 deletion(s). Raw diff Collapse all Expand all
99 #include <nginx.h>
1010
1111
12 static u_char error_full_tail[] =
12 static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r,
13 ngx_http_err_page_t *err_page);
14 static ngx_int_t ngx_http_send_special_response(ngx_http_request_t *r,
15 ngx_http_core_loc_conf_t *clcf, ngx_uint_t err);
16 static ngx_int_t ngx_http_send_refresh(ngx_http_request_t *r);
17
18
19 static u_char ngx_http_error_full_tail[] =
1320 "<hr><center>" NGINX_VER "</center>" CRLF
1421 "</body>" CRLF
1522 "</html>" CRLF
1623 ;
1724
1825
19 static u_char error_tail[] =
26 static u_char ngx_http_error_tail[] =
2027 "<hr><center>nginx</center>" CRLF
2128 "</body>" CRLF
2229 "</html>" CRLF
4148 "\"></head><body></body></html>" CRLF;
4249
4350
44 static char error_301_page[] =
51 static char ngx_http_error_301_page[] =
4552 "<html>" CRLF
4653 "<head><title>301 Moved Permanently</title></head>" CRLF
4754 "<body bgcolor=\"white\">" CRLF
4956 ;
5057
5158
52 static char error_302_page[] =
59 static char ngx_http_error_302_page[] =
5360 "<html>" CRLF
5461 "<head><title>302 Found</title></head>" CRLF
5562 "<body bgcolor=\"white\">" CRLF
5764 ;
5865
5966
60 static char error_400_page[] =
67 static char ngx_http_error_400_page[] =
6168 "<html>" CRLF
6269 "<head><title>400 Bad Request</title></head>" CRLF
6370 "<body bgcolor=\"white\">" CRLF
6572 ;
6673
6774
68 static char error_401_page[] =
75 static char ngx_http_error_401_page[] =
6976 "<html>" CRLF
7077 "<head><title>401 Authorization Required</title></head>" CRLF
7178 "<body bgcolor=\"white\">" CRLF
7380 ;
7481
7582
76 static char error_402_page[] =
83 static char ngx_http_error_402_page[] =
7784 "<html>" CRLF
7885 "<head><title>402 Payment Required</title></head>" CRLF
7986 "<body bgcolor=\"white\">" CRLF
8188 ;
8289
8390
84 static char error_403_page[] =
91 static char ngx_http_error_403_page[] =
8592 "<html>" CRLF
8693 "<head><title>403 Forbidden</title></head>" CRLF
8794 "<body bgcolor=\"white\">" CRLF
8996 ;
9097
9198
92 static char error_404_page[] =
99 static char ngx_http_error_404_page[] =
93100 "<html>" CRLF
94101 "<head><title>404 Not Found</title></head>" CRLF
95102 "<body bgcolor=\"white\">" CRLF
97104 ;
98105
99106
100 static char error_405_page[] =
107 static char ngx_http_error_405_page[] =
101108 "<html>" CRLF
102109 "<head><title>405 Not Allowed</title></head>" CRLF
103110 "<body bgcolor=\"white\">" CRLF
105112 ;
106113
107114
108 static char error_406_page[] =
115 static char ngx_http_error_406_page[] =
109116 "<html>" CRLF
110117 "<head><title>406 Not Acceptable</title></head>" CRLF
111118 "<body bgcolor=\"white\">" CRLF
113120 ;
114121
115122
116 static char error_408_page[] =
123 static char ngx_http_error_408_page[] =
117124 "<html>" CRLF
118125 "<head><title>408 Request Time-out</title></head>" CRLF
119126 "<body bgcolor=\"white\">" CRLF
121128 ;
122129
123130
124 static char error_409_page[] =
131 static char ngx_http_error_409_page[] =
125132 "<html>" CRLF
126133 "<head><title>409 Conflict</title></head>" CRLF
127134 "<body bgcolor=\"white\">" CRLF
129136 ;
130137
131138
132 static char error_410_page[] =
139 static char ngx_http_error_410_page[] =
133140 "<html>" CRLF
134141 "<head><title>410 Gone</title></head>" CRLF
135142 "<body bgcolor=\"white\">" CRLF
137144 ;
138145
139146
140 static char error_411_page[] =
147 static char ngx_http_error_411_page[] =
141148 "<html>" CRLF
142149 "<head><title>411 Length Required</title></head>" CRLF
143150 "<body bgcolor=\"white\">" CRLF
145152 ;
146153
147154
148 static char error_412_page[] =
155 static char ngx_http_error_412_page[] =
149156 "<html>" CRLF
150157 "<head><title>412 Precondition Failed</title></head>" CRLF
151158 "<body bgcolor=\"white\">" CRLF
153160 ;
154161
155162
156 static char error_413_page[] =
163 static char ngx_http_error_413_page[] =
157164 "<html>" CRLF
158165 "<head><title>413 Request Entity Too Large</title></head>" CRLF
159166 "<body bgcolor=\"white\">" CRLF
161168 ;
162169
163170
164 static char error_414_page[] =
171 static char ngx_http_error_414_page[] =
165172 "<html>" CRLF
166173 "<head><title>414 Request-URI Too Large</title></head>" CRLF
167174 "<body bgcolor=\"white\">" CRLF
169176 ;
170177
171178
172 static char error_415_page[] =
179 static char ngx_http_error_415_page[] =
173180 "<html>" CRLF
174181 "<head><title>415 Unsupported Media Type</title></head>" CRLF
175182 "<body bgcolor=\"white\">" CRLF
177184 ;
178185
179186
180 static char error_416_page[] =
187 static char ngx_http_error_416_page[] =
181188 "<html>" CRLF
182189 "<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF
183190 "<body bgcolor=\"white\">" CRLF
185192 ;
186193
187194
188 static char error_495_page[] =
195 static char ngx_http_error_495_page[] =
189196 "<html>" CRLF
190197 "<head><title>400 The SSL certificate error</title></head>"
191198 CRLF
195202 ;
196203
197204
198 static char error_496_page[] =
205 static char ngx_http_error_496_page[] =
199206 "<html>" CRLF
200207 "<head><title>400 No required SSL certificate was sent</title></head>"
201208 CRLF
205212 ;
206213
207214
208 static char error_497_page[] =
215 static char ngx_http_error_497_page[] =
209216 "<html>" CRLF
210217 "<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>"
211218 CRLF
215222 ;
216223
217224
218 static char error_500_page[] =
225 static char ngx_http_error_500_page[] =
219226 "<html>" CRLF
220227 "<head><title>500 Internal Server Error</title></head>" CRLF
221228 "<body bgcolor=\"white\">" CRLF
223230 ;
224231
225232
226 static char error_501_page[] =
233 static char ngx_http_error_501_page[] =
227234 "<html>" CRLF
228235 "<head><title>501 Method Not Implemented</title></head>" CRLF
229236 "<body bgcolor=\"white\">" CRLF
231238 ;
232239
233240
234 static char error_502_page[] =
241 static char ngx_http_error_502_page[] =
235242 "<html>" CRLF
236243 "<head><title>502 Bad Gateway</title></head>" CRLF
237244 "<body bgcolor=\"white\">" CRLF
239246 ;
240247
241248
242 static char error_503_page[] =
249 static char ngx_http_error_503_page[] =
243250 "<html>" CRLF
244251 "<head><title>503 Service Temporarily Unavailable</title></head>" CRLF
245252 "<body bgcolor=\"white\">" CRLF
247254 ;
248255
249256
250 static char error_504_page[] =
257 static char ngx_http_error_504_page[] =
251258 "<html>" CRLF
252259 "<head><title>504 Gateway Time-out</title></head>" CRLF
253260 "<body bgcolor=\"white\">" CRLF
255262 ;
256263
257264
258 static char error_507_page[] =
265 static char ngx_http_error_507_page[] =
259266 "<html>" CRLF
260267 "<head><title>507 Insufficient Storage</title></head>" CRLF
261268 "<body bgcolor=\"white\">" CRLF
263270 ;
264271
265272
266 static ngx_str_t error_pages[] = {
267
268 ngx_null_string, /* 201, 204 */
273 static ngx_str_t ngx_http_error_pages[] = {
274
275 ngx_null_string, /* 201, 204 */
269276
270277 #define NGX_HTTP_LEVEL_200 1
271278
272 /* ngx_null_string, */ /* 300 */
273 ngx_string(error_301_page),
274 ngx_string(error_302_page),
275 ngx_null_string, /* 303 */
279 /* ngx_null_string, */ /* 300 */
280 ngx_string(ngx_http_error_301_page),
281 ngx_string(ngx_http_error_302_page),
282 ngx_null_string, /* 303 */
276283
277284 #define NGX_HTTP_LEVEL_300 3
278285
279 ngx_string(error_400_page),
280 ngx_string(error_401_page),
281 ngx_string(error_402_page),
282 ngx_string(error_403_page),
283 ngx_string(error_404_page),
284 ngx_string(error_405_page),
285 ngx_string(error_406_page),
286 ngx_null_string, /* 407 */
287 ngx_string(error_408_page),
288 ngx_string(error_409_page),
289 ngx_string(error_410_page),
290 ngx_string(error_411_page),
291 ngx_string(error_412_page),
292 ngx_string(error_413_page),
293 ngx_string(error_414_page),
294 ngx_string(error_415_page),
295 ngx_string(error_416_page),
286 ngx_string(ngx_http_error_400_page),
287 ngx_string(ngx_http_error_401_page),
288 ngx_string(ngx_http_error_402_page),
289 ngx_string(ngx_http_error_403_page),
290 ngx_string(ngx_http_error_404_page),
291 ngx_string(ngx_http_error_405_page),
292 ngx_string(ngx_http_error_406_page),
293 ngx_null_string, /* 407 */
294 ngx_string(ngx_http_error_408_page),
295 ngx_string(ngx_http_error_409_page),
296 ngx_string(ngx_http_error_410_page),
297 ngx_string(ngx_http_error_411_page),
298 ngx_string(ngx_http_error_412_page),
299 ngx_string(ngx_http_error_413_page),
300 ngx_string(ngx_http_error_414_page),
301 ngx_string(ngx_http_error_415_page),
302 ngx_string(ngx_http_error_416_page),
296303
297304 #define NGX_HTTP_LEVEL_400 17
298305
299 ngx_string(error_495_page), /* 495, https certificate error */
300 ngx_string(error_496_page), /* 496, https no certificate */
301 ngx_string(error_497_page), /* 497, http to https */
302 ngx_string(error_404_page), /* 498, invalid host name */
303 ngx_null_string, /* 499, client had closed connection */
304
305 ngx_string(error_500_page),
306 ngx_string(error_501_page),
307 ngx_string(error_502_page),
308 ngx_string(error_503_page),
309 ngx_string(error_504_page),
310 ngx_null_string, /* 505 */
311 ngx_null_string, /* 506 */
312 ngx_string(error_507_page)
306 ngx_string(ngx_http_error_495_page), /* 495, https certificate error */
307 ngx_string(ngx_http_error_496_page), /* 496, https no certificate */
308 ngx_string(ngx_http_error_497_page), /* 497, http to https */
309 ngx_string(ngx_http_error_404_page), /* 498, invalid host name */
310 ngx_null_string, /* 499, client has closed connection */
311
312 ngx_string(ngx_http_error_500_page),
313 ngx_string(ngx_http_error_501_page),
314 ngx_string(ngx_http_error_502_page),
315 ngx_string(ngx_http_error_503_page),
316 ngx_string(ngx_http_error_504_page),
317 ngx_null_string, /* 505 */
318 ngx_null_string, /* 506 */
319 ngx_string(ngx_http_error_507_page)
313320 };
314321
315322
319326 ngx_int_t
320327 ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
321328 {
322 u_char *p;
323 size_t msie_refresh;
324 uintptr_t escape;
325329 ngx_int_t rc;
326 ngx_buf_t *b;
327 ngx_str_t *uri, *location;
328 ngx_uint_t i, n, err, msie_padding;
329 ngx_chain_t *out, *cl;
330 ngx_uint_t i, err;
330331 ngx_http_err_page_t *err_page;
331332 ngx_http_core_loc_conf_t *clcf;
332333
377378 err_page = clcf->error_pages->elts;
378379
379380 for (i = 0; i < clcf->error_pages->nelts; i++) {
380
381381 if (err_page[i].status == error) {
382 r->err_status = err_page[i].overwrite;
383
384 r->method = NGX_HTTP_GET;
385 r->method_name = ngx_http_get_name;
386
387 uri = &err_page[i].uri;
388
389 if (err_page[i].uri_lengths) {
390 if (ngx_http_script_run(r, uri,
391 err_page[i].uri_lengths->elts, 0,
392 err_page[i].uri_values->elts)
393 == NULL)
394 {
395 return NGX_ERROR;
396 }
397
398 if (r->zero_in_uri) {
399 for (n = 0; n < uri->len; n++) {
400 if (uri->data[n] == '\0') {
401 goto zero;
402 }
403 }
404
405 r->zero_in_uri = 0;
406 }
407
408 } else {
409 r->zero_in_uri = 0;
410 }
411
412 zero:
413
414 if (uri->data[0] == '/') {
415 return ngx_http_internal_redirect(r, uri, NULL);
416 }
417
418 if (uri->data[0] == '@') {
419 return ngx_http_named_location(r, uri);
420 }
421
422 r->headers_out.location =
423 ngx_list_push(&r->headers_out.headers);
424
425 if (r->headers_out.location) {
426 error = NGX_HTTP_MOVED_TEMPORARILY;
427
428 r->err_status = NGX_HTTP_MOVED_TEMPORARILY;
429
430 r->headers_out.location->hash = 1;
431 r->headers_out.location->key.len = sizeof("Location") - 1;
432 r->headers_out.location->key.data = (u_char *) "Location";
433 r->headers_out.location->value = *uri;
434
435 } else {
436 return NGX_ERROR;
437 }
382 return ngx_http_send_error_page(r, &err_page[i]);
438383 }
439384 }
385 }
386
387 if (clcf->msie_refresh
388 && r->headers_in.msie
389 && (error == NGX_HTTP_MOVED_PERMANENTLY
390 || error == NGX_HTTP_MOVED_TEMPORARILY))
391 {
392 return ngx_http_send_refresh(r);
440393 }
441394
442395 if (error == NGX_HTTP_CREATED) {
467420 case NGX_HTTPS_CERT_ERROR:
468421 case NGX_HTTPS_NO_CERT:
469422 r->err_status = NGX_HTTP_BAD_REQUEST;
470 error = NGX_HTTP_BAD_REQUEST;
471423 break;
472424 }
473425 }
474426
427 return ngx_http_send_special_response(r, clcf, err);
428 }
429
430
431 static ngx_int_t
432 ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
433 {
434 u_char ch, *p, *last;
435 ngx_str_t *uri, *args, u, a;
436 ngx_table_elt_t *location;
437 ngx_http_core_loc_conf_t *clcf;
438
439 r->err_status = err_page->overwrite;
440
441 r->method = NGX_HTTP_GET;
442 r->method_name = ngx_http_get_name;
443
444 r->zero_in_uri = 0;
445
446 args = NULL;
447
448 if (err_page->uri_lengths) {
449 if (ngx_http_script_run(r, &u, err_page->uri_lengths->elts, 0,
450 err_page->uri_values->elts)
451 == NULL)
452 {
453 return NGX_ERROR;
454 }
455
456 p = u.data;
457 uri = &u;
458
459 if (*p == '/') {
460
461 last = p + uri->len;
462
463 while (p < last) {
464
465 ch = *p++;
466
467 if (ch == '?') {
468 a.len = last - p;
469 a.data = p;
470 args = &a;
471
472 u.len = p - 1 - u.data;
473
474 while (p < last) {
475 if (*p++ == '\0') {
476 r->zero_in_uri = 1;
477 break;
478 }
479 }
480
481 break;
482 }
483
484 if (ch == '\0') {
485 r->zero_in_uri = 1;
486 continue;
487 }
488 }
489 }
490
491 } else {
492 uri = &err_page->uri;
493 }
494
495 if (uri->data[0] == '/') {
496 return ngx_http_internal_redirect(r, uri, args);
497 }
498
499 if (uri->data[0] == '@') {
500 return ngx_http_named_location(r, uri);
501 }
502
503 location = ngx_list_push(&r->headers_out.headers);
504
505 if (location == NULL) {
506 return NGX_ERROR;
507 }
508
509 r->err_status = NGX_HTTP_MOVED_TEMPORARILY;
510
511 location->hash = 1;
512 location->key.len = sizeof("Location") - 1;
513 location->key.data = (u_char *) "Location";
514 location->value = *uri;
515
516 r->headers_out.location = location;
517
518 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
519
520 if (clcf->msie_refresh && r->headers_in.msie) {
521 return ngx_http_send_refresh(r);
522 }
523
524 return ngx_http_send_special_response(r, clcf, NGX_HTTP_MOVED_TEMPORARILY
525 - NGX_HTTP_MOVED_PERMANENTLY
526 + NGX_HTTP_LEVEL_200);
527 }
528
529
530 static ngx_int_t
531 ngx_http_send_special_response(ngx_http_request_t *r,
532 ngx_http_core_loc_conf_t *clcf, ngx_uint_t err)
533 {
534 u_char *tail;
535 size_t len;
536 ngx_int_t rc;
537 ngx_buf_t *b;
538 ngx_uint_t msie_padding;
539 ngx_chain_t out[3];
540
541 if (clcf->server_tokens) {
542 len = sizeof(ngx_http_error_full_tail) - 1;
543 tail = ngx_http_error_full_tail;
544
545 } else {
546 len = sizeof(ngx_http_error_tail) - 1;
547 tail = ngx_http_error_tail;
548 }
549
475550 msie_padding = 0;
476551
477552 if (!r->zero_body) {
478 if (error_pages[err].len) {
479 r->headers_out.content_length_n = error_pages[err].len
480 + (clcf->server_tokens ? sizeof(error_full_tail) - 1:
481 sizeof(error_tail) - 1);
482
553 if (ngx_http_error_pages[err].len) {
554 r->headers_out.content_length_n = ngx_http_error_pages[err].len
555 + len;
483556 if (clcf->msie_padding
484557 && r->headers_in.msie
485558 && r->http_version >= NGX_HTTP_VERSION_10
486 && error >= NGX_HTTP_BAD_REQUEST
487 && error != NGX_HTTP_REQUEST_URI_TOO_LARGE)
559 && err >= NGX_HTTP_LEVEL_300)
488560 {
489561 r->headers_out.content_length_n +=
490562 sizeof(ngx_http_msie_stub) - 1;
491563 msie_padding = 1;
492564 }
493565
566 r->headers_out.content_type_len = sizeof("text/html") - 1;
494567 r->headers_out.content_type.len = sizeof("text/html") - 1;
495568 r->headers_out.content_type.data = (u_char *) "text/html";
496569
508581 r->headers_out.content_length = NULL;
509582 }
510583
511 if (clcf->msie_refresh
512 && r->headers_in.msie
513 && (error == NGX_HTTP_MOVED_PERMANENTLY
514 || error == NGX_HTTP_MOVED_TEMPORARILY))
515 {
516
517 location = &r->headers_out.location->value;
518
519 escape = 2 * ngx_escape_uri(NULL, location->data, location->len,
520 NGX_ESCAPE_REFRESH);
521
522 msie_refresh = sizeof(ngx_http_msie_refresh_head) - 1
523 + escape + location->len
524 + sizeof(ngx_http_msie_refresh_tail) - 1;
525
526 r->err_status = NGX_HTTP_OK;
527 r->headers_out.content_type_len = sizeof("text/html") - 1;
528 r->headers_out.content_length_n = msie_refresh;
529 r->headers_out.location->hash = 0;
530 r->headers_out.location = NULL;
531
532 } else {
533 location = NULL;
534 escape = 0;
535 msie_refresh = 0;
536 }
537
538584 ngx_http_clear_accept_ranges(r);
539585 ngx_http_clear_last_modified(r);
540586
544590 return rc;
545591 }
546592
547
548 if (msie_refresh == 0) {
549
550 if (error_pages[err].len == 0) {
551 return NGX_OK;
552 }
553
593 if (ngx_http_error_pages[err].len == 0) {
594 return NGX_OK;
595 }
596
597 b = ngx_calloc_buf(r->pool);
598 if (b == NULL) {
599 return NGX_ERROR;
600 }
601
602 b->memory = 1;
603 b->pos = ngx_http_error_pages[err].data;
604 b->last = ngx_http_error_pages[err].data + ngx_http_error_pages[err].len;
605
606 out[0].buf = b;
607 out[0].next = &out[1];
608
609 b = ngx_calloc_buf(r->pool);
610 if (b == NULL) {
611 return NGX_ERROR;
612 }
613
614 b->memory = 1;
615
616 b->pos = tail;
617 b->last = tail + len;
618
619 out[1].buf = b;
620 out[1].next = NULL;;
621
622 if (msie_padding) {
554623 b = ngx_calloc_buf(r->pool);
555624 if (b == NULL) {
556625 return NGX_ERROR;
557626 }
558627
559628 b->memory = 1;
560 b->pos = error_pages[err].data;
561 b->last = error_pages[err].data + error_pages[err].len;
562
563 cl = ngx_alloc_chain_link(r->pool);
564 if (cl == NULL) {
565 return NGX_ERROR;
566 }
567
568 cl->buf = b;
569 out = cl;
570
571
572 b = ngx_calloc_buf(r->pool);
573 if (b == NULL) {
574 return NGX_ERROR;
575 }
576
577 b->memory = 1;
578
579 if (clcf->server_tokens) {
580 b->pos = error_full_tail;
581 b->last = error_full_tail + sizeof(error_full_tail) - 1;
582 } else {
583 b->pos = error_tail;
584 b->last = error_tail + sizeof(error_tail) - 1;
585 }
586
587 cl->next = ngx_alloc_chain_link(r->pool);
588 if (cl->next == NULL) {
589 return NGX_ERROR;
590 }
591
592 cl = cl->next;
593 cl->buf = b;
594
595 if (msie_padding) {
596 b = ngx_calloc_buf(r->pool);
597 if (b == NULL) {
598 return NGX_ERROR;
599 }
600
601 b->memory = 1;
602 b->pos = ngx_http_msie_stub;
603 b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1;
604
605 cl->next = ngx_alloc_chain_link(r->pool);
606 if (cl->next == NULL) {
607 return NGX_ERROR;
608 }
609
610 cl = cl->next;
611 cl->buf = b;
612 }
613
614 } else {
615 b = ngx_create_temp_buf(r->pool, msie_refresh);
616 if (b == NULL) {
617 return NGX_ERROR;
618 }
619
620 p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head,
621 sizeof(ngx_http_msie_refresh_head) - 1);
622
623 if (escape == 0) {
624 p = ngx_cpymem(p, location->data, location->len);
625
626 } else {
627 p = (u_char *) ngx_escape_uri(p, location->data, location->len,
628 NGX_ESCAPE_REFRESH);
629 }
630
631 b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail,
632 sizeof(ngx_http_msie_refresh_tail) - 1);
633
634 cl = ngx_alloc_chain_link(r->pool);
635 if (cl == NULL) {
636 return NGX_ERROR;
637 }
638
639 cl->buf = b;
640 out = cl;
629 b->pos = ngx_http_msie_stub;
630 b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1;
631
632 out[1].next = &out[2];
633 out[2].buf = b;
634 out[2].next = NULL;;
641635 }
642636
643637 if (r == r->main) {
646640
647641 b->last_in_chain = 1;
648642
649 cl->next = NULL;
650
651 return ngx_http_output_filter(r, out);
643 return ngx_http_output_filter(r, &out[0]);
652644 }
645
646
647 static ngx_int_t
648 ngx_http_send_refresh(ngx_http_request_t *r)
649 {
650 u_char *p, *location;
651 size_t len, size;
652 uintptr_t escape;
653 ngx_int_t rc;
654 ngx_buf_t *b;
655 ngx_chain_t out;
656
657 len = r->headers_out.location->value.len;
658 location = r->headers_out.location->value.data;
659
660 escape = 2 * ngx_escape_uri(NULL, location, len, NGX_ESCAPE_REFRESH);
661
662 size = sizeof(ngx_http_msie_refresh_head) - 1
663 + escape + len
664 + sizeof(ngx_http_msie_refresh_tail) - 1;
665
666 r->err_status = NGX_HTTP_OK;
667
668 r->headers_out.content_type_len = sizeof("text/html") - 1;
669 r->headers_out.content_type.len = sizeof("text/html") - 1;
670 r->headers_out.content_type.data = (u_char *) "text/html";
671
672 r->headers_out.location->hash = 0;
673 r->headers_out.location = NULL;
674
675 r->headers_out.content_length_n = size;
676
677 if (r->headers_out.content_length) {
678 r->headers_out.content_length->hash = 0;
679 r->headers_out.content_length = NULL;
680 }
681
682 ngx_http_clear_accept_ranges(r);
683 ngx_http_clear_last_modified(r);
684
685 rc = ngx_http_send_header(r);
686
687 if (rc == NGX_ERROR || r->header_only) {
688 return rc;
689 }
690
691 b = ngx_create_temp_buf(r->pool, size);
692 if (b == NULL) {
693 return NGX_ERROR;
694 }
695
696 p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head,
697 sizeof(ngx_http_msie_refresh_head) - 1);
698
699 if (escape == 0) {
700 p = ngx_cpymem(p, location, len);
701
702 } else {
703 p = (u_char *) ngx_escape_uri(p, location, len, NGX_ESCAPE_REFRESH);
704 }
705
706 b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail,
707 sizeof(ngx_http_msie_refresh_tail) - 1);
708
709 b->last_buf = 1;
710 b->last_in_chain = 1;
711
712 out.buf = b;
713 out.next = NULL;
714
715 return ngx_http_output_filter(r, &out);
716 }