Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 #include <nginx.h>
0012 
0013 
0014 static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r,
0015     ngx_http_err_page_t *err_page);
0016 static ngx_int_t ngx_http_send_special_response(ngx_http_request_t *r,
0017     ngx_http_core_loc_conf_t *clcf, ngx_uint_t err);
0018 static ngx_int_t ngx_http_send_refresh(ngx_http_request_t *r);
0019 
0020 
0021 static u_char ngx_http_error_full_tail[] =
0022 "<hr><center>" NGINX_VER "</center>" CRLF
0023 "</body>" CRLF
0024 "</html>" CRLF
0025 ;
0026 
0027 
0028 static u_char ngx_http_error_build_tail[] =
0029 "<hr><center>" NGINX_VER_BUILD "</center>" CRLF
0030 "</body>" CRLF
0031 "</html>" CRLF
0032 ;
0033 
0034 
0035 static u_char ngx_http_error_tail[] =
0036 "<hr><center>nginx</center>" CRLF
0037 "</body>" CRLF
0038 "</html>" CRLF
0039 ;
0040 
0041 
0042 static u_char ngx_http_msie_padding[] =
0043 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
0044 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
0045 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
0046 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
0047 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
0048 "<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
0049 ;
0050 
0051 
0052 static u_char ngx_http_msie_refresh_head[] =
0053 "<html><head><meta http-equiv=\"Refresh\" content=\"0; URL=";
0054 
0055 
0056 static u_char ngx_http_msie_refresh_tail[] =
0057 "\"></head><body></body></html>" CRLF;
0058 
0059 
0060 static char ngx_http_error_301_page[] =
0061 "<html>" CRLF
0062 "<head><title>301 Moved Permanently</title></head>" CRLF
0063 "<body bgcolor=\"white\">" CRLF
0064 "<center><h1>301 Moved Permanently</h1></center>" CRLF
0065 ;
0066 
0067 
0068 static char ngx_http_error_302_page[] =
0069 "<html>" CRLF
0070 "<head><title>302 Found</title></head>" CRLF
0071 "<body bgcolor=\"white\">" CRLF
0072 "<center><h1>302 Found</h1></center>" CRLF
0073 ;
0074 
0075 
0076 static char ngx_http_error_303_page[] =
0077 "<html>" CRLF
0078 "<head><title>303 See Other</title></head>" CRLF
0079 "<body bgcolor=\"white\">" CRLF
0080 "<center><h1>303 See Other</h1></center>" CRLF
0081 ;
0082 
0083 
0084 static char ngx_http_error_307_page[] =
0085 "<html>" CRLF
0086 "<head><title>307 Temporary Redirect</title></head>" CRLF
0087 "<body bgcolor=\"white\">" CRLF
0088 "<center><h1>307 Temporary Redirect</h1></center>" CRLF
0089 ;
0090 
0091 
0092 static char ngx_http_error_400_page[] =
0093 "<html>" CRLF
0094 "<head><title>400 Bad Request</title></head>" CRLF
0095 "<body bgcolor=\"white\">" CRLF
0096 "<center><h1>400 Bad Request</h1></center>" CRLF
0097 ;
0098 
0099 
0100 static char ngx_http_error_401_page[] =
0101 "<html>" CRLF
0102 "<head><title>401 Authorization Required</title></head>" CRLF
0103 "<body bgcolor=\"white\">" CRLF
0104 "<center><h1>401 Authorization Required</h1></center>" CRLF
0105 ;
0106 
0107 
0108 static char ngx_http_error_402_page[] =
0109 "<html>" CRLF
0110 "<head><title>402 Payment Required</title></head>" CRLF
0111 "<body bgcolor=\"white\">" CRLF
0112 "<center><h1>402 Payment Required</h1></center>" CRLF
0113 ;
0114 
0115 
0116 static char ngx_http_error_403_page[] =
0117 "<html>" CRLF
0118 "<head><title>403 Forbidden</title></head>" CRLF
0119 "<body bgcolor=\"white\">" CRLF
0120 "<center><h1>403 Forbidden</h1></center>" CRLF
0121 ;
0122 
0123 
0124 static char ngx_http_error_404_page[] =
0125 "<html>" CRLF
0126 "<head><title>404 Not Found</title></head>" CRLF
0127 "<body bgcolor=\"white\">" CRLF
0128 "<center><h1>404 Not Found</h1></center>" CRLF
0129 ;
0130 
0131 
0132 static char ngx_http_error_405_page[] =
0133 "<html>" CRLF
0134 "<head><title>405 Not Allowed</title></head>" CRLF
0135 "<body bgcolor=\"white\">" CRLF
0136 "<center><h1>405 Not Allowed</h1></center>" CRLF
0137 ;
0138 
0139 
0140 static char ngx_http_error_406_page[] =
0141 "<html>" CRLF
0142 "<head><title>406 Not Acceptable</title></head>" CRLF
0143 "<body bgcolor=\"white\">" CRLF
0144 "<center><h1>406 Not Acceptable</h1></center>" CRLF
0145 ;
0146 
0147 
0148 static char ngx_http_error_408_page[] =
0149 "<html>" CRLF
0150 "<head><title>408 Request Time-out</title></head>" CRLF
0151 "<body bgcolor=\"white\">" CRLF
0152 "<center><h1>408 Request Time-out</h1></center>" CRLF
0153 ;
0154 
0155 
0156 static char ngx_http_error_409_page[] =
0157 "<html>" CRLF
0158 "<head><title>409 Conflict</title></head>" CRLF
0159 "<body bgcolor=\"white\">" CRLF
0160 "<center><h1>409 Conflict</h1></center>" CRLF
0161 ;
0162 
0163 
0164 static char ngx_http_error_410_page[] =
0165 "<html>" CRLF
0166 "<head><title>410 Gone</title></head>" CRLF
0167 "<body bgcolor=\"white\">" CRLF
0168 "<center><h1>410 Gone</h1></center>" CRLF
0169 ;
0170 
0171 
0172 static char ngx_http_error_411_page[] =
0173 "<html>" CRLF
0174 "<head><title>411 Length Required</title></head>" CRLF
0175 "<body bgcolor=\"white\">" CRLF
0176 "<center><h1>411 Length Required</h1></center>" CRLF
0177 ;
0178 
0179 
0180 static char ngx_http_error_412_page[] =
0181 "<html>" CRLF
0182 "<head><title>412 Precondition Failed</title></head>" CRLF
0183 "<body bgcolor=\"white\">" CRLF
0184 "<center><h1>412 Precondition Failed</h1></center>" CRLF
0185 ;
0186 
0187 
0188 static char ngx_http_error_413_page[] =
0189 "<html>" CRLF
0190 "<head><title>413 Request Entity Too Large</title></head>" CRLF
0191 "<body bgcolor=\"white\">" CRLF
0192 "<center><h1>413 Request Entity Too Large</h1></center>" CRLF
0193 ;
0194 
0195 
0196 static char ngx_http_error_414_page[] =
0197 "<html>" CRLF
0198 "<head><title>414 Request-URI Too Large</title></head>" CRLF
0199 "<body bgcolor=\"white\">" CRLF
0200 "<center><h1>414 Request-URI Too Large</h1></center>" CRLF
0201 ;
0202 
0203 
0204 static char ngx_http_error_415_page[] =
0205 "<html>" CRLF
0206 "<head><title>415 Unsupported Media Type</title></head>" CRLF
0207 "<body bgcolor=\"white\">" CRLF
0208 "<center><h1>415 Unsupported Media Type</h1></center>" CRLF
0209 ;
0210 
0211 
0212 static char ngx_http_error_416_page[] =
0213 "<html>" CRLF
0214 "<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF
0215 "<body bgcolor=\"white\">" CRLF
0216 "<center><h1>416 Requested Range Not Satisfiable</h1></center>" CRLF
0217 ;
0218 
0219 
0220 static char ngx_http_error_421_page[] =
0221 "<html>" CRLF
0222 "<head><title>421 Misdirected Request</title></head>" CRLF
0223 "<body bgcolor=\"white\">" CRLF
0224 "<center><h1>421 Misdirected Request</h1></center>" CRLF
0225 ;
0226 
0227 
0228 static char ngx_http_error_429_page[] =
0229 "<html>" CRLF
0230 "<head><title>429 Too Many Requests</title></head>" CRLF
0231 "<body bgcolor=\"white\">" CRLF
0232 "<center><h1>429 Too Many Requests</h1></center>" CRLF
0233 ;
0234 
0235 
0236 static char ngx_http_error_494_page[] =
0237 "<html>" CRLF
0238 "<head><title>400 Request Header Or Cookie Too Large</title></head>"
0239 CRLF
0240 "<body bgcolor=\"white\">" CRLF
0241 "<center><h1>400 Bad Request</h1></center>" CRLF
0242 "<center>Request Header Or Cookie Too Large</center>" CRLF
0243 ;
0244 
0245 
0246 static char ngx_http_error_495_page[] =
0247 "<html>" CRLF
0248 "<head><title>400 The SSL certificate error</title></head>"
0249 CRLF
0250 "<body bgcolor=\"white\">" CRLF
0251 "<center><h1>400 Bad Request</h1></center>" CRLF
0252 "<center>The SSL certificate error</center>" CRLF
0253 ;
0254 
0255 
0256 static char ngx_http_error_496_page[] =
0257 "<html>" CRLF
0258 "<head><title>400 No required SSL certificate was sent</title></head>"
0259 CRLF
0260 "<body bgcolor=\"white\">" CRLF
0261 "<center><h1>400 Bad Request</h1></center>" CRLF
0262 "<center>No required SSL certificate was sent</center>" CRLF
0263 ;
0264 
0265 
0266 static char ngx_http_error_497_page[] =
0267 "<html>" CRLF
0268 "<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>"
0269 CRLF
0270 "<body bgcolor=\"white\">" CRLF
0271 "<center><h1>400 Bad Request</h1></center>" CRLF
0272 "<center>The plain HTTP request was sent to HTTPS port</center>" CRLF
0273 ;
0274 
0275 
0276 static char ngx_http_error_500_page[] =
0277 "<html>" CRLF
0278 "<head><title>500 Internal Server Error</title></head>" CRLF
0279 "<body bgcolor=\"white\">" CRLF
0280 "<center><h1>500 Internal Server Error</h1></center>" CRLF
0281 ;
0282 
0283 
0284 static char ngx_http_error_501_page[] =
0285 "<html>" CRLF
0286 "<head><title>501 Not Implemented</title></head>" CRLF
0287 "<body bgcolor=\"white\">" CRLF
0288 "<center><h1>501 Not Implemented</h1></center>" CRLF
0289 ;
0290 
0291 
0292 static char ngx_http_error_502_page[] =
0293 "<html>" CRLF
0294 "<head><title>502 Bad Gateway</title></head>" CRLF
0295 "<body bgcolor=\"white\">" CRLF
0296 "<center><h1>502 Bad Gateway</h1></center>" CRLF
0297 ;
0298 
0299 
0300 static char ngx_http_error_503_page[] =
0301 "<html>" CRLF
0302 "<head><title>503 Service Temporarily Unavailable</title></head>" CRLF
0303 "<body bgcolor=\"white\">" CRLF
0304 "<center><h1>503 Service Temporarily Unavailable</h1></center>" CRLF
0305 ;
0306 
0307 
0308 static char ngx_http_error_504_page[] =
0309 "<html>" CRLF
0310 "<head><title>504 Gateway Time-out</title></head>" CRLF
0311 "<body bgcolor=\"white\">" CRLF
0312 "<center><h1>504 Gateway Time-out</h1></center>" CRLF
0313 ;
0314 
0315 
0316 static char ngx_http_error_507_page[] =
0317 "<html>" CRLF
0318 "<head><title>507 Insufficient Storage</title></head>" CRLF
0319 "<body bgcolor=\"white\">" CRLF
0320 "<center><h1>507 Insufficient Storage</h1></center>" CRLF
0321 ;
0322 
0323 
0324 static ngx_str_t ngx_http_error_pages[] = {
0325 
0326     ngx_null_string,                     /* 201, 204 */
0327 
0328 #define NGX_HTTP_LAST_2XX  202
0329 #define NGX_HTTP_OFF_3XX   (NGX_HTTP_LAST_2XX - 201)
0330 
0331     /* ngx_null_string, */               /* 300 */
0332     ngx_string(ngx_http_error_301_page),
0333     ngx_string(ngx_http_error_302_page),
0334     ngx_string(ngx_http_error_303_page),
0335     ngx_null_string,                     /* 304 */
0336     ngx_null_string,                     /* 305 */
0337     ngx_null_string,                     /* 306 */
0338     ngx_string(ngx_http_error_307_page),
0339 
0340 #define NGX_HTTP_LAST_3XX  308
0341 #define NGX_HTTP_OFF_4XX   (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX)
0342 
0343     ngx_string(ngx_http_error_400_page),
0344     ngx_string(ngx_http_error_401_page),
0345     ngx_string(ngx_http_error_402_page),
0346     ngx_string(ngx_http_error_403_page),
0347     ngx_string(ngx_http_error_404_page),
0348     ngx_string(ngx_http_error_405_page),
0349     ngx_string(ngx_http_error_406_page),
0350     ngx_null_string,                     /* 407 */
0351     ngx_string(ngx_http_error_408_page),
0352     ngx_string(ngx_http_error_409_page),
0353     ngx_string(ngx_http_error_410_page),
0354     ngx_string(ngx_http_error_411_page),
0355     ngx_string(ngx_http_error_412_page),
0356     ngx_string(ngx_http_error_413_page),
0357     ngx_string(ngx_http_error_414_page),
0358     ngx_string(ngx_http_error_415_page),
0359     ngx_string(ngx_http_error_416_page),
0360     ngx_null_string,                     /* 417 */
0361     ngx_null_string,                     /* 418 */
0362     ngx_null_string,                     /* 419 */
0363     ngx_null_string,                     /* 420 */
0364     ngx_string(ngx_http_error_421_page),
0365     ngx_null_string,                     /* 422 */
0366     ngx_null_string,                     /* 423 */
0367     ngx_null_string,                     /* 424 */
0368     ngx_null_string,                     /* 425 */
0369     ngx_null_string,                     /* 426 */
0370     ngx_null_string,                     /* 427 */
0371     ngx_null_string,                     /* 428 */
0372     ngx_string(ngx_http_error_429_page),
0373 
0374 #define NGX_HTTP_LAST_4XX  430
0375 #define NGX_HTTP_OFF_5XX   (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX)
0376 
0377     ngx_string(ngx_http_error_494_page), /* 494, request header too large */
0378     ngx_string(ngx_http_error_495_page), /* 495, https certificate error */
0379     ngx_string(ngx_http_error_496_page), /* 496, https no certificate */
0380     ngx_string(ngx_http_error_497_page), /* 497, http to https */
0381     ngx_string(ngx_http_error_404_page), /* 498, canceled */
0382     ngx_null_string,                     /* 499, client has closed connection */
0383 
0384     ngx_string(ngx_http_error_500_page),
0385     ngx_string(ngx_http_error_501_page),
0386     ngx_string(ngx_http_error_502_page),
0387     ngx_string(ngx_http_error_503_page),
0388     ngx_string(ngx_http_error_504_page),
0389     ngx_null_string,                     /* 505 */
0390     ngx_null_string,                     /* 506 */
0391     ngx_string(ngx_http_error_507_page)
0392 
0393 #define NGX_HTTP_LAST_5XX  508
0394 
0395 };
0396 
0397 
0398 ngx_int_t
0399 ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
0400 {
0401     ngx_uint_t                 i, err;
0402     ngx_http_err_page_t       *err_page;
0403     ngx_http_core_loc_conf_t  *clcf;
0404 
0405     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
0406                    "http special response: %i, \"%V?%V\"",
0407                    error, &r->uri, &r->args);
0408 
0409     r->err_status = error;
0410 
0411     if (r->keepalive) {
0412         switch (error) {
0413             case NGX_HTTP_BAD_REQUEST:
0414             case NGX_HTTP_REQUEST_ENTITY_TOO_LARGE:
0415             case NGX_HTTP_REQUEST_URI_TOO_LARGE:
0416             case NGX_HTTP_TO_HTTPS:
0417             case NGX_HTTPS_CERT_ERROR:
0418             case NGX_HTTPS_NO_CERT:
0419             case NGX_HTTP_INTERNAL_SERVER_ERROR:
0420             case NGX_HTTP_NOT_IMPLEMENTED:
0421                 r->keepalive = 0;
0422         }
0423     }
0424 
0425     if (r->lingering_close) {
0426         switch (error) {
0427             case NGX_HTTP_BAD_REQUEST:
0428             case NGX_HTTP_TO_HTTPS:
0429             case NGX_HTTPS_CERT_ERROR:
0430             case NGX_HTTPS_NO_CERT:
0431                 r->lingering_close = 0;
0432         }
0433     }
0434 
0435     r->headers_out.content_type.len = 0;
0436 
0437     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0438 
0439     if (!r->error_page && clcf->error_pages && r->uri_changes != 0) {
0440 
0441         if (clcf->recursive_error_pages == 0) {
0442             r->error_page = 1;
0443         }
0444 
0445         err_page = clcf->error_pages->elts;
0446 
0447         for (i = 0; i < clcf->error_pages->nelts; i++) {
0448             if (err_page[i].status == error) {
0449                 return ngx_http_send_error_page(r, &err_page[i]);
0450             }
0451         }
0452     }
0453 
0454     r->expect_tested = 1;
0455 
0456     if (ngx_http_discard_request_body(r) != NGX_OK) {
0457         r->keepalive = 0;
0458     }
0459 
0460     if (clcf->msie_refresh
0461         && r->headers_in.msie
0462         && (error == NGX_HTTP_MOVED_PERMANENTLY
0463             || error == NGX_HTTP_MOVED_TEMPORARILY))
0464     {
0465         return ngx_http_send_refresh(r);
0466     }
0467 
0468     if (error == NGX_HTTP_CREATED) {
0469         /* 201 */
0470         err = 0;
0471 
0472     } else if (error == NGX_HTTP_NO_CONTENT) {
0473         /* 204 */
0474         err = 0;
0475 
0476     } else if (error >= NGX_HTTP_MOVED_PERMANENTLY
0477                && error < NGX_HTTP_LAST_3XX)
0478     {
0479         /* 3XX */
0480         err = error - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX;
0481 
0482     } else if (error >= NGX_HTTP_BAD_REQUEST
0483                && error < NGX_HTTP_LAST_4XX)
0484     {
0485         /* 4XX */
0486         err = error - NGX_HTTP_BAD_REQUEST + NGX_HTTP_OFF_4XX;
0487 
0488     } else if (error >= NGX_HTTP_NGINX_CODES
0489                && error < NGX_HTTP_LAST_5XX)
0490     {
0491         /* 49X, 5XX */
0492         err = error - NGX_HTTP_NGINX_CODES + NGX_HTTP_OFF_5XX;
0493         switch (error) {
0494             case NGX_HTTP_TO_HTTPS:
0495             case NGX_HTTPS_CERT_ERROR:
0496             case NGX_HTTPS_NO_CERT:
0497             case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:
0498                 r->err_status = NGX_HTTP_BAD_REQUEST;
0499         }
0500 
0501     } else {
0502         /* unknown code, zero body */
0503         err = 0;
0504     }
0505 
0506     return ngx_http_send_special_response(r, clcf, err);
0507 }
0508 
0509 
0510 ngx_int_t
0511 ngx_http_filter_finalize_request(ngx_http_request_t *r, ngx_module_t *m,
0512     ngx_int_t error)
0513 {
0514     void       *ctx;
0515     ngx_int_t   rc;
0516 
0517     ngx_http_clean_header(r);
0518 
0519     ctx = NULL;
0520 
0521     if (m) {
0522         ctx = r->ctx[m->ctx_index];
0523     }
0524 
0525     /* clear the modules contexts */
0526     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
0527 
0528     if (m) {
0529         r->ctx[m->ctx_index] = ctx;
0530     }
0531 
0532     r->filter_finalize = 1;
0533 
0534     rc = ngx_http_special_response_handler(r, error);
0535 
0536     /* NGX_ERROR resets any pending data */
0537 
0538     switch (rc) {
0539 
0540     case NGX_OK:
0541     case NGX_DONE:
0542         return NGX_ERROR;
0543 
0544     default:
0545         return rc;
0546     }
0547 }
0548 
0549 
0550 void
0551 ngx_http_clean_header(ngx_http_request_t *r)
0552 {
0553     ngx_memzero(&r->headers_out.status,
0554                 sizeof(ngx_http_headers_out_t)
0555                     - offsetof(ngx_http_headers_out_t, status));
0556 
0557     r->headers_out.headers.part.nelts = 0;
0558     r->headers_out.headers.part.next = NULL;
0559     r->headers_out.headers.last = &r->headers_out.headers.part;
0560 
0561     r->headers_out.content_length_n = -1;
0562     r->headers_out.last_modified_time = -1;
0563 }
0564 
0565 
0566 static ngx_int_t
0567 ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
0568 {
0569     ngx_int_t                  overwrite;
0570     ngx_str_t                  uri, args;
0571     ngx_table_elt_t           *location;
0572     ngx_http_core_loc_conf_t  *clcf;
0573 
0574     overwrite = err_page->overwrite;
0575 
0576     if (overwrite && overwrite != NGX_HTTP_OK) {
0577         r->expect_tested = 1;
0578     }
0579 
0580     if (overwrite >= 0) {
0581         r->err_status = overwrite;
0582     }
0583 
0584     if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) {
0585         return NGX_ERROR;
0586     }
0587 
0588     if (uri.len && uri.data[0] == '/') {
0589 
0590         if (err_page->value.lengths) {
0591             ngx_http_split_args(r, &uri, &args);
0592 
0593         } else {
0594             args = err_page->args;
0595         }
0596 
0597         if (r->method != NGX_HTTP_HEAD) {
0598             r->method = NGX_HTTP_GET;
0599             r->method_name = ngx_http_core_get_method;
0600         }
0601 
0602         return ngx_http_internal_redirect(r, &uri, &args);
0603     }
0604 
0605     if (uri.len && uri.data[0] == '@') {
0606         return ngx_http_named_location(r, &uri);
0607     }
0608 
0609     location = ngx_list_push(&r->headers_out.headers);
0610 
0611     if (location == NULL) {
0612         return NGX_ERROR;
0613     }
0614 
0615     if (overwrite != NGX_HTTP_MOVED_PERMANENTLY
0616         && overwrite != NGX_HTTP_MOVED_TEMPORARILY
0617         && overwrite != NGX_HTTP_SEE_OTHER
0618         && overwrite != NGX_HTTP_TEMPORARY_REDIRECT)
0619     {
0620         r->err_status = NGX_HTTP_MOVED_TEMPORARILY;
0621     }
0622 
0623     location->hash = 1;
0624     ngx_str_set(&location->key, "Location");
0625     location->value = uri;
0626 
0627     ngx_http_clear_location(r);
0628 
0629     r->headers_out.location = location;
0630 
0631     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0632 
0633     if (clcf->msie_refresh && r->headers_in.msie) {
0634         return ngx_http_send_refresh(r);
0635     }
0636 
0637     return ngx_http_send_special_response(r, clcf, r->err_status
0638                                                    - NGX_HTTP_MOVED_PERMANENTLY
0639                                                    + NGX_HTTP_OFF_3XX);
0640 }
0641 
0642 
0643 static ngx_int_t
0644 ngx_http_send_special_response(ngx_http_request_t *r,
0645     ngx_http_core_loc_conf_t *clcf, ngx_uint_t err)
0646 {
0647     u_char       *tail;
0648     size_t        len;
0649     ngx_int_t     rc;
0650     ngx_buf_t    *b;
0651     ngx_uint_t    msie_padding;
0652     ngx_chain_t   out[3];
0653 
0654     if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) {
0655         len = sizeof(ngx_http_error_full_tail) - 1;
0656         tail = ngx_http_error_full_tail;
0657 
0658     } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) {
0659         len = sizeof(ngx_http_error_build_tail) - 1;
0660         tail = ngx_http_error_build_tail;
0661 
0662     } else {
0663         len = sizeof(ngx_http_error_tail) - 1;
0664         tail = ngx_http_error_tail;
0665     }
0666 
0667     msie_padding = 0;
0668 
0669     if (ngx_http_error_pages[err].len) {
0670         r->headers_out.content_length_n = ngx_http_error_pages[err].len + len;
0671         if (clcf->msie_padding
0672             && (r->headers_in.msie || r->headers_in.chrome)
0673             && r->http_version >= NGX_HTTP_VERSION_10
0674             && err >= NGX_HTTP_OFF_4XX)
0675         {
0676             r->headers_out.content_length_n +=
0677                                          sizeof(ngx_http_msie_padding) - 1;
0678             msie_padding = 1;
0679         }
0680 
0681         r->headers_out.content_type_len = sizeof("text/html") - 1;
0682         ngx_str_set(&r->headers_out.content_type, "text/html");
0683         r->headers_out.content_type_lowcase = NULL;
0684 
0685     } else {
0686         r->headers_out.content_length_n = 0;
0687     }
0688 
0689     if (r->headers_out.content_length) {
0690         r->headers_out.content_length->hash = 0;
0691         r->headers_out.content_length = NULL;
0692     }
0693 
0694     ngx_http_clear_accept_ranges(r);
0695     ngx_http_clear_last_modified(r);
0696     ngx_http_clear_etag(r);
0697 
0698     rc = ngx_http_send_header(r);
0699 
0700     if (rc == NGX_ERROR || r->header_only) {
0701         return rc;
0702     }
0703 
0704     if (ngx_http_error_pages[err].len == 0) {
0705         return ngx_http_send_special(r, NGX_HTTP_LAST);
0706     }
0707 
0708     b = ngx_calloc_buf(r->pool);
0709     if (b == NULL) {
0710         return NGX_ERROR;
0711     }
0712 
0713     b->memory = 1;
0714     b->pos = ngx_http_error_pages[err].data;
0715     b->last = ngx_http_error_pages[err].data + ngx_http_error_pages[err].len;
0716 
0717     out[0].buf = b;
0718     out[0].next = &out[1];
0719 
0720     b = ngx_calloc_buf(r->pool);
0721     if (b == NULL) {
0722         return NGX_ERROR;
0723     }
0724 
0725     b->memory = 1;
0726 
0727     b->pos = tail;
0728     b->last = tail + len;
0729 
0730     out[1].buf = b;
0731     out[1].next = NULL;
0732 
0733     if (msie_padding) {
0734         b = ngx_calloc_buf(r->pool);
0735         if (b == NULL) {
0736             return NGX_ERROR;
0737         }
0738 
0739         b->memory = 1;
0740         b->pos = ngx_http_msie_padding;
0741         b->last = ngx_http_msie_padding + sizeof(ngx_http_msie_padding) - 1;
0742 
0743         out[1].next = &out[2];
0744         out[2].buf = b;
0745         out[2].next = NULL;
0746     }
0747 
0748     if (r == r->main) {
0749         b->last_buf = 1;
0750     }
0751 
0752     b->last_in_chain = 1;
0753 
0754     return ngx_http_output_filter(r, &out[0]);
0755 }
0756 
0757 
0758 static ngx_int_t
0759 ngx_http_send_refresh(ngx_http_request_t *r)
0760 {
0761     u_char       *p, *location;
0762     size_t        len, size;
0763     uintptr_t     escape;
0764     ngx_int_t     rc;
0765     ngx_buf_t    *b;
0766     ngx_chain_t   out;
0767 
0768     len = r->headers_out.location->value.len;
0769     location = r->headers_out.location->value.data;
0770 
0771     escape = 2 * ngx_escape_uri(NULL, location, len, NGX_ESCAPE_REFRESH);
0772 
0773     size = sizeof(ngx_http_msie_refresh_head) - 1
0774            + escape + len
0775            + sizeof(ngx_http_msie_refresh_tail) - 1;
0776 
0777     r->err_status = NGX_HTTP_OK;
0778 
0779     r->headers_out.content_type_len = sizeof("text/html") - 1;
0780     ngx_str_set(&r->headers_out.content_type, "text/html");
0781     r->headers_out.content_type_lowcase = NULL;
0782 
0783     r->headers_out.location->hash = 0;
0784     r->headers_out.location = NULL;
0785 
0786     r->headers_out.content_length_n = size;
0787 
0788     if (r->headers_out.content_length) {
0789         r->headers_out.content_length->hash = 0;
0790         r->headers_out.content_length = NULL;
0791     }
0792 
0793     ngx_http_clear_accept_ranges(r);
0794     ngx_http_clear_last_modified(r);
0795     ngx_http_clear_etag(r);
0796 
0797     rc = ngx_http_send_header(r);
0798 
0799     if (rc == NGX_ERROR || r->header_only) {
0800         return rc;
0801     }
0802 
0803     b = ngx_create_temp_buf(r->pool, size);
0804     if (b == NULL) {
0805         return NGX_ERROR;
0806     }
0807 
0808     p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head,
0809                    sizeof(ngx_http_msie_refresh_head) - 1);
0810 
0811     if (escape == 0) {
0812         p = ngx_cpymem(p, location, len);
0813 
0814     } else {
0815         p = (u_char *) ngx_escape_uri(p, location, len, NGX_ESCAPE_REFRESH);
0816     }
0817 
0818     b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail,
0819                          sizeof(ngx_http_msie_refresh_tail) - 1);
0820 
0821     b->last_buf = (r == r->main) ? 1 : 0;
0822     b->last_in_chain = 1;
0823 
0824     out.buf = b;
0825     out.next = NULL;
0826 
0827     return ngx_http_output_filter(r, &out);
0828 }