blob: 4d9bba99fda0b40cb29062e6ef53a5216f2b681f [file] [log] [blame]
Igor Sysoevb0869052002-12-10 18:05:12 +00001
Igor Sysoev42feecb2002-12-15 06:25:09 +00002#include <nginx.h>
Igor Sysoevb0869052002-12-10 18:05:12 +00003
4#include <ngx_config.h>
Igor Sysoevb0869052002-12-10 18:05:12 +00005#include <ngx_core.h>
Igor Sysoev42feecb2002-12-15 06:25:09 +00006#include <ngx_string.h>
Igor Sysoevb0869052002-12-10 18:05:12 +00007#include <ngx_http.h>
Igor Sysoev73009772003-02-06 17:21:13 +00008#include <ngx_http_output_filter.h>
9
Igor Sysoevb0869052002-12-10 18:05:12 +000010
Igor Sysoev42feecb2002-12-15 06:25:09 +000011static char error_tail[] =
12"<hr><center>" NGINX_VER "</center>" CRLF
13"</body>" CRLF
14"</html>" CRLF
15;
16
Igor Sysoev73009772003-02-06 17:21:13 +000017
Igor Sysoev42feecb2002-12-15 06:25:09 +000018static char error_400_page[] =
19"<html>" CRLF
20"<head><title>400 Bad Request</title></head>" CRLF
21"<body bgcolor=\"white\">" CRLF
22"<center><h1>400 Bad Request</h1></center>" CRLF
23;
24
Igor Sysoev73009772003-02-06 17:21:13 +000025
Igor Sysoevb2620632003-01-10 06:09:20 +000026static char error_403_page[] =
27"<html>" CRLF
28"<head><title>403 Forbidden</title></head>" CRLF
29"<body bgcolor=\"white\">" CRLF
30"<center><h1>403 Forbidden</h1></center>" CRLF
31;
32
Igor Sysoev73009772003-02-06 17:21:13 +000033
Igor Sysoev42feecb2002-12-15 06:25:09 +000034static char error_404_page[] =
35"<html>" CRLF
36"<head><title>404 Not Found</title></head>" CRLF
37"<body bgcolor=\"white\">" CRLF
38"<center><h1>404 Not Found</h1></center>" CRLF
39;
40
Igor Sysoev73009772003-02-06 17:21:13 +000041
Igor Sysoev6253ca12003-05-27 12:18:54 +000042static char error_405_page[] =
43"<html>" CRLF
44"<head><title>405 Not Allowed</title></head>" CRLF
45"<body bgcolor=\"white\">" CRLF
46"<center><h1>405 Not Allowed</h1></center>" CRLF
47;
48
49
Igor Sysoevdc479b42003-03-20 16:09:44 +000050static char error_408_page[] =
51"<html>" CRLF
52"<head><title>408 Request Time-out</title></head>" CRLF
53"<body bgcolor=\"white\">" CRLF
54"<center><h1>408 Request Time-out</h1></center>" CRLF
55;
56
57
Igor Sysoevb7387572003-03-11 20:38:13 +000058static char error_414_page[] =
59"<html>" CRLF
60"<head><title>414 Request-URI Too Large</title></head>" CRLF
61"<body bgcolor=\"white\">" CRLF
62"<center><h1>414 Request-URI Too Large</h1></center>" CRLF
63;
64
65
Igor Sysoevad22e012003-01-15 07:02:27 +000066static char error_500_page[] =
67"<html>" CRLF
68"<head><title>500 Internal Server Error</title></head>" CRLF
69"<body bgcolor=\"white\">" CRLF
70"<center><h1>500 Internal Server Error</h1></center>" CRLF
71;
72
Igor Sysoev42feecb2002-12-15 06:25:09 +000073
Igor Sysoevdc479b42003-03-20 16:09:44 +000074static char error_502_page[] =
75"<html>" CRLF
76"<head><title>502 Bad Gateway</title></head>" CRLF
77"<body bgcolor=\"white\">" CRLF
78"<center><h1>502 Bad Gateway</h1></center>" CRLF
79;
80
81
82static char error_504_page[] =
83"<html>" CRLF
84"<head><title>504 Gateway Time-out</title></head>" CRLF
85"<body bgcolor=\"white\">" CRLF
86"<center><h1>504 Gateway Time-out</h1></center>" CRLF
87;
88
89
Igor Sysoev42feecb2002-12-15 06:25:09 +000090static ngx_str_t error_pages[] = {
Igor Sysoevdc479b42003-03-20 16:09:44 +000091 ngx_null_string, /* 301 */
92 ngx_null_string, /* 302 */
93 ngx_null_string, /* 303 */
Igor Sysoev42feecb2002-12-15 06:25:09 +000094
Igor Sysoevdc479b42003-03-20 16:09:44 +000095 ngx_string(error_400_page),
96 ngx_null_string, /* 401 */
97 ngx_null_string, /* 402 */
98 ngx_string(error_403_page),
99 ngx_string(error_404_page),
Igor Sysoev6253ca12003-05-27 12:18:54 +0000100 ngx_string(error_405_page),
Igor Sysoevdc479b42003-03-20 16:09:44 +0000101 ngx_null_string, /* 406 */
102 ngx_null_string, /* 407 */
103 ngx_string(error_408_page),
104 ngx_null_string, /* 409 */
105 ngx_null_string, /* 410 */
106 ngx_null_string, /* 411 */
107 ngx_null_string, /* 412 */
108 ngx_null_string, /* 413 */
109 ngx_string(error_414_page),
110 ngx_null_string, /* 415 */
111 ngx_null_string, /* 416 */
Igor Sysoev42feecb2002-12-15 06:25:09 +0000112
Igor Sysoevdc479b42003-03-20 16:09:44 +0000113 ngx_string(error_500_page),
114 ngx_null_string, /* 501 */
115 ngx_string(error_502_page),
116 ngx_null_string, /* 503 */
117 ngx_string(error_504_page)
Igor Sysoev42feecb2002-12-15 06:25:09 +0000118};
Igor Sysoevb0869052002-12-10 18:05:12 +0000119
Igor Sysoev73009772003-02-06 17:21:13 +0000120
Igor Sysoevdc479b42003-03-20 16:09:44 +0000121int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
Igor Sysoevb0869052002-12-10 18:05:12 +0000122{
Igor Sysoev73009772003-02-06 17:21:13 +0000123 int err, len;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000124 ngx_hunk_t *message, *tail;
Igor Sysoevb0869052002-12-10 18:05:12 +0000125
Igor Sysoev42feecb2002-12-15 06:25:09 +0000126 len = 0;
Igor Sysoevb0869052002-12-10 18:05:12 +0000127
Igor Sysoev42feecb2002-12-15 06:25:09 +0000128 r->headers_out.status = error;
Igor Sysoevb0869052002-12-10 18:05:12 +0000129
Igor Sysoev90ace682003-03-12 17:32:22 +0000130 if (error < NGX_HTTP_BAD_REQUEST) {
Igor Sysoev79a80482003-05-14 17:13:13 +0000131 /* 3XX */
Igor Sysoev42feecb2002-12-15 06:25:09 +0000132 err = error - NGX_HTTP_MOVED_PERMANENTLY;
133
Igor Sysoev90ace682003-03-12 17:32:22 +0000134 } else {
Igor Sysoeve2a31542003-04-08 15:40:10 +0000135 ngx_test_null(r->headers_out.content_type,
136 ngx_push_table(r->headers_out.headers),
137 NGX_HTTP_INTERNAL_SERVER_ERROR);
138
139 r->headers_out.content_type->key.len = 12;
140 r->headers_out.content_type->key.data = "Content-Type";
141 r->headers_out.content_type->value.len = 9;
142 r->headers_out.content_type->value.data = "text/html";
143
144 if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
Igor Sysoev79a80482003-05-14 17:13:13 +0000145 /* 4XX */
Igor Sysoeve2a31542003-04-08 15:40:10 +0000146 err = error - NGX_HTTP_BAD_REQUEST + 3;
147
148 } else {
Igor Sysoev79a80482003-05-14 17:13:13 +0000149 /* 5XX */
Igor Sysoeve2a31542003-04-08 15:40:10 +0000150 err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17;
151 }
Igor Sysoev90ace682003-03-12 17:32:22 +0000152 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000153
Igor Sysoev90ace682003-03-12 17:32:22 +0000154 if (r->keepalive != 0) {
155 switch (error) {
156 case NGX_HTTP_BAD_REQUEST:
157 case NGX_HTTP_REQUEST_URI_TOO_LARGE:
158 case NGX_HTTP_INTERNAL_SERVER_ERROR:
159 r->keepalive = 0;
160 }
161 }
162
Igor Sysoev79a80482003-05-14 17:13:13 +0000163 if (r->lingering_close == 1) {
164 switch (error) {
165 case NGX_HTTP_BAD_REQUEST:
166 case NGX_HTTP_REQUEST_URI_TOO_LARGE:
167 case NGX_HTTP_INTERNAL_SERVER_ERROR:
168 r->lingering_close = 0;
169 }
170 }
171
Igor Sysoev90ace682003-03-12 17:32:22 +0000172 if (error_pages[err].len == 0) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000173 r->headers_out.content_length = -1;
Igor Sysoev90ace682003-03-12 17:32:22 +0000174 } else {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000175 r->headers_out.content_length = error_pages[err].len
176 + len + sizeof(error_tail);
Igor Sysoev90ace682003-03-12 17:32:22 +0000177 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000178
Igor Sysoev73009772003-02-06 17:21:13 +0000179 if (ngx_http_send_header(r) == NGX_ERROR) {
180 return NGX_ERROR;
181 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000182
Igor Sysoev73009772003-02-06 17:21:13 +0000183 if (error_pages[err].len == 0) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000184 return NGX_OK;
Igor Sysoev73009772003-02-06 17:21:13 +0000185 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000186
Igor Sysoev73009772003-02-06 17:21:13 +0000187 ngx_test_null(message, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), NGX_ERROR);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000188
Igor Sysoevb7387572003-03-11 20:38:13 +0000189 message->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY;
190 message->pos = error_pages[err].data;
191 message->last = error_pages[err].data + error_pages[err].len;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000192
Igor Sysoev73009772003-02-06 17:21:13 +0000193 if (ngx_http_output_filter(r, message) == NGX_ERROR) {
194 return NGX_ERROR;
195 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000196
Igor Sysoev73009772003-02-06 17:21:13 +0000197 ngx_test_null(tail, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), NGX_ERROR);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000198
Igor Sysoevb7387572003-03-11 20:38:13 +0000199 tail->type = NGX_HUNK_MEMORY|NGX_HUNK_LAST|NGX_HUNK_IN_MEMORY;
200 tail->pos = error_tail;
201 tail->last = error_tail + sizeof(error_tail);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000202
Igor Sysoev73009772003-02-06 17:21:13 +0000203 return ngx_http_output_filter(r, tail);
Igor Sysoevb0869052002-12-10 18:05:12 +0000204}