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