Mercurial > hg > nginx-vendor-current
comparison src/http/ngx_http_special_response.c-C @ 230:38e7b94d63ac NGINX_0_4_0
nginx 0.4.0
*) Change in internal API: the HTTP modules initialization was moved
from the init module phase to the HTTP postconfiguration phase.
*) Change: now the request body is not read beforehand for the
ngx_http_perl_module: it's required to start the reading using the
$r->has_request_body method.
*) Feature: the ngx_http_perl_module supports the DECLINED return code.
*) Feature: the ngx_http_dav_module supports the incoming "Date" header
line for the PUT method.
*) Feature: the "ssi" directive is available inside the "if" block.
*) Bugfix: a segmentation fault occurred if there was an "index"
directive with variables and the first index name was without
variables; bug appeared in 0.1.29.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 30 Aug 2006 00:00:00 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
229:1965c8e23be7 | 230:38e7b94d63ac |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 #include <nginx.h> | |
11 | |
12 | |
13 static u_char error_tail[] = | |
14 "<hr><center>" NGINX_VER "</center>" CRLF | |
15 "</body>" CRLF | |
16 "</html>" CRLF | |
17 ; | |
18 | |
19 | |
20 static u_char ngx_http_msie_stub[] = | |
21 "<!-- The padding to disable MSIE's friendly error page -->" CRLF | |
22 "<!-- The padding to disable MSIE's friendly error page -->" CRLF | |
23 "<!-- The padding to disable MSIE's friendly error page -->" CRLF | |
24 "<!-- The padding to disable MSIE's friendly error page -->" CRLF | |
25 "<!-- The padding to disable MSIE's friendly error page -->" CRLF | |
26 "<!-- The padding to disable MSIE's friendly error page -->" CRLF | |
27 ; | |
28 | |
29 | |
30 static char error_301_page[] = | |
31 "<html>" CRLF | |
32 "<head><title>301 Moved Permanently</title></head>" CRLF | |
33 "<body bgcolor=\"white\">" CRLF | |
34 "<center><h1>301 Moved Permanently</h1></center>" CRLF | |
35 ; | |
36 | |
37 | |
38 static char error_302_page[] = | |
39 "<html>" CRLF | |
40 "<head><title>302 Found</title></head>" CRLF | |
41 "<body bgcolor=\"white\">" CRLF | |
42 "<center><h1>302 Found</h1></center>" CRLF | |
43 ; | |
44 | |
45 | |
46 static char error_400_page[] = | |
47 "<html>" CRLF | |
48 "<head><title>400 Bad Request</title></head>" CRLF | |
49 "<body bgcolor=\"white\">" CRLF | |
50 "<center><h1>400 Bad Request</h1></center>" CRLF | |
51 ; | |
52 | |
53 | |
54 static char error_401_page[] = | |
55 "<html>" CRLF | |
56 "<head><title>401 Authorization Required</title></head>" CRLF | |
57 "<body bgcolor=\"white\">" CRLF | |
58 "<center><h1>401 Authorization Required</h1></center>" CRLF | |
59 ; | |
60 | |
61 | |
62 static char error_402_page[] = | |
63 "<html>" CRLF | |
64 "<head><title>402 Payment Required</title></head>" CRLF | |
65 "<body bgcolor=\"white\">" CRLF | |
66 "<center><h1>402 Payment Required</h1></center>" CRLF | |
67 ; | |
68 | |
69 | |
70 static char error_403_page[] = | |
71 "<html>" CRLF | |
72 "<head><title>403 Forbidden</title></head>" CRLF | |
73 "<body bgcolor=\"white\">" CRLF | |
74 "<center><h1>403 Forbidden</h1></center>" CRLF | |
75 ; | |
76 | |
77 | |
78 static char error_404_page[] = | |
79 "<html>" CRLF | |
80 "<head><title>404 Not Found</title></head>" CRLF | |
81 "<body bgcolor=\"white\">" CRLF | |
82 "<center><h1>404 Not Found</h1></center>" CRLF | |
83 ; | |
84 | |
85 | |
86 static char error_405_page[] = | |
87 "<html>" CRLF | |
88 "<head><title>405 Not Allowed</title></head>" CRLF | |
89 "<body bgcolor=\"white\">" CRLF | |
90 "<center><h1>405 Not Allowed</h1></center>" CRLF | |
91 ; | |
92 | |
93 | |
94 static char error_406_page[] = | |
95 "<html>" CRLF | |
96 "<head><title>406 Not Acceptable</title></head>" CRLF | |
97 "<body bgcolor=\"white\">" CRLF | |
98 "<center><h1>406 Not Acceptable</h1></center>" CRLF | |
99 ; | |
100 | |
101 | |
102 static char error_408_page[] = | |
103 "<html>" CRLF | |
104 "<head><title>408 Request Time-out</title></head>" CRLF | |
105 "<body bgcolor=\"white\">" CRLF | |
106 "<center><h1>408 Request Time-out</h1></center>" CRLF | |
107 ; | |
108 | |
109 | |
110 static char error_409_page[] = | |
111 "<html>" CRLF | |
112 "<head><title>409 Conflict</title></head>" CRLF | |
113 "<body bgcolor=\"white\">" CRLF | |
114 "<center><h1>409 Conflict</h1></center>" CRLF | |
115 ; | |
116 | |
117 | |
118 static char error_410_page[] = | |
119 "<html>" CRLF | |
120 "<head><title>410 Gone</title></head>" CRLF | |
121 "<body bgcolor=\"white\">" CRLF | |
122 "<center><h1>410 Gone</h1></center>" CRLF | |
123 ; | |
124 | |
125 | |
126 static char error_411_page[] = | |
127 "<html>" CRLF | |
128 "<head><title>411 Length Required</title></head>" CRLF | |
129 "<body bgcolor=\"white\">" CRLF | |
130 "<center><h1>411 Length Required</h1></center>" CRLF | |
131 ; | |
132 | |
133 | |
134 static char error_413_page[] = | |
135 "<html>" CRLF | |
136 "<head><title>413 Request Entity Too Large</title></head>" CRLF | |
137 "<body bgcolor=\"white\">" CRLF | |
138 "<center><h1>413 Request Entity Too Large</h1></center>" CRLF | |
139 ; | |
140 | |
141 | |
142 static char error_414_page[] = | |
143 "<html>" CRLF | |
144 "<head><title>414 Request-URI Too Large</title></head>" CRLF | |
145 "<body bgcolor=\"white\">" CRLF | |
146 "<center><h1>414 Request-URI Too Large</h1></center>" CRLF | |
147 ; | |
148 | |
149 | |
150 static char error_415_page[] = | |
151 "<html>" CRLF | |
152 "<head><title>415 Unsupported Media Type</title></head>" CRLF | |
153 "<body bgcolor=\"white\">" CRLF | |
154 "<center><h1>415 Unsupported Media Type</h1></center>" CRLF | |
155 ; | |
156 | |
157 | |
158 static char error_416_page[] = | |
159 "<html>" CRLF | |
160 "<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF | |
161 "<body bgcolor=\"white\">" CRLF | |
162 "<center><h1>416 Requested Range Not Satisfiable</h1></center>" CRLF | |
163 ; | |
164 | |
165 | |
166 static char error_495_page[] = | |
167 "<html>" CRLF | |
168 "<head><title>400 The SSL certificate error</title></head>" | |
169 CRLF | |
170 "<body bgcolor=\"white\">" CRLF | |
171 "<center><h1>400 Bad Request</h1></center>" CRLF | |
172 "<center>The SSL certificate error</center>" CRLF | |
173 ; | |
174 | |
175 | |
176 static char error_496_page[] = | |
177 "<html>" CRLF | |
178 "<head><title>400 No required SSL certificate was sent</title></head>" | |
179 CRLF | |
180 "<body bgcolor=\"white\">" CRLF | |
181 "<center><h1>400 Bad Request</h1></center>" CRLF | |
182 "<center>No required SSL certificate was sent</center>" CRLF | |
183 ; | |
184 | |
185 | |
186 static char error_497_page[] = | |
187 "<html>" CRLF | |
188 "<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>" | |
189 CRLF | |
190 "<body bgcolor=\"white\">" CRLF | |
191 "<center><h1>400 Bad Request</h1></center>" CRLF | |
192 "<center>The plain HTTP request was sent to HTTPS port</center>" CRLF | |
193 ; | |
194 | |
195 | |
196 static char error_500_page[] = | |
197 "<html>" CRLF | |
198 "<head><title>500 Internal Server Error</title></head>" CRLF | |
199 "<body bgcolor=\"white\">" CRLF | |
200 "<center><h1>500 Internal Server Error</h1></center>" CRLF | |
201 ; | |
202 | |
203 | |
204 static char error_501_page[] = | |
205 "<html>" CRLF | |
206 "<head><title>501 Method Not Implemented</title></head>" CRLF | |
207 "<body bgcolor=\"white\">" CRLF | |
208 "<center><h1>501 Method Not Implemented</h1></center>" CRLF | |
209 ; | |
210 | |
211 | |
212 static char error_502_page[] = | |
213 "<html>" CRLF | |
214 "<head><title>502 Bad Gateway</title></head>" CRLF | |
215 "<body bgcolor=\"white\">" CRLF | |
216 "<center><h1>502 Bad Gateway</h1></center>" CRLF | |
217 ; | |
218 | |
219 | |
220 static char error_503_page[] = | |
221 "<html>" CRLF | |
222 "<head><title>503 Service Temporarily Unavailable</title></head>" CRLF | |
223 "<body bgcolor=\"white\">" CRLF | |
224 "<center><h1>503 Service Temporarily Unavailable</h1></center>" CRLF | |
225 ; | |
226 | |
227 | |
228 static char error_504_page[] = | |
229 "<html>" CRLF | |
230 "<head><title>504 Gateway Time-out</title></head>" CRLF | |
231 "<body bgcolor=\"white\">" CRLF | |
232 "<center><h1>504 Gateway Time-out</h1></center>" CRLF | |
233 ; | |
234 | |
235 | |
236 static char error_507_page[] = | |
237 "<html>" CRLF | |
238 "<head><title>507 Insufficient Storage</title></head>" CRLF | |
239 "<body bgcolor=\"white\">" CRLF | |
240 "<center><h1>507 Insufficient Storage</h1></center>" CRLF | |
241 ; | |
242 | |
243 | |
244 static ngx_str_t error_pages[] = { | |
245 | |
246 ngx_null_string, /* 201, 204 */ | |
247 | |
248 #define NGX_HTTP_LEVEL_200 1 | |
249 | |
250 /* ngx_null_string, */ /* 300 */ | |
251 ngx_string(error_301_page), | |
252 ngx_string(error_302_page), | |
253 ngx_null_string, /* 303 */ | |
254 | |
255 #define NGX_HTTP_LEVEL_300 3 | |
256 | |
257 ngx_string(error_400_page), | |
258 ngx_string(error_401_page), | |
259 ngx_string(error_402_page), | |
260 ngx_string(error_403_page), | |
261 ngx_string(error_404_page), | |
262 ngx_string(error_405_page), | |
263 ngx_string(error_406_page), | |
264 ngx_null_string, /* 407 */ | |
265 ngx_string(error_408_page), | |
266 ngx_string(error_409_page), | |
267 ngx_string(error_410_page), | |
268 ngx_string(error_411_page), | |
269 ngx_null_string, /* 412 */ | |
270 ngx_string(error_413_page), | |
271 ngx_string(error_414_page), | |
272 ngx_string(error_415_page), | |
273 ngx_string(error_416_page), | |
274 | |
275 #define NGX_HTTP_LEVEL_400 17 | |
276 | |
277 ngx_string(error_495_page), /* 495, https certificate error */ | |
278 ngx_string(error_496_page), /* 496, https no certificate */ | |
279 ngx_string(error_497_page), /* 497, http to https */ | |
280 ngx_string(error_404_page), /* 498, invalid host name */ | |
281 ngx_null_string, /* 499, client had closed connection */ | |
282 | |
283 ngx_string(error_500_page), | |
284 ngx_string(error_501_page), | |
285 ngx_string(error_502_page), | |
286 ngx_string(error_503_page), | |
287 ngx_string(error_504_page), | |
288 ngx_null_string, /* 505 */ | |
289 ngx_null_string, /* 506 */ | |
290 ngx_string(error_507_page) | |
291 }; | |
292 | |
293 | |
294 ngx_int_t | |
295 ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) | |
296 { | |
297 ngx_int_t rc; | |
298 ngx_buf_t *b; | |
299 ngx_str_t *uri; | |
300 ngx_uint_t i, n, err, msie_padding; | |
301 ngx_chain_t *out, *cl; | |
302 ngx_http_err_page_t *err_page; | |
303 ngx_http_core_loc_conf_t *clcf; | |
304 | |
305 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
306 "http special response: %d, \"%V\"", error, &r->uri); | |
307 | |
308 rc = ngx_http_discard_body(r); | |
309 | |
310 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { | |
311 error = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
312 } | |
313 | |
314 r->headers_out.status = error; | |
315 r->err_status = error; | |
316 | |
317 if (r->keepalive != 0) { | |
318 switch (error) { | |
319 case NGX_HTTP_BAD_REQUEST: | |
320 case NGX_HTTP_REQUEST_ENTITY_TOO_LARGE: | |
321 case NGX_HTTP_REQUEST_URI_TOO_LARGE: | |
322 case NGX_HTTP_TO_HTTPS: | |
323 case NGX_HTTPS_CERT_ERROR: | |
324 case NGX_HTTPS_NO_CERT: | |
325 case NGX_HTTP_INTERNAL_SERVER_ERROR: | |
326 r->keepalive = 0; | |
327 } | |
328 } | |
329 | |
330 if (r->lingering_close == 1) { | |
331 switch (error) { | |
332 case NGX_HTTP_BAD_REQUEST: | |
333 case NGX_HTTP_TO_HTTPS: | |
334 case NGX_HTTPS_CERT_ERROR: | |
335 case NGX_HTTPS_NO_CERT: | |
336 r->lingering_close = 0; | |
337 } | |
338 } | |
339 | |
340 r->headers_out.content_type.len = 0; | |
341 | |
342 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
343 | |
344 if (!r->error_page && clcf->error_pages) { | |
345 | |
346 if (clcf->recursive_error_pages == 0) { | |
347 r->error_page = 1; | |
348 } | |
349 | |
350 err_page = clcf->error_pages->elts; | |
351 | |
352 for (i = 0; i < clcf->error_pages->nelts; i++) { | |
353 | |
354 if (err_page[i].status == error) { | |
355 r->err_status = err_page[i].overwrite; | |
356 | |
357 r->method = NGX_HTTP_GET; | |
358 | |
359 uri = &err_page[i].uri; | |
360 | |
361 if (err_page[i].uri_lengths) { | |
362 if (ngx_http_script_run(r, uri, | |
363 err_page[i].uri_lengths->elts, 0, | |
364 err_page[i].uri_values->elts) | |
365 == NULL) | |
366 { | |
367 return NGX_ERROR; | |
368 } | |
369 | |
370 if (r->zero_in_uri) { | |
371 for (n = 0; n < uri->len; n++) { | |
372 if (uri->data[n] == '\0') { | |
373 goto zero; | |
374 } | |
375 } | |
376 | |
377 r->zero_in_uri = 0; | |
378 } | |
379 | |
380 } else { | |
381 r->zero_in_uri = 0; | |
382 } | |
383 | |
384 zero: | |
385 | |
386 if (uri->data[0] == '/') { | |
387 return ngx_http_internal_redirect(r, uri, NULL); | |
388 } | |
389 | |
390 r->headers_out.location = | |
391 ngx_list_push(&r->headers_out.headers); | |
392 | |
393 if (r->headers_out.location) { | |
394 error = NGX_HTTP_MOVED_TEMPORARILY; | |
395 | |
396 r->err_status = NGX_HTTP_MOVED_TEMPORARILY; | |
397 | |
398 r->headers_out.location->hash = 1; | |
399 r->headers_out.location->key.len = sizeof("Location") - 1; | |
400 r->headers_out.location->key.data = (u_char *) "Location"; | |
401 r->headers_out.location->value = *uri; | |
402 | |
403 } else { | |
404 return NGX_ERROR; | |
405 } | |
406 } | |
407 } | |
408 } | |
409 | |
410 if (error == NGX_HTTP_CREATED) { | |
411 /* 201 */ | |
412 err = 0; | |
413 r->header_only = 1; | |
414 | |
415 } else if (error == NGX_HTTP_NO_CONTENT) { | |
416 /* 204 */ | |
417 err = 0; | |
418 | |
419 } else if (error < NGX_HTTP_BAD_REQUEST) { | |
420 /* 3XX */ | |
421 err = error - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200; | |
422 | |
423 } else if (error < NGX_HTTP_OWN_CODES) { | |
424 /* 4XX */ | |
425 err = error - NGX_HTTP_BAD_REQUEST + NGX_HTTP_LEVEL_200 | |
426 + NGX_HTTP_LEVEL_300; | |
427 | |
428 } else { | |
429 /* 49X, 5XX */ | |
430 err = error - NGX_HTTP_OWN_CODES + NGX_HTTP_LEVEL_200 | |
431 + NGX_HTTP_LEVEL_300 | |
432 + NGX_HTTP_LEVEL_400; | |
433 switch (error) { | |
434 case NGX_HTTP_TO_HTTPS: | |
435 case NGX_HTTPS_CERT_ERROR: | |
436 case NGX_HTTPS_NO_CERT: | |
437 r->headers_out.status = NGX_HTTP_BAD_REQUEST; | |
438 error = NGX_HTTP_BAD_REQUEST; | |
439 break; | |
440 } | |
441 } | |
442 | |
443 msie_padding = 0; | |
444 | |
445 if (error_pages[err].len) { | |
446 r->headers_out.content_length_n = error_pages[err].len | |
447 + sizeof(error_tail) - 1; | |
448 | |
449 if (clcf->msie_padding | |
450 && r->headers_in.msie | |
451 && r->http_version >= NGX_HTTP_VERSION_10 | |
452 && error >= NGX_HTTP_BAD_REQUEST | |
453 && error != NGX_HTTP_REQUEST_URI_TOO_LARGE) | |
454 { | |
455 r->headers_out.content_length_n += sizeof(ngx_http_msie_stub) - 1; | |
456 msie_padding = 1; | |
457 } | |
458 | |
459 r->headers_out.content_type.len = sizeof("text/html") - 1; | |
460 r->headers_out.content_type.data = (u_char *) "text/html"; | |
461 | |
462 } else { | |
463 r->headers_out.content_length_n = -1; | |
464 } | |
465 | |
466 if (r->headers_out.content_length) { | |
467 r->headers_out.content_length->hash = 0; | |
468 r->headers_out.content_length = NULL; | |
469 } | |
470 | |
471 ngx_http_clear_accept_ranges(r); | |
472 ngx_http_clear_last_modified(r); | |
473 | |
474 rc = ngx_http_send_header(r); | |
475 | |
476 if (rc == NGX_ERROR || r->header_only) { | |
477 return rc; | |
478 } | |
479 | |
480 if (error_pages[err].len == 0) { | |
481 return NGX_OK; | |
482 } | |
483 | |
484 | |
485 b = ngx_calloc_buf(r->pool); | |
486 if (b == NULL) { | |
487 return NGX_ERROR; | |
488 } | |
489 | |
490 b->memory = 1; | |
491 b->pos = error_pages[err].data; | |
492 b->last = error_pages[err].data + error_pages[err].len; | |
493 | |
494 cl = ngx_alloc_chain_link(r->pool); | |
495 if (cl == NULL) { | |
496 return NGX_ERROR; | |
497 } | |
498 | |
499 cl->buf = b; | |
500 out = cl; | |
501 | |
502 | |
503 b = ngx_calloc_buf(r->pool); | |
504 if (b == NULL) { | |
505 return NGX_ERROR; | |
506 } | |
507 | |
508 b->memory = 1; | |
509 b->pos = error_tail; | |
510 b->last = error_tail + sizeof(error_tail) - 1; | |
511 | |
512 cl->next = ngx_alloc_chain_link(r->pool); | |
513 if (cl->next == NULL) { | |
514 return NGX_ERROR; | |
515 } | |
516 | |
517 cl = cl->next; | |
518 cl->buf = b; | |
519 | |
520 if (msie_padding) { | |
521 b = ngx_calloc_buf(r->pool); | |
522 if (b == NULL) { | |
523 return NGX_ERROR; | |
524 } | |
525 | |
526 b->memory = 1; | |
527 b->pos = ngx_http_msie_stub; | |
528 b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1; | |
529 | |
530 cl->next = ngx_alloc_chain_link(r->pool); | |
531 if (cl->next == NULL) { | |
532 return NGX_ERROR; | |
533 } | |
534 | |
535 cl = cl->next; | |
536 cl->buf = b; | |
537 } | |
538 | |
539 if (r == r->main) { | |
540 b->last_buf = 1; | |
541 } | |
542 | |
543 b->last_in_chain = 1; | |
544 | |
545 cl->next = NULL; | |
546 | |
547 return ngx_http_output_filter(r, out); | |
548 } |