Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_special_response.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 #include <nginx.h>
12 
13 
14 static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r,
15  ngx_http_err_page_t *err_page);
16 static ngx_int_t ngx_http_send_special_response(ngx_http_request_t *r,
18 static ngx_int_t ngx_http_send_refresh(ngx_http_request_t *r);
19 
20 
21 static u_char ngx_http_error_full_tail[] =
22 "<hr><center>" NGINX_VER "</center>" CRLF
23 "</body>" CRLF
24 "</html>" CRLF
25 ;
26 
27 
28 static u_char ngx_http_error_tail[] =
29 "<hr><center>nginx</center>" CRLF
30 "</body>" CRLF
31 "</html>" CRLF
32 ;
33 
34 
35 static u_char ngx_http_msie_padding[] =
36 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
37 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
38 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
39 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
40 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
41 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
42 ;
43 
44 
45 static u_char ngx_http_msie_refresh_head[] =
46 "<html><head><meta http-equiv=\"Refresh\" content=\"0; URL=";
47 
48 
49 static u_char ngx_http_msie_refresh_tail[] =
50 "\"></head><body></body></html>" CRLF;
51 
52 
53 static char ngx_http_error_301_page[] =
54 "<html>" CRLF
55 "<head><title>301 Moved Permanently</title></head>" CRLF
56 "<body bgcolor=\"white\">" CRLF
57 "<center><h1>301 Moved Permanently</h1></center>" CRLF
58 ;
59 
60 
61 static char ngx_http_error_302_page[] =
62 "<html>" CRLF
63 "<head><title>302 Found</title></head>" CRLF
64 "<body bgcolor=\"white\">" CRLF
65 "<center><h1>302 Found</h1></center>" CRLF
66 ;
67 
68 
69 static char ngx_http_error_303_page[] =
70 "<html>" CRLF
71 "<head><title>303 See Other</title></head>" CRLF
72 "<body bgcolor=\"white\">" CRLF
73 "<center><h1>303 See Other</h1></center>" CRLF
74 ;
75 
76 
77 static char ngx_http_error_307_page[] =
78 "<html>" CRLF
79 "<head><title>307 Temporary Redirect</title></head>" CRLF
80 "<body bgcolor=\"white\">" CRLF
81 "<center><h1>307 Temporary Redirect</h1></center>" CRLF
82 ;
83 
84 
85 static char ngx_http_error_400_page[] =
86 "<html>" CRLF
87 "<head><title>400 Bad Request</title></head>" CRLF
88 "<body bgcolor=\"white\">" CRLF
89 "<center><h1>400 Bad Request</h1></center>" CRLF
90 ;
91 
92 
93 static char ngx_http_error_401_page[] =
94 "<html>" CRLF
95 "<head><title>401 Authorization Required</title></head>" CRLF
96 "<body bgcolor=\"white\">" CRLF
97 "<center><h1>401 Authorization Required</h1></center>" CRLF
98 ;
99 
100 
101 static char ngx_http_error_402_page[] =
102 "<html>" CRLF
103 "<head><title>402 Payment Required</title></head>" CRLF
104 "<body bgcolor=\"white\">" CRLF
105 "<center><h1>402 Payment Required</h1></center>" CRLF
106 ;
107 
108 
109 static char ngx_http_error_403_page[] =
110 "<html>" CRLF
111 "<head><title>403 Forbidden</title></head>" CRLF
112 "<body bgcolor=\"white\">" CRLF
113 "<center><h1>403 Forbidden</h1></center>" CRLF
114 ;
115 
116 
117 static char ngx_http_error_404_page[] =
118 "<html>" CRLF
119 "<head><title>404 Not Found</title></head>" CRLF
120 "<body bgcolor=\"white\">" CRLF
121 "<center><h1>404 Not Found</h1></center>" CRLF
122 ;
123 
124 
125 static char ngx_http_error_405_page[] =
126 "<html>" CRLF
127 "<head><title>405 Not Allowed</title></head>" CRLF
128 "<body bgcolor=\"white\">" CRLF
129 "<center><h1>405 Not Allowed</h1></center>" CRLF
130 ;
131 
132 
133 static char ngx_http_error_406_page[] =
134 "<html>" CRLF
135 "<head><title>406 Not Acceptable</title></head>" CRLF
136 "<body bgcolor=\"white\">" CRLF
137 "<center><h1>406 Not Acceptable</h1></center>" CRLF
138 ;
139 
140 
141 static char ngx_http_error_408_page[] =
142 "<html>" CRLF
143 "<head><title>408 Request Time-out</title></head>" CRLF
144 "<body bgcolor=\"white\">" CRLF
145 "<center><h1>408 Request Time-out</h1></center>" CRLF
146 ;
147 
148 
149 static char ngx_http_error_409_page[] =
150 "<html>" CRLF
151 "<head><title>409 Conflict</title></head>" CRLF
152 "<body bgcolor=\"white\">" CRLF
153 "<center><h1>409 Conflict</h1></center>" CRLF
154 ;
155 
156 
157 static char ngx_http_error_410_page[] =
158 "<html>" CRLF
159 "<head><title>410 Gone</title></head>" CRLF
160 "<body bgcolor=\"white\">" CRLF
161 "<center><h1>410 Gone</h1></center>" CRLF
162 ;
163 
164 
165 static char ngx_http_error_411_page[] =
166 "<html>" CRLF
167 "<head><title>411 Length Required</title></head>" CRLF
168 "<body bgcolor=\"white\">" CRLF
169 "<center><h1>411 Length Required</h1></center>" CRLF
170 ;
171 
172 
173 static char ngx_http_error_412_page[] =
174 "<html>" CRLF
175 "<head><title>412 Precondition Failed</title></head>" CRLF
176 "<body bgcolor=\"white\">" CRLF
177 "<center><h1>412 Precondition Failed</h1></center>" CRLF
178 ;
179 
180 
181 static char ngx_http_error_413_page[] =
182 "<html>" CRLF
183 "<head><title>413 Request Entity Too Large</title></head>" CRLF
184 "<body bgcolor=\"white\">" CRLF
185 "<center><h1>413 Request Entity Too Large</h1></center>" CRLF
186 ;
187 
188 
189 static char ngx_http_error_414_page[] =
190 "<html>" CRLF
191 "<head><title>414 Request-URI Too Large</title></head>" CRLF
192 "<body bgcolor=\"white\">" CRLF
193 "<center><h1>414 Request-URI Too Large</h1></center>" CRLF
194 ;
195 
196 
197 static char ngx_http_error_415_page[] =
198 "<html>" CRLF
199 "<head><title>415 Unsupported Media Type</title></head>" CRLF
200 "<body bgcolor=\"white\">" CRLF
201 "<center><h1>415 Unsupported Media Type</h1></center>" CRLF
202 ;
203 
204 
205 static char ngx_http_error_416_page[] =
206 "<html>" CRLF
207 "<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF
208 "<body bgcolor=\"white\">" CRLF
209 "<center><h1>416 Requested Range Not Satisfiable</h1></center>" CRLF
210 ;
211 
212 
213 static char ngx_http_error_494_page[] =
214 "<html>" CRLF
215 "<head><title>400 Request Header Or Cookie Too Large</title></head>"
216 CRLF
217 "<body bgcolor=\"white\">" CRLF
218 "<center><h1>400 Bad Request</h1></center>" CRLF
219 "<center>Request Header Or Cookie Too Large</center>" CRLF
220 ;
221 
222 
223 static char ngx_http_error_495_page[] =
224 "<html>" CRLF
225 "<head><title>400 The SSL certificate error</title></head>"
226 CRLF
227 "<body bgcolor=\"white\">" CRLF
228 "<center><h1>400 Bad Request</h1></center>" CRLF
229 "<center>The SSL certificate error</center>" CRLF
230 ;
231 
232 
233 static char ngx_http_error_496_page[] =
234 "<html>" CRLF
235 "<head><title>400 No required SSL certificate was sent</title></head>"
236 CRLF
237 "<body bgcolor=\"white\">" CRLF
238 "<center><h1>400 Bad Request</h1></center>" CRLF
239 "<center>No required SSL certificate was sent</center>" CRLF
240 ;
241 
242 
243 static char ngx_http_error_497_page[] =
244 "<html>" CRLF
245 "<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>"
246 CRLF
247 "<body bgcolor=\"white\">" CRLF
248 "<center><h1>400 Bad Request</h1></center>" CRLF
249 "<center>The plain HTTP request was sent to HTTPS port</center>" CRLF
250 ;
251 
252 
253 static char ngx_http_error_500_page[] =
254 "<html>" CRLF
255 "<head><title>500 Internal Server Error</title></head>" CRLF
256 "<body bgcolor=\"white\">" CRLF
257 "<center><h1>500 Internal Server Error</h1></center>" CRLF
258 ;
259 
260 
261 static char ngx_http_error_501_page[] =
262 "<html>" CRLF
263 "<head><title>501 Not Implemented</title></head>" CRLF
264 "<body bgcolor=\"white\">" CRLF
265 "<center><h1>501 Not Implemented</h1></center>" CRLF
266 ;
267 
268 
269 static char ngx_http_error_502_page[] =
270 "<html>" CRLF
271 "<head><title>502 Bad Gateway</title></head>" CRLF
272 "<body bgcolor=\"white\">" CRLF
273 "<center><h1>502 Bad Gateway</h1></center>" CRLF
274 ;
275 
276 
277 static char ngx_http_error_503_page[] =
278 "<html>" CRLF
279 "<head><title>503 Service Temporarily Unavailable</title></head>" CRLF
280 "<body bgcolor=\"white\">" CRLF
281 "<center><h1>503 Service Temporarily Unavailable</h1></center>" CRLF
282 ;
283 
284 
285 static char ngx_http_error_504_page[] =
286 "<html>" CRLF
287 "<head><title>504 Gateway Time-out</title></head>" CRLF
288 "<body bgcolor=\"white\">" CRLF
289 "<center><h1>504 Gateway Time-out</h1></center>" CRLF
290 ;
291 
292 
293 static char ngx_http_error_507_page[] =
294 "<html>" CRLF
295 "<head><title>507 Insufficient Storage</title></head>" CRLF
296 "<body bgcolor=\"white\">" CRLF
297 "<center><h1>507 Insufficient Storage</h1></center>" CRLF
298 ;
299 
300 
301 static ngx_str_t ngx_http_error_pages[] = {
302 
303  ngx_null_string, /* 201, 204 */
304 
305 #define NGX_HTTP_LAST_2XX 202
306 #define NGX_HTTP_OFF_3XX (NGX_HTTP_LAST_2XX - 201)
307 
308  /* ngx_null_string, */ /* 300 */
309  ngx_string(ngx_http_error_301_page),
310  ngx_string(ngx_http_error_302_page),
311  ngx_string(ngx_http_error_303_page),
312  ngx_null_string, /* 304 */
313  ngx_null_string, /* 305 */
314  ngx_null_string, /* 306 */
315  ngx_string(ngx_http_error_307_page),
316 
317 #define NGX_HTTP_LAST_3XX 308
318 #define NGX_HTTP_OFF_4XX (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX)
319 
320  ngx_string(ngx_http_error_400_page),
321  ngx_string(ngx_http_error_401_page),
322  ngx_string(ngx_http_error_402_page),
323  ngx_string(ngx_http_error_403_page),
324  ngx_string(ngx_http_error_404_page),
325  ngx_string(ngx_http_error_405_page),
326  ngx_string(ngx_http_error_406_page),
327  ngx_null_string, /* 407 */
328  ngx_string(ngx_http_error_408_page),
329  ngx_string(ngx_http_error_409_page),
330  ngx_string(ngx_http_error_410_page),
331  ngx_string(ngx_http_error_411_page),
332  ngx_string(ngx_http_error_412_page),
333  ngx_string(ngx_http_error_413_page),
334  ngx_string(ngx_http_error_414_page),
335  ngx_string(ngx_http_error_415_page),
336  ngx_string(ngx_http_error_416_page),
337 
338 #define NGX_HTTP_LAST_4XX 417
339 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX)
340 
341  ngx_string(ngx_http_error_494_page), /* 494, request header too large */
342  ngx_string(ngx_http_error_495_page), /* 495, https certificate error */
343  ngx_string(ngx_http_error_496_page), /* 496, https no certificate */
344  ngx_string(ngx_http_error_497_page), /* 497, http to https */
345  ngx_string(ngx_http_error_404_page), /* 498, canceled */
346  ngx_null_string, /* 499, client has closed connection */
347 
348  ngx_string(ngx_http_error_500_page),
349  ngx_string(ngx_http_error_501_page),
350  ngx_string(ngx_http_error_502_page),
351  ngx_string(ngx_http_error_503_page),
352  ngx_string(ngx_http_error_504_page),
353  ngx_null_string, /* 505 */
354  ngx_null_string, /* 506 */
355  ngx_string(ngx_http_error_507_page)
356 
357 #define NGX_HTTP_LAST_5XX 508
358 
359 };
360 
361 
362 static ngx_str_t ngx_http_get_name = { 3, (u_char *) "GET " };
363 
364 
365 ngx_int_t
367 {
368  ngx_uint_t i, err;
369  ngx_http_err_page_t *err_page;
371 
373  "http special response: %d, \"%V?%V\"",
374  error, &r->uri, &r->args);
375 
376  r->err_status = error;
377 
378  if (r->keepalive) {
379  switch (error) {
383  case NGX_HTTP_TO_HTTPS:
385  case NGX_HTTPS_NO_CERT:
388  r->keepalive = 0;
389  }
390  }
391 
392  if (r->lingering_close) {
393  switch (error) {
395  case NGX_HTTP_TO_HTTPS:
397  case NGX_HTTPS_NO_CERT:
398  r->lingering_close = 0;
399  }
400  }
401 
403 
405 
406  if (!r->error_page && clcf->error_pages && r->uri_changes != 0) {
407 
408  if (clcf->recursive_error_pages == 0) {
409  r->error_page = 1;
410  }
411 
412  err_page = clcf->error_pages->elts;
413 
414  for (i = 0; i < clcf->error_pages->nelts; i++) {
415  if (err_page[i].status == error) {
416  return ngx_http_send_error_page(r, &err_page[i]);
417  }
418  }
419  }
420 
421  r->expect_tested = 1;
422 
424  r->keepalive = 0;
425  }
426 
427  if (clcf->msie_refresh
428  && r->headers_in.msie
429  && (error == NGX_HTTP_MOVED_PERMANENTLY
430  || error == NGX_HTTP_MOVED_TEMPORARILY))
431  {
432  return ngx_http_send_refresh(r);
433  }
434 
435  if (error == NGX_HTTP_CREATED) {
436  /* 201 */
437  err = 0;
438 
439  } else if (error == NGX_HTTP_NO_CONTENT) {
440  /* 204 */
441  err = 0;
442 
443  } else if (error >= NGX_HTTP_MOVED_PERMANENTLY
444  && error < NGX_HTTP_LAST_3XX)
445  {
446  /* 3XX */
448 
449  } else if (error >= NGX_HTTP_BAD_REQUEST
450  && error < NGX_HTTP_LAST_4XX)
451  {
452  /* 4XX */
453  err = error - NGX_HTTP_BAD_REQUEST + NGX_HTTP_OFF_4XX;
454 
455  } else if (error >= NGX_HTTP_NGINX_CODES
456  && error < NGX_HTTP_LAST_5XX)
457  {
458  /* 49X, 5XX */
459  err = error - NGX_HTTP_NGINX_CODES + NGX_HTTP_OFF_5XX;
460  switch (error) {
461  case NGX_HTTP_TO_HTTPS:
463  case NGX_HTTPS_NO_CERT:
466  break;
467  }
468 
469  } else {
470  /* unknown code, zero body */
471  err = 0;
472  }
473 
474  return ngx_http_send_special_response(r, clcf, err);
475 }
476 
477 
478 ngx_int_t
481 {
482  void *ctx;
483  ngx_int_t rc;
484 
486 
487  ctx = NULL;
488 
489  if (m) {
490  ctx = r->ctx[m->ctx_index];
491  }
492 
493  /* clear the modules contexts */
494  ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
495 
496  if (m) {
497  r->ctx[m->ctx_index] = ctx;
498  }
499 
500  r->filter_finalize = 1;
501 
502  rc = ngx_http_special_response_handler(r, error);
503 
504  /* NGX_ERROR resets any pending data */
505 
506  switch (rc) {
507 
508  case NGX_OK:
509  case NGX_DONE:
510  return NGX_ERROR;
511 
512  default:
513  return rc;
514  }
515 }
516 
517 
518 void
520 {
522  sizeof(ngx_http_headers_out_t)
523  - offsetof(ngx_http_headers_out_t, status));
524 
525  r->headers_out.headers.part.nelts = 0;
526  r->headers_out.headers.part.next = NULL;
528 
531 }
532 
533 
534 static ngx_int_t
535 ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
536 {
537  ngx_int_t overwrite;
538  ngx_str_t uri, args;
539  ngx_table_elt_t *location;
541 
542  overwrite = err_page->overwrite;
543 
544  if (overwrite && overwrite != NGX_HTTP_OK) {
545  r->expect_tested = 1;
546  }
547 
548  if (overwrite >= 0) {
549  r->err_status = overwrite;
550  }
551 
552  if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) {
553  return NGX_ERROR;
554  }
555 
556  if (uri.data[0] == '/') {
557 
558  if (err_page->value.lengths) {
559  ngx_http_split_args(r, &uri, &args);
560 
561  } else {
562  args = err_page->args;
563  }
564 
565  if (r->method != NGX_HTTP_HEAD) {
566  r->method = NGX_HTTP_GET;
567  r->method_name = ngx_http_get_name;
568  }
569 
570  return ngx_http_internal_redirect(r, &uri, &args);
571  }
572 
573  if (uri.data[0] == '@') {
574  return ngx_http_named_location(r, &uri);
575  }
576 
577  location = ngx_list_push(&r->headers_out.headers);
578 
579  if (location == NULL) {
580  return NGX_ERROR;
581  }
582 
583  if (overwrite != NGX_HTTP_MOVED_PERMANENTLY
584  && overwrite != NGX_HTTP_MOVED_TEMPORARILY
585  && overwrite != NGX_HTTP_SEE_OTHER
586  && overwrite != NGX_HTTP_TEMPORARY_REDIRECT)
587  {
589  }
590 
591  location->hash = 1;
592  ngx_str_set(&location->key, "Location");
593  location->value = uri;
594 
596 
597  r->headers_out.location = location;
598 
600 
601  if (clcf->msie_refresh && r->headers_in.msie) {
602  return ngx_http_send_refresh(r);
603  }
604 
605  return ngx_http_send_special_response(r, clcf, r->err_status
607  + NGX_HTTP_OFF_3XX);
608 }
609 
610 
611 static ngx_int_t
612 ngx_http_send_special_response(ngx_http_request_t *r,
614 {
615  u_char *tail;
616  size_t len;
617  ngx_int_t rc;
618  ngx_buf_t *b;
619  ngx_uint_t msie_padding;
620  ngx_chain_t out[3];
621 
622  if (clcf->server_tokens) {
623  len = sizeof(ngx_http_error_full_tail) - 1;
624  tail = ngx_http_error_full_tail;
625 
626  } else {
627  len = sizeof(ngx_http_error_tail) - 1;
628  tail = ngx_http_error_tail;
629  }
630 
631  msie_padding = 0;
632 
633  if (ngx_http_error_pages[err].len) {
634  r->headers_out.content_length_n = ngx_http_error_pages[err].len + len;
635  if (clcf->msie_padding
636  && (r->headers_in.msie || r->headers_in.chrome)
638  && err >= NGX_HTTP_OFF_4XX)
639  {
641  sizeof(ngx_http_msie_padding) - 1;
642  msie_padding = 1;
643  }
644 
645  r->headers_out.content_type_len = sizeof("text/html") - 1;
646  ngx_str_set(&r->headers_out.content_type, "text/html");
648 
649  } else {
651  }
652 
653  if (r->headers_out.content_length) {
655  r->headers_out.content_length = NULL;
656  }
657 
661 
662  rc = ngx_http_send_header(r);
663 
664  if (rc == NGX_ERROR || r->header_only) {
665  return rc;
666  }
667 
668  if (ngx_http_error_pages[err].len == 0) {
670  }
671 
672  b = ngx_calloc_buf(r->pool);
673  if (b == NULL) {
674  return NGX_ERROR;
675  }
676 
677  b->memory = 1;
678  b->pos = ngx_http_error_pages[err].data;
679  b->last = ngx_http_error_pages[err].data + ngx_http_error_pages[err].len;
680 
681  out[0].buf = b;
682  out[0].next = &out[1];
683 
684  b = ngx_calloc_buf(r->pool);
685  if (b == NULL) {
686  return NGX_ERROR;
687  }
688 
689  b->memory = 1;
690 
691  b->pos = tail;
692  b->last = tail + len;
693 
694  out[1].buf = b;
695  out[1].next = NULL;
696 
697  if (msie_padding) {
698  b = ngx_calloc_buf(r->pool);
699  if (b == NULL) {
700  return NGX_ERROR;
701  }
702 
703  b->memory = 1;
704  b->pos = ngx_http_msie_padding;
705  b->last = ngx_http_msie_padding + sizeof(ngx_http_msie_padding) - 1;
706 
707  out[1].next = &out[2];
708  out[2].buf = b;
709  out[2].next = NULL;
710  }
711 
712  if (r == r->main) {
713  b->last_buf = 1;
714  }
715 
716  b->last_in_chain = 1;
717 
718  return ngx_http_output_filter(r, &out[0]);
719 }
720 
721 
722 static ngx_int_t
723 ngx_http_send_refresh(ngx_http_request_t *r)
724 {
725  u_char *p, *location;
726  size_t len, size;
727  uintptr_t escape;
728  ngx_int_t rc;
729  ngx_buf_t *b;
730  ngx_chain_t out;
731 
732  len = r->headers_out.location->value.len;
733  location = r->headers_out.location->value.data;
734 
735  escape = 2 * ngx_escape_uri(NULL, location, len, NGX_ESCAPE_REFRESH);
736 
737  size = sizeof(ngx_http_msie_refresh_head) - 1
738  + escape + len
739  + sizeof(ngx_http_msie_refresh_tail) - 1;
740 
741  r->err_status = NGX_HTTP_OK;
742 
743  r->headers_out.content_type_len = sizeof("text/html") - 1;
744  ngx_str_set(&r->headers_out.content_type, "text/html");
746 
747  r->headers_out.location->hash = 0;
748  r->headers_out.location = NULL;
749 
750  r->headers_out.content_length_n = size;
751 
752  if (r->headers_out.content_length) {
754  r->headers_out.content_length = NULL;
755  }
756 
760 
761  rc = ngx_http_send_header(r);
762 
763  if (rc == NGX_ERROR || r->header_only) {
764  return rc;
765  }
766 
767  b = ngx_create_temp_buf(r->pool, size);
768  if (b == NULL) {
769  return NGX_ERROR;
770  }
771 
772  p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head,
773  sizeof(ngx_http_msie_refresh_head) - 1);
774 
775  if (escape == 0) {
776  p = ngx_cpymem(p, location, len);
777 
778  } else {
779  p = (u_char *) ngx_escape_uri(p, location, len, NGX_ESCAPE_REFRESH);
780  }
781 
782  b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail,
783  sizeof(ngx_http_msie_refresh_tail) - 1);
784 
785  b->last_buf = 1;
786  b->last_in_chain = 1;
787 
788  out.buf = b;
789  out.next = NULL;
790 
791  return ngx_http_output_filter(r, &out);
792 }