comparison src/http/ngx_http_special_response.c @ 330:c60beecc6ab5 NGINX_0_5_35

nginx 0.5.35 *) Change: now the ngx_http_userid_module adds start time microseconds to the cookie field contains a pid value. *) Change: now the uname(2) is used on Linux instead of procfs. Thanks to Ilya Novikov. *) Feature: the "If-Range" request header line support. Thanks to Alexander V. Inyukhin. *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" error; bug appeared in 0.5.13. *) Bugfix: the STARTTLS in SMTP mode did not work. Thanks to Oleg Motienko. *) Bugfix: large_client_header_buffers did not freed before going to keep-alive state. Thanks to Olexander Shtepa. *) Bugfix: the "limit_rate" directive did not allow to use full throughput, even if limit value was very high. *) Bugfix: the $status variable was equal to 0 if a proxied server returned response in HTTP/0.9 version. *) Bugfix: if the "?" character was in a "error_page" directive, then it was escaped in a proxied request; bug appeared in 0.5.32.
author Igor Sysoev <http://sysoev.ru>
date Tue, 08 Jan 2008 00:00:00 +0300
parents 26ff8d6b618d
children
comparison
equal deleted inserted replaced
329:d792b2cd78fe 330:c60beecc6ab5
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 }