Mercurial > hg > nginx-quic
comparison src/http/ngx_http_special_response.c @ 1840:21d89aba08fa stable-0.5
r1605, r1673 merge:
divide special response handling into several functions
fix "?" escaping introduced in r1526
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 08 Jan 2008 16:42:02 +0000 |
parents | 0a174d921f1e |
children |
comparison
equal
deleted
inserted
replaced
1839:68db9281c81c | 1840:21d89aba08fa |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 #include <nginx.h> | 10 #include <nginx.h> |
11 | 11 |
12 | 12 |
13 static u_char error_full_tail[] = | 13 static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r, |
14 ngx_http_err_page_t *err_page); | |
15 static ngx_int_t ngx_http_send_special_response(ngx_http_request_t *r, | |
16 ngx_http_core_loc_conf_t *clcf, ngx_uint_t err); | |
17 static ngx_int_t ngx_http_send_refresh(ngx_http_request_t *r); | |
18 | |
19 | |
20 static u_char ngx_http_error_full_tail[] = | |
14 "<hr><center>" NGINX_VER "</center>" CRLF | 21 "<hr><center>" NGINX_VER "</center>" CRLF |
15 "</body>" CRLF | 22 "</body>" CRLF |
16 "</html>" CRLF | 23 "</html>" CRLF |
17 ; | 24 ; |
18 | 25 |
19 | 26 |
20 static u_char error_tail[] = | 27 static u_char ngx_http_error_tail[] = |
21 "<hr><center>nginx</center>" CRLF | 28 "<hr><center>nginx</center>" CRLF |
22 "</body>" CRLF | 29 "</body>" CRLF |
23 "</html>" CRLF | 30 "</html>" CRLF |
24 ; | 31 ; |
25 | 32 |
40 | 47 |
41 static u_char ngx_http_msie_refresh_tail[] = | 48 static u_char ngx_http_msie_refresh_tail[] = |
42 "\"></head><body></body></html>" CRLF; | 49 "\"></head><body></body></html>" CRLF; |
43 | 50 |
44 | 51 |
45 static char error_301_page[] = | 52 static char ngx_http_error_301_page[] = |
46 "<html>" CRLF | 53 "<html>" CRLF |
47 "<head><title>301 Moved Permanently</title></head>" CRLF | 54 "<head><title>301 Moved Permanently</title></head>" CRLF |
48 "<body bgcolor=\"white\">" CRLF | 55 "<body bgcolor=\"white\">" CRLF |
49 "<center><h1>301 Moved Permanently</h1></center>" CRLF | 56 "<center><h1>301 Moved Permanently</h1></center>" CRLF |
50 ; | 57 ; |
51 | 58 |
52 | 59 |
53 static char error_302_page[] = | 60 static char ngx_http_error_302_page[] = |
54 "<html>" CRLF | 61 "<html>" CRLF |
55 "<head><title>302 Found</title></head>" CRLF | 62 "<head><title>302 Found</title></head>" CRLF |
56 "<body bgcolor=\"white\">" CRLF | 63 "<body bgcolor=\"white\">" CRLF |
57 "<center><h1>302 Found</h1></center>" CRLF | 64 "<center><h1>302 Found</h1></center>" CRLF |
58 ; | 65 ; |
59 | 66 |
60 | 67 |
61 static char error_400_page[] = | 68 static char ngx_http_error_400_page[] = |
62 "<html>" CRLF | 69 "<html>" CRLF |
63 "<head><title>400 Bad Request</title></head>" CRLF | 70 "<head><title>400 Bad Request</title></head>" CRLF |
64 "<body bgcolor=\"white\">" CRLF | 71 "<body bgcolor=\"white\">" CRLF |
65 "<center><h1>400 Bad Request</h1></center>" CRLF | 72 "<center><h1>400 Bad Request</h1></center>" CRLF |
66 ; | 73 ; |
67 | 74 |
68 | 75 |
69 static char error_401_page[] = | 76 static char ngx_http_error_401_page[] = |
70 "<html>" CRLF | 77 "<html>" CRLF |
71 "<head><title>401 Authorization Required</title></head>" CRLF | 78 "<head><title>401 Authorization Required</title></head>" CRLF |
72 "<body bgcolor=\"white\">" CRLF | 79 "<body bgcolor=\"white\">" CRLF |
73 "<center><h1>401 Authorization Required</h1></center>" CRLF | 80 "<center><h1>401 Authorization Required</h1></center>" CRLF |
74 ; | 81 ; |
75 | 82 |
76 | 83 |
77 static char error_402_page[] = | 84 static char ngx_http_error_402_page[] = |
78 "<html>" CRLF | 85 "<html>" CRLF |
79 "<head><title>402 Payment Required</title></head>" CRLF | 86 "<head><title>402 Payment Required</title></head>" CRLF |
80 "<body bgcolor=\"white\">" CRLF | 87 "<body bgcolor=\"white\">" CRLF |
81 "<center><h1>402 Payment Required</h1></center>" CRLF | 88 "<center><h1>402 Payment Required</h1></center>" CRLF |
82 ; | 89 ; |
83 | 90 |
84 | 91 |
85 static char error_403_page[] = | 92 static char ngx_http_error_403_page[] = |
86 "<html>" CRLF | 93 "<html>" CRLF |
87 "<head><title>403 Forbidden</title></head>" CRLF | 94 "<head><title>403 Forbidden</title></head>" CRLF |
88 "<body bgcolor=\"white\">" CRLF | 95 "<body bgcolor=\"white\">" CRLF |
89 "<center><h1>403 Forbidden</h1></center>" CRLF | 96 "<center><h1>403 Forbidden</h1></center>" CRLF |
90 ; | 97 ; |
91 | 98 |
92 | 99 |
93 static char error_404_page[] = | 100 static char ngx_http_error_404_page[] = |
94 "<html>" CRLF | 101 "<html>" CRLF |
95 "<head><title>404 Not Found</title></head>" CRLF | 102 "<head><title>404 Not Found</title></head>" CRLF |
96 "<body bgcolor=\"white\">" CRLF | 103 "<body bgcolor=\"white\">" CRLF |
97 "<center><h1>404 Not Found</h1></center>" CRLF | 104 "<center><h1>404 Not Found</h1></center>" CRLF |
98 ; | 105 ; |
99 | 106 |
100 | 107 |
101 static char error_405_page[] = | 108 static char ngx_http_error_405_page[] = |
102 "<html>" CRLF | 109 "<html>" CRLF |
103 "<head><title>405 Not Allowed</title></head>" CRLF | 110 "<head><title>405 Not Allowed</title></head>" CRLF |
104 "<body bgcolor=\"white\">" CRLF | 111 "<body bgcolor=\"white\">" CRLF |
105 "<center><h1>405 Not Allowed</h1></center>" CRLF | 112 "<center><h1>405 Not Allowed</h1></center>" CRLF |
106 ; | 113 ; |
107 | 114 |
108 | 115 |
109 static char error_406_page[] = | 116 static char ngx_http_error_406_page[] = |
110 "<html>" CRLF | 117 "<html>" CRLF |
111 "<head><title>406 Not Acceptable</title></head>" CRLF | 118 "<head><title>406 Not Acceptable</title></head>" CRLF |
112 "<body bgcolor=\"white\">" CRLF | 119 "<body bgcolor=\"white\">" CRLF |
113 "<center><h1>406 Not Acceptable</h1></center>" CRLF | 120 "<center><h1>406 Not Acceptable</h1></center>" CRLF |
114 ; | 121 ; |
115 | 122 |
116 | 123 |
117 static char error_408_page[] = | 124 static char ngx_http_error_408_page[] = |
118 "<html>" CRLF | 125 "<html>" CRLF |
119 "<head><title>408 Request Time-out</title></head>" CRLF | 126 "<head><title>408 Request Time-out</title></head>" CRLF |
120 "<body bgcolor=\"white\">" CRLF | 127 "<body bgcolor=\"white\">" CRLF |
121 "<center><h1>408 Request Time-out</h1></center>" CRLF | 128 "<center><h1>408 Request Time-out</h1></center>" CRLF |
122 ; | 129 ; |
123 | 130 |
124 | 131 |
125 static char error_409_page[] = | 132 static char ngx_http_error_409_page[] = |
126 "<html>" CRLF | 133 "<html>" CRLF |
127 "<head><title>409 Conflict</title></head>" CRLF | 134 "<head><title>409 Conflict</title></head>" CRLF |
128 "<body bgcolor=\"white\">" CRLF | 135 "<body bgcolor=\"white\">" CRLF |
129 "<center><h1>409 Conflict</h1></center>" CRLF | 136 "<center><h1>409 Conflict</h1></center>" CRLF |
130 ; | 137 ; |
131 | 138 |
132 | 139 |
133 static char error_410_page[] = | 140 static char ngx_http_error_410_page[] = |
134 "<html>" CRLF | 141 "<html>" CRLF |
135 "<head><title>410 Gone</title></head>" CRLF | 142 "<head><title>410 Gone</title></head>" CRLF |
136 "<body bgcolor=\"white\">" CRLF | 143 "<body bgcolor=\"white\">" CRLF |
137 "<center><h1>410 Gone</h1></center>" CRLF | 144 "<center><h1>410 Gone</h1></center>" CRLF |
138 ; | 145 ; |
139 | 146 |
140 | 147 |
141 static char error_411_page[] = | 148 static char ngx_http_error_411_page[] = |
142 "<html>" CRLF | 149 "<html>" CRLF |
143 "<head><title>411 Length Required</title></head>" CRLF | 150 "<head><title>411 Length Required</title></head>" CRLF |
144 "<body bgcolor=\"white\">" CRLF | 151 "<body bgcolor=\"white\">" CRLF |
145 "<center><h1>411 Length Required</h1></center>" CRLF | 152 "<center><h1>411 Length Required</h1></center>" CRLF |
146 ; | 153 ; |
147 | 154 |
148 | 155 |
149 static char error_412_page[] = | 156 static char ngx_http_error_412_page[] = |
150 "<html>" CRLF | 157 "<html>" CRLF |
151 "<head><title>412 Precondition Failed</title></head>" CRLF | 158 "<head><title>412 Precondition Failed</title></head>" CRLF |
152 "<body bgcolor=\"white\">" CRLF | 159 "<body bgcolor=\"white\">" CRLF |
153 "<center><h1>412 Precondition Failed</h1></center>" CRLF | 160 "<center><h1>412 Precondition Failed</h1></center>" CRLF |
154 ; | 161 ; |
155 | 162 |
156 | 163 |
157 static char error_413_page[] = | 164 static char ngx_http_error_413_page[] = |
158 "<html>" CRLF | 165 "<html>" CRLF |
159 "<head><title>413 Request Entity Too Large</title></head>" CRLF | 166 "<head><title>413 Request Entity Too Large</title></head>" CRLF |
160 "<body bgcolor=\"white\">" CRLF | 167 "<body bgcolor=\"white\">" CRLF |
161 "<center><h1>413 Request Entity Too Large</h1></center>" CRLF | 168 "<center><h1>413 Request Entity Too Large</h1></center>" CRLF |
162 ; | 169 ; |
163 | 170 |
164 | 171 |
165 static char error_414_page[] = | 172 static char ngx_http_error_414_page[] = |
166 "<html>" CRLF | 173 "<html>" CRLF |
167 "<head><title>414 Request-URI Too Large</title></head>" CRLF | 174 "<head><title>414 Request-URI Too Large</title></head>" CRLF |
168 "<body bgcolor=\"white\">" CRLF | 175 "<body bgcolor=\"white\">" CRLF |
169 "<center><h1>414 Request-URI Too Large</h1></center>" CRLF | 176 "<center><h1>414 Request-URI Too Large</h1></center>" CRLF |
170 ; | 177 ; |
171 | 178 |
172 | 179 |
173 static char error_415_page[] = | 180 static char ngx_http_error_415_page[] = |
174 "<html>" CRLF | 181 "<html>" CRLF |
175 "<head><title>415 Unsupported Media Type</title></head>" CRLF | 182 "<head><title>415 Unsupported Media Type</title></head>" CRLF |
176 "<body bgcolor=\"white\">" CRLF | 183 "<body bgcolor=\"white\">" CRLF |
177 "<center><h1>415 Unsupported Media Type</h1></center>" CRLF | 184 "<center><h1>415 Unsupported Media Type</h1></center>" CRLF |
178 ; | 185 ; |
179 | 186 |
180 | 187 |
181 static char error_416_page[] = | 188 static char ngx_http_error_416_page[] = |
182 "<html>" CRLF | 189 "<html>" CRLF |
183 "<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF | 190 "<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF |
184 "<body bgcolor=\"white\">" CRLF | 191 "<body bgcolor=\"white\">" CRLF |
185 "<center><h1>416 Requested Range Not Satisfiable</h1></center>" CRLF | 192 "<center><h1>416 Requested Range Not Satisfiable</h1></center>" CRLF |
186 ; | 193 ; |
187 | 194 |
188 | 195 |
189 static char error_495_page[] = | 196 static char ngx_http_error_495_page[] = |
190 "<html>" CRLF | 197 "<html>" CRLF |
191 "<head><title>400 The SSL certificate error</title></head>" | 198 "<head><title>400 The SSL certificate error</title></head>" |
192 CRLF | 199 CRLF |
193 "<body bgcolor=\"white\">" CRLF | 200 "<body bgcolor=\"white\">" CRLF |
194 "<center><h1>400 Bad Request</h1></center>" CRLF | 201 "<center><h1>400 Bad Request</h1></center>" CRLF |
195 "<center>The SSL certificate error</center>" CRLF | 202 "<center>The SSL certificate error</center>" CRLF |
196 ; | 203 ; |
197 | 204 |
198 | 205 |
199 static char error_496_page[] = | 206 static char ngx_http_error_496_page[] = |
200 "<html>" CRLF | 207 "<html>" CRLF |
201 "<head><title>400 No required SSL certificate was sent</title></head>" | 208 "<head><title>400 No required SSL certificate was sent</title></head>" |
202 CRLF | 209 CRLF |
203 "<body bgcolor=\"white\">" CRLF | 210 "<body bgcolor=\"white\">" CRLF |
204 "<center><h1>400 Bad Request</h1></center>" CRLF | 211 "<center><h1>400 Bad Request</h1></center>" CRLF |
205 "<center>No required SSL certificate was sent</center>" CRLF | 212 "<center>No required SSL certificate was sent</center>" CRLF |
206 ; | 213 ; |
207 | 214 |
208 | 215 |
209 static char error_497_page[] = | 216 static char ngx_http_error_497_page[] = |
210 "<html>" CRLF | 217 "<html>" CRLF |
211 "<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>" | 218 "<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>" |
212 CRLF | 219 CRLF |
213 "<body bgcolor=\"white\">" CRLF | 220 "<body bgcolor=\"white\">" CRLF |
214 "<center><h1>400 Bad Request</h1></center>" CRLF | 221 "<center><h1>400 Bad Request</h1></center>" CRLF |
215 "<center>The plain HTTP request was sent to HTTPS port</center>" CRLF | 222 "<center>The plain HTTP request was sent to HTTPS port</center>" CRLF |
216 ; | 223 ; |
217 | 224 |
218 | 225 |
219 static char error_500_page[] = | 226 static char ngx_http_error_500_page[] = |
220 "<html>" CRLF | 227 "<html>" CRLF |
221 "<head><title>500 Internal Server Error</title></head>" CRLF | 228 "<head><title>500 Internal Server Error</title></head>" CRLF |
222 "<body bgcolor=\"white\">" CRLF | 229 "<body bgcolor=\"white\">" CRLF |
223 "<center><h1>500 Internal Server Error</h1></center>" CRLF | 230 "<center><h1>500 Internal Server Error</h1></center>" CRLF |
224 ; | 231 ; |
225 | 232 |
226 | 233 |
227 static char error_501_page[] = | 234 static char ngx_http_error_501_page[] = |
228 "<html>" CRLF | 235 "<html>" CRLF |
229 "<head><title>501 Method Not Implemented</title></head>" CRLF | 236 "<head><title>501 Method Not Implemented</title></head>" CRLF |
230 "<body bgcolor=\"white\">" CRLF | 237 "<body bgcolor=\"white\">" CRLF |
231 "<center><h1>501 Method Not Implemented</h1></center>" CRLF | 238 "<center><h1>501 Method Not Implemented</h1></center>" CRLF |
232 ; | 239 ; |
233 | 240 |
234 | 241 |
235 static char error_502_page[] = | 242 static char ngx_http_error_502_page[] = |
236 "<html>" CRLF | 243 "<html>" CRLF |
237 "<head><title>502 Bad Gateway</title></head>" CRLF | 244 "<head><title>502 Bad Gateway</title></head>" CRLF |
238 "<body bgcolor=\"white\">" CRLF | 245 "<body bgcolor=\"white\">" CRLF |
239 "<center><h1>502 Bad Gateway</h1></center>" CRLF | 246 "<center><h1>502 Bad Gateway</h1></center>" CRLF |
240 ; | 247 ; |
241 | 248 |
242 | 249 |
243 static char error_503_page[] = | 250 static char ngx_http_error_503_page[] = |
244 "<html>" CRLF | 251 "<html>" CRLF |
245 "<head><title>503 Service Temporarily Unavailable</title></head>" CRLF | 252 "<head><title>503 Service Temporarily Unavailable</title></head>" CRLF |
246 "<body bgcolor=\"white\">" CRLF | 253 "<body bgcolor=\"white\">" CRLF |
247 "<center><h1>503 Service Temporarily Unavailable</h1></center>" CRLF | 254 "<center><h1>503 Service Temporarily Unavailable</h1></center>" CRLF |
248 ; | 255 ; |
249 | 256 |
250 | 257 |
251 static char error_504_page[] = | 258 static char ngx_http_error_504_page[] = |
252 "<html>" CRLF | 259 "<html>" CRLF |
253 "<head><title>504 Gateway Time-out</title></head>" CRLF | 260 "<head><title>504 Gateway Time-out</title></head>" CRLF |
254 "<body bgcolor=\"white\">" CRLF | 261 "<body bgcolor=\"white\">" CRLF |
255 "<center><h1>504 Gateway Time-out</h1></center>" CRLF | 262 "<center><h1>504 Gateway Time-out</h1></center>" CRLF |
256 ; | 263 ; |
257 | 264 |
258 | 265 |
259 static char error_507_page[] = | 266 static char ngx_http_error_507_page[] = |
260 "<html>" CRLF | 267 "<html>" CRLF |
261 "<head><title>507 Insufficient Storage</title></head>" CRLF | 268 "<head><title>507 Insufficient Storage</title></head>" CRLF |
262 "<body bgcolor=\"white\">" CRLF | 269 "<body bgcolor=\"white\">" CRLF |
263 "<center><h1>507 Insufficient Storage</h1></center>" CRLF | 270 "<center><h1>507 Insufficient Storage</h1></center>" CRLF |
264 ; | 271 ; |
265 | 272 |
266 | 273 |
267 static ngx_str_t error_pages[] = { | 274 static ngx_str_t ngx_http_error_pages[] = { |
268 | 275 |
269 ngx_null_string, /* 201, 204 */ | 276 ngx_null_string, /* 201, 204 */ |
270 | 277 |
271 #define NGX_HTTP_LEVEL_200 1 | 278 #define NGX_HTTP_LEVEL_200 1 |
272 | 279 |
273 /* ngx_null_string, */ /* 300 */ | 280 /* ngx_null_string, */ /* 300 */ |
274 ngx_string(error_301_page), | 281 ngx_string(ngx_http_error_301_page), |
275 ngx_string(error_302_page), | 282 ngx_string(ngx_http_error_302_page), |
276 ngx_null_string, /* 303 */ | 283 ngx_null_string, /* 303 */ |
277 | 284 |
278 #define NGX_HTTP_LEVEL_300 3 | 285 #define NGX_HTTP_LEVEL_300 3 |
279 | 286 |
280 ngx_string(error_400_page), | 287 ngx_string(ngx_http_error_400_page), |
281 ngx_string(error_401_page), | 288 ngx_string(ngx_http_error_401_page), |
282 ngx_string(error_402_page), | 289 ngx_string(ngx_http_error_402_page), |
283 ngx_string(error_403_page), | 290 ngx_string(ngx_http_error_403_page), |
284 ngx_string(error_404_page), | 291 ngx_string(ngx_http_error_404_page), |
285 ngx_string(error_405_page), | 292 ngx_string(ngx_http_error_405_page), |
286 ngx_string(error_406_page), | 293 ngx_string(ngx_http_error_406_page), |
287 ngx_null_string, /* 407 */ | 294 ngx_null_string, /* 407 */ |
288 ngx_string(error_408_page), | 295 ngx_string(ngx_http_error_408_page), |
289 ngx_string(error_409_page), | 296 ngx_string(ngx_http_error_409_page), |
290 ngx_string(error_410_page), | 297 ngx_string(ngx_http_error_410_page), |
291 ngx_string(error_411_page), | 298 ngx_string(ngx_http_error_411_page), |
292 ngx_string(error_412_page), | 299 ngx_string(ngx_http_error_412_page), |
293 ngx_string(error_413_page), | 300 ngx_string(ngx_http_error_413_page), |
294 ngx_string(error_414_page), | 301 ngx_string(ngx_http_error_414_page), |
295 ngx_string(error_415_page), | 302 ngx_string(ngx_http_error_415_page), |
296 ngx_string(error_416_page), | 303 ngx_string(ngx_http_error_416_page), |
297 | 304 |
298 #define NGX_HTTP_LEVEL_400 17 | 305 #define NGX_HTTP_LEVEL_400 17 |
299 | 306 |
300 ngx_string(error_495_page), /* 495, https certificate error */ | 307 ngx_string(ngx_http_error_495_page), /* 495, https certificate error */ |
301 ngx_string(error_496_page), /* 496, https no certificate */ | 308 ngx_string(ngx_http_error_496_page), /* 496, https no certificate */ |
302 ngx_string(error_497_page), /* 497, http to https */ | 309 ngx_string(ngx_http_error_497_page), /* 497, http to https */ |
303 ngx_string(error_404_page), /* 498, invalid host name */ | 310 ngx_string(ngx_http_error_404_page), /* 498, canceled */ |
304 ngx_null_string, /* 499, client had closed connection */ | 311 ngx_null_string, /* 499, client has closed connection */ |
305 | 312 |
306 ngx_string(error_500_page), | 313 ngx_string(ngx_http_error_500_page), |
307 ngx_string(error_501_page), | 314 ngx_string(ngx_http_error_501_page), |
308 ngx_string(error_502_page), | 315 ngx_string(ngx_http_error_502_page), |
309 ngx_string(error_503_page), | 316 ngx_string(ngx_http_error_503_page), |
310 ngx_string(error_504_page), | 317 ngx_string(ngx_http_error_504_page), |
311 ngx_null_string, /* 505 */ | 318 ngx_null_string, /* 505 */ |
312 ngx_null_string, /* 506 */ | 319 ngx_null_string, /* 506 */ |
313 ngx_string(error_507_page) | 320 ngx_string(ngx_http_error_507_page) |
314 }; | 321 }; |
315 | 322 |
316 | 323 |
317 static ngx_str_t ngx_http_get_name = { 3, (u_char *) "GET " }; | 324 static ngx_str_t ngx_http_get_name = { 3, (u_char *) "GET " }; |
318 | 325 |
319 | 326 |
320 ngx_int_t | 327 ngx_int_t |
321 ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) | 328 ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) |
322 { | 329 { |
323 u_char *p; | |
324 size_t msie_refresh; | |
325 uintptr_t escape; | |
326 ngx_int_t rc; | 330 ngx_int_t rc; |
327 ngx_buf_t *b; | 331 ngx_uint_t i, err; |
328 ngx_str_t *uri, *location; | |
329 ngx_uint_t i, n, err, msie_padding; | |
330 ngx_chain_t *out, *cl; | |
331 ngx_http_err_page_t *err_page; | 332 ngx_http_err_page_t *err_page; |
332 ngx_http_core_loc_conf_t *clcf; | 333 ngx_http_core_loc_conf_t *clcf; |
333 | 334 |
334 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 335 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
335 "http special response: %d, \"%V\"", error, &r->uri); | 336 "http special response: %d, \"%V\"", error, &r->uri); |
376 } | 377 } |
377 | 378 |
378 err_page = clcf->error_pages->elts; | 379 err_page = clcf->error_pages->elts; |
379 | 380 |
380 for (i = 0; i < clcf->error_pages->nelts; i++) { | 381 for (i = 0; i < clcf->error_pages->nelts; i++) { |
381 | |
382 if (err_page[i].status == error) { | 382 if (err_page[i].status == error) { |
383 r->err_status = err_page[i].overwrite; | 383 return ngx_http_send_error_page(r, &err_page[i]); |
384 | |
385 r->method = NGX_HTTP_GET; | |
386 r->method_name = ngx_http_get_name; | |
387 | |
388 uri = &err_page[i].uri; | |
389 | |
390 if (err_page[i].uri_lengths) { | |
391 if (ngx_http_script_run(r, uri, | |
392 err_page[i].uri_lengths->elts, 0, | |
393 err_page[i].uri_values->elts) | |
394 == NULL) | |
395 { | |
396 return NGX_ERROR; | |
397 } | |
398 | |
399 if (r->zero_in_uri) { | |
400 for (n = 0; n < uri->len; n++) { | |
401 if (uri->data[n] == '\0') { | |
402 goto zero; | |
403 } | |
404 } | |
405 | |
406 r->zero_in_uri = 0; | |
407 } | |
408 | |
409 } else { | |
410 r->zero_in_uri = 0; | |
411 } | |
412 | |
413 zero: | |
414 | |
415 if (uri->data[0] == '/') { | |
416 return ngx_http_internal_redirect(r, uri, NULL); | |
417 } | |
418 | |
419 if (uri->data[0] == '@') { | |
420 return ngx_http_named_location(r, uri); | |
421 } | |
422 | |
423 r->headers_out.location = | |
424 ngx_list_push(&r->headers_out.headers); | |
425 | |
426 if (r->headers_out.location) { | |
427 error = NGX_HTTP_MOVED_TEMPORARILY; | |
428 | |
429 r->err_status = NGX_HTTP_MOVED_TEMPORARILY; | |
430 | |
431 r->headers_out.location->hash = 1; | |
432 r->headers_out.location->key.len = sizeof("Location") - 1; | |
433 r->headers_out.location->key.data = (u_char *) "Location"; | |
434 r->headers_out.location->value = *uri; | |
435 | |
436 } else { | |
437 return NGX_ERROR; | |
438 } | |
439 } | 384 } |
440 } | 385 } |
386 } | |
387 | |
388 if (clcf->msie_refresh | |
389 && r->headers_in.msie | |
390 && (error == NGX_HTTP_MOVED_PERMANENTLY | |
391 || error == NGX_HTTP_MOVED_TEMPORARILY)) | |
392 { | |
393 return ngx_http_send_refresh(r); | |
441 } | 394 } |
442 | 395 |
443 if (error == NGX_HTTP_CREATED) { | 396 if (error == NGX_HTTP_CREATED) { |
444 /* 201 */ | 397 /* 201 */ |
445 err = 0; | 398 err = 0; |
466 switch (error) { | 419 switch (error) { |
467 case NGX_HTTP_TO_HTTPS: | 420 case NGX_HTTP_TO_HTTPS: |
468 case NGX_HTTPS_CERT_ERROR: | 421 case NGX_HTTPS_CERT_ERROR: |
469 case NGX_HTTPS_NO_CERT: | 422 case NGX_HTTPS_NO_CERT: |
470 r->err_status = NGX_HTTP_BAD_REQUEST; | 423 r->err_status = NGX_HTTP_BAD_REQUEST; |
471 error = NGX_HTTP_BAD_REQUEST; | |
472 break; | 424 break; |
473 } | 425 } |
474 } | 426 } |
475 | 427 |
428 return ngx_http_send_special_response(r, clcf, err); | |
429 } | |
430 | |
431 | |
432 static ngx_int_t | |
433 ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) | |
434 { | |
435 u_char ch, *p, *last; | |
436 ngx_str_t *uri, *args, u, a; | |
437 ngx_table_elt_t *location; | |
438 ngx_http_core_loc_conf_t *clcf; | |
439 | |
440 r->err_status = err_page->overwrite; | |
441 | |
442 r->method = NGX_HTTP_GET; | |
443 r->method_name = ngx_http_get_name; | |
444 | |
445 r->zero_in_uri = 0; | |
446 | |
447 args = NULL; | |
448 | |
449 if (err_page->uri_lengths) { | |
450 if (ngx_http_script_run(r, &u, err_page->uri_lengths->elts, 0, | |
451 err_page->uri_values->elts) | |
452 == NULL) | |
453 { | |
454 return NGX_ERROR; | |
455 } | |
456 | |
457 p = u.data; | |
458 uri = &u; | |
459 | |
460 if (*p == '/') { | |
461 | |
462 last = p + uri->len; | |
463 | |
464 while (p < last) { | |
465 | |
466 ch = *p++; | |
467 | |
468 if (ch == '?') { | |
469 a.len = last - p; | |
470 a.data = p; | |
471 args = &a; | |
472 | |
473 u.len = p - 1 - u.data; | |
474 | |
475 while (p < last) { | |
476 if (*p++ == '\0') { | |
477 r->zero_in_uri = 1; | |
478 break; | |
479 } | |
480 } | |
481 | |
482 break; | |
483 } | |
484 | |
485 if (ch == '\0') { | |
486 r->zero_in_uri = 1; | |
487 continue; | |
488 } | |
489 } | |
490 } | |
491 | |
492 } else { | |
493 uri = &err_page->uri; | |
494 } | |
495 | |
496 if (uri->data[0] == '/') { | |
497 return ngx_http_internal_redirect(r, uri, args); | |
498 } | |
499 | |
500 if (uri->data[0] == '@') { | |
501 return ngx_http_named_location(r, uri); | |
502 } | |
503 | |
504 location = ngx_list_push(&r->headers_out.headers); | |
505 | |
506 if (location == NULL) { | |
507 return NGX_ERROR; | |
508 } | |
509 | |
510 r->err_status = NGX_HTTP_MOVED_TEMPORARILY; | |
511 | |
512 location->hash = 1; | |
513 location->key.len = sizeof("Location") - 1; | |
514 location->key.data = (u_char *) "Location"; | |
515 location->value = *uri; | |
516 | |
517 r->headers_out.location = location; | |
518 | |
519 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
520 | |
521 if (clcf->msie_refresh && r->headers_in.msie) { | |
522 return ngx_http_send_refresh(r); | |
523 } | |
524 | |
525 return ngx_http_send_special_response(r, clcf, NGX_HTTP_MOVED_TEMPORARILY | |
526 - NGX_HTTP_MOVED_PERMANENTLY | |
527 + NGX_HTTP_LEVEL_200); | |
528 } | |
529 | |
530 | |
531 static ngx_int_t | |
532 ngx_http_send_special_response(ngx_http_request_t *r, | |
533 ngx_http_core_loc_conf_t *clcf, ngx_uint_t err) | |
534 { | |
535 u_char *tail; | |
536 size_t len; | |
537 ngx_int_t rc; | |
538 ngx_buf_t *b; | |
539 ngx_uint_t msie_padding; | |
540 ngx_chain_t out[3]; | |
541 | |
542 if (clcf->server_tokens) { | |
543 len = sizeof(ngx_http_error_full_tail) - 1; | |
544 tail = ngx_http_error_full_tail; | |
545 | |
546 } else { | |
547 len = sizeof(ngx_http_error_tail) - 1; | |
548 tail = ngx_http_error_tail; | |
549 } | |
550 | |
476 msie_padding = 0; | 551 msie_padding = 0; |
477 | 552 |
478 if (!r->zero_body) { | 553 if (!r->zero_body) { |
479 if (error_pages[err].len) { | 554 if (ngx_http_error_pages[err].len) { |
480 r->headers_out.content_length_n = error_pages[err].len | 555 r->headers_out.content_length_n = ngx_http_error_pages[err].len |
481 + (clcf->server_tokens ? sizeof(error_full_tail) - 1: | 556 + len; |
482 sizeof(error_tail) - 1); | |
483 | |
484 if (clcf->msie_padding | 557 if (clcf->msie_padding |
485 && r->headers_in.msie | 558 && r->headers_in.msie |
486 && r->http_version >= NGX_HTTP_VERSION_10 | 559 && r->http_version >= NGX_HTTP_VERSION_10 |
487 && error >= NGX_HTTP_BAD_REQUEST | 560 && err >= NGX_HTTP_LEVEL_300) |
488 && error != NGX_HTTP_REQUEST_URI_TOO_LARGE) | |
489 { | 561 { |
490 r->headers_out.content_length_n += | 562 r->headers_out.content_length_n += |
491 sizeof(ngx_http_msie_stub) - 1; | 563 sizeof(ngx_http_msie_stub) - 1; |
492 msie_padding = 1; | 564 msie_padding = 1; |
493 } | 565 } |
494 | 566 |
567 r->headers_out.content_type_len = sizeof("text/html") - 1; | |
495 r->headers_out.content_type.len = sizeof("text/html") - 1; | 568 r->headers_out.content_type.len = sizeof("text/html") - 1; |
496 r->headers_out.content_type.data = (u_char *) "text/html"; | 569 r->headers_out.content_type.data = (u_char *) "text/html"; |
497 | 570 |
498 } else { | 571 } else { |
499 r->headers_out.content_length_n = -1; | 572 r->headers_out.content_length_n = -1; |
507 if (r->headers_out.content_length) { | 580 if (r->headers_out.content_length) { |
508 r->headers_out.content_length->hash = 0; | 581 r->headers_out.content_length->hash = 0; |
509 r->headers_out.content_length = NULL; | 582 r->headers_out.content_length = NULL; |
510 } | 583 } |
511 | 584 |
512 if (clcf->msie_refresh | |
513 && r->headers_in.msie | |
514 && (error == NGX_HTTP_MOVED_PERMANENTLY | |
515 || error == NGX_HTTP_MOVED_TEMPORARILY)) | |
516 { | |
517 | |
518 location = &r->headers_out.location->value; | |
519 | |
520 escape = 2 * ngx_escape_uri(NULL, location->data, location->len, | |
521 NGX_ESCAPE_REFRESH); | |
522 | |
523 msie_refresh = sizeof(ngx_http_msie_refresh_head) - 1 | |
524 + escape + location->len | |
525 + sizeof(ngx_http_msie_refresh_tail) - 1; | |
526 | |
527 r->err_status = NGX_HTTP_OK; | |
528 r->headers_out.content_type_len = sizeof("text/html") - 1; | |
529 r->headers_out.content_length_n = msie_refresh; | |
530 r->headers_out.location->hash = 0; | |
531 r->headers_out.location = NULL; | |
532 | |
533 } else { | |
534 location = NULL; | |
535 escape = 0; | |
536 msie_refresh = 0; | |
537 } | |
538 | |
539 ngx_http_clear_accept_ranges(r); | 585 ngx_http_clear_accept_ranges(r); |
540 ngx_http_clear_last_modified(r); | 586 ngx_http_clear_last_modified(r); |
541 | 587 |
542 rc = ngx_http_send_header(r); | 588 rc = ngx_http_send_header(r); |
543 | 589 |
544 if (rc == NGX_ERROR || r->header_only) { | 590 if (rc == NGX_ERROR || r->header_only) { |
545 return rc; | 591 return rc; |
546 } | 592 } |
547 | 593 |
548 | 594 if (ngx_http_error_pages[err].len == 0) { |
549 if (msie_refresh == 0) { | 595 return NGX_OK; |
550 | 596 } |
551 if (error_pages[err].len == 0) { | 597 |
552 return NGX_OK; | 598 b = ngx_calloc_buf(r->pool); |
553 } | 599 if (b == NULL) { |
554 | 600 return NGX_ERROR; |
601 } | |
602 | |
603 b->memory = 1; | |
604 b->pos = ngx_http_error_pages[err].data; | |
605 b->last = ngx_http_error_pages[err].data + ngx_http_error_pages[err].len; | |
606 | |
607 out[0].buf = b; | |
608 out[0].next = &out[1]; | |
609 | |
610 b = ngx_calloc_buf(r->pool); | |
611 if (b == NULL) { | |
612 return NGX_ERROR; | |
613 } | |
614 | |
615 b->memory = 1; | |
616 | |
617 b->pos = tail; | |
618 b->last = tail + len; | |
619 | |
620 out[1].buf = b; | |
621 out[1].next = NULL;; | |
622 | |
623 if (msie_padding) { | |
555 b = ngx_calloc_buf(r->pool); | 624 b = ngx_calloc_buf(r->pool); |
556 if (b == NULL) { | 625 if (b == NULL) { |
557 return NGX_ERROR; | 626 return NGX_ERROR; |
558 } | 627 } |
559 | 628 |
560 b->memory = 1; | 629 b->memory = 1; |
561 b->pos = error_pages[err].data; | 630 b->pos = ngx_http_msie_stub; |
562 b->last = error_pages[err].data + error_pages[err].len; | 631 b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1; |
563 | 632 |
564 cl = ngx_alloc_chain_link(r->pool); | 633 out[1].next = &out[2]; |
565 if (cl == NULL) { | 634 out[2].buf = b; |
566 return NGX_ERROR; | 635 out[2].next = NULL;; |
567 } | |
568 | |
569 cl->buf = b; | |
570 out = cl; | |
571 | |
572 | |
573 b = ngx_calloc_buf(r->pool); | |
574 if (b == NULL) { | |
575 return NGX_ERROR; | |
576 } | |
577 | |
578 b->memory = 1; | |
579 | |
580 if (clcf->server_tokens) { | |
581 b->pos = error_full_tail; | |
582 b->last = error_full_tail + sizeof(error_full_tail) - 1; | |
583 } else { | |
584 b->pos = error_tail; | |
585 b->last = error_tail + sizeof(error_tail) - 1; | |
586 } | |
587 | |
588 cl->next = ngx_alloc_chain_link(r->pool); | |
589 if (cl->next == NULL) { | |
590 return NGX_ERROR; | |
591 } | |
592 | |
593 cl = cl->next; | |
594 cl->buf = b; | |
595 | |
596 if (msie_padding) { | |
597 b = ngx_calloc_buf(r->pool); | |
598 if (b == NULL) { | |
599 return NGX_ERROR; | |
600 } | |
601 | |
602 b->memory = 1; | |
603 b->pos = ngx_http_msie_stub; | |
604 b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1; | |
605 | |
606 cl->next = ngx_alloc_chain_link(r->pool); | |
607 if (cl->next == NULL) { | |
608 return NGX_ERROR; | |
609 } | |
610 | |
611 cl = cl->next; | |
612 cl->buf = b; | |
613 } | |
614 | |
615 } else { | |
616 b = ngx_create_temp_buf(r->pool, msie_refresh); | |
617 if (b == NULL) { | |
618 return NGX_ERROR; | |
619 } | |
620 | |
621 p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head, | |
622 sizeof(ngx_http_msie_refresh_head) - 1); | |
623 | |
624 if (escape == 0) { | |
625 p = ngx_cpymem(p, location->data, location->len); | |
626 | |
627 } else { | |
628 p = (u_char *) ngx_escape_uri(p, location->data, location->len, | |
629 NGX_ESCAPE_REFRESH); | |
630 } | |
631 | |
632 b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail, | |
633 sizeof(ngx_http_msie_refresh_tail) - 1); | |
634 | |
635 cl = ngx_alloc_chain_link(r->pool); | |
636 if (cl == NULL) { | |
637 return NGX_ERROR; | |
638 } | |
639 | |
640 cl->buf = b; | |
641 out = cl; | |
642 } | 636 } |
643 | 637 |
644 if (r == r->main) { | 638 if (r == r->main) { |
645 b->last_buf = 1; | 639 b->last_buf = 1; |
646 } | 640 } |
647 | 641 |
648 b->last_in_chain = 1; | 642 b->last_in_chain = 1; |
649 | 643 |
650 cl->next = NULL; | 644 return ngx_http_output_filter(r, &out[0]); |
651 | |
652 return ngx_http_output_filter(r, out); | |
653 } | 645 } |
646 | |
647 | |
648 static ngx_int_t | |
649 ngx_http_send_refresh(ngx_http_request_t *r) | |
650 { | |
651 u_char *p, *location; | |
652 size_t len, size; | |
653 uintptr_t escape; | |
654 ngx_int_t rc; | |
655 ngx_buf_t *b; | |
656 ngx_chain_t out; | |
657 | |
658 len = r->headers_out.location->value.len; | |
659 location = r->headers_out.location->value.data; | |
660 | |
661 escape = 2 * ngx_escape_uri(NULL, location, len, NGX_ESCAPE_REFRESH); | |
662 | |
663 size = sizeof(ngx_http_msie_refresh_head) - 1 | |
664 + escape + len | |
665 + sizeof(ngx_http_msie_refresh_tail) - 1; | |
666 | |
667 r->err_status = NGX_HTTP_OK; | |
668 | |
669 r->headers_out.content_type_len = sizeof("text/html") - 1; | |
670 r->headers_out.content_type.len = sizeof("text/html") - 1; | |
671 r->headers_out.content_type.data = (u_char *) "text/html"; | |
672 | |
673 r->headers_out.location->hash = 0; | |
674 r->headers_out.location = NULL; | |
675 | |
676 r->headers_out.content_length_n = size; | |
677 | |
678 if (r->headers_out.content_length) { | |
679 r->headers_out.content_length->hash = 0; | |
680 r->headers_out.content_length = NULL; | |
681 } | |
682 | |
683 ngx_http_clear_accept_ranges(r); | |
684 ngx_http_clear_last_modified(r); | |
685 | |
686 rc = ngx_http_send_header(r); | |
687 | |
688 if (rc == NGX_ERROR || r->header_only) { | |
689 return rc; | |
690 } | |
691 | |
692 b = ngx_create_temp_buf(r->pool, size); | |
693 if (b == NULL) { | |
694 return NGX_ERROR; | |
695 } | |
696 | |
697 p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head, | |
698 sizeof(ngx_http_msie_refresh_head) - 1); | |
699 | |
700 if (escape == 0) { | |
701 p = ngx_cpymem(p, location, len); | |
702 | |
703 } else { | |
704 p = (u_char *) ngx_escape_uri(p, location, len, NGX_ESCAPE_REFRESH); | |
705 } | |
706 | |
707 b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail, | |
708 sizeof(ngx_http_msie_refresh_tail) - 1); | |
709 | |
710 b->last_buf = 1; | |
711 b->last_in_chain = 1; | |
712 | |
713 out.buf = b; | |
714 out.next = NULL; | |
715 | |
716 return ngx_http_output_filter(r, &out); | |
717 } |