Custom page for 400 (Bad Request)

Igor Sysoev igor at sysoev.ru
Wed Dec 15 02:33:05 MSK 2010


On Wed, Dec 15, 2010 at 01:35:17AM +0300, Igor Sysoev wrote:

> On Tue, Dec 14, 2010 at 12:33:02PM -0500, Denis wrote:
> 
> > [quote]
> > This should be added to default server, as error 400 is generated
> > before any server_name matching occurs.
> > [/quote]
> > 
> > Yep, I added it to the default server. At least, it's listening as
> > [code]
> > listen       80 default;
> > [/code]
> > 
> > [quote]
> > Note that you may also bump client_header_buffer_size /
> > large_client_header_buffers if you want cookies in question to be
> > actually accepted and processed (this should be done in default
> > server, too, or at http level).
> > [/quote]
> > That's exactly what I'm bumping. Sorry, I should have made it more clear
> > in my first post. I don't want to make my large_client_header_buffer 1
> > megabyte and I need some kind of way to fall back gracefully when a
> > client appears with 1Mbyte cookie. Like show him a page saying "your
> > cookie is too large, please delete it" or delete it in javascript.
> > But the problem is, I either get that hardcoded simple page or get http
> > response with no response body at all.
> > [code]
> > $ curl http://foobar.com/ -b hugecookies.jar
> > HTTP/1.1 400 Bad Request
> > Server: nginx
> > Date: Tue, 14 Dec 2010 17:29:07 GMT
> > Content-Type: text/html; charset=EUC-JP
> > Content-Length: 237
> > Connection: close
> > 
> > curl: (55) Send failure: Connection reset by peer
> > $
> > [/code]
> 
> The attached patch allows HTTP lingering close for 400 responses.
> However, it will not be included in next releases: I'm going to
> introduce a special code, say 490, for long HTTP header lines as
> it's already done for SSL errors (495, 496, and 497). Then you can
> set expliclty
> 
>     error_page  490  =200 /large_cookie.html;

The new patch introduce the new error code 494.
It can be used as

      error_page  494  =200 /large_cookie.html;

If it's not handled via error_page, it returns 400 code.


-- 
Igor Sysoev
http://sysoev.ru/en/
-------------- next part --------------
Index: src/http/ngx_http_request.h
===================================================================
--- src/http/ngx_http_request.h	(revision 3164)
+++ src/http/ngx_http_request.h	(working copy)
@@ -95,8 +95,10 @@
 /* The special code to close connection without any response */
 #define NGX_HTTP_CLOSE                     444
 
-#define NGX_HTTP_OWN_CODES                 495
+#define NGX_HTTP_NGINX_CODES               494
 
+#define NGX_HTTP_TOO_LONG_HEADER_LINE      494
+
 #define NGX_HTTPS_CERT_ERROR               495
 #define NGX_HTTPS_NO_CERT                  496
 
Index: src/http/ngx_http_special_response.c
===================================================================
--- src/http/ngx_http_special_response.c	(revision 3164)
+++ src/http/ngx_http_special_response.c	(working copy)
@@ -201,6 +201,16 @@
 ;
 
 
+static char ngx_http_error_494_page[] =
+"<html>" CRLF
+"<head><title>400 Too Long Header Line</title></head>"
+CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>400 Bad Request</h1></center>" CRLF
+"<center>Too Long Header Line</center>" CRLF
+;
+
+
 static char ngx_http_error_495_page[] =
 "<html>" CRLF
 "<head><title>400 The SSL certificate error</title></head>"
@@ -315,6 +325,7 @@
 #define NGX_HTTP_LAST_LEVEL_400  417
 #define NGX_HTTP_LEVEL_400       (NGX_HTTP_LAST_LEVEL_400 - 400)
 
+    ngx_string(ngx_http_error_494_page), /* 494, too long header line */
     ngx_string(ngx_http_error_495_page), /* 495, https certificate error */
     ngx_string(ngx_http_error_496_page), /* 496, https no certificate */
     ngx_string(ngx_http_error_497_page), /* 497, http to https */
@@ -429,14 +440,15 @@
         err = error - NGX_HTTP_BAD_REQUEST + NGX_HTTP_LEVEL_200
                                            + NGX_HTTP_LEVEL_300;
 
-    } else if (error >= NGX_HTTP_OWN_CODES
+    } else if (error >= NGX_HTTP_NGINX_CODES
                && error < NGX_HTTP_LAST_LEVEL_500)
     {
         /* 49X, 5XX */
-        err = error - NGX_HTTP_OWN_CODES + NGX_HTTP_LEVEL_200
-                                         + NGX_HTTP_LEVEL_300
-                                         + NGX_HTTP_LEVEL_400;
+        err = error - NGX_HTTP_NGINX_CODES + NGX_HTTP_LEVEL_200
+                                           + NGX_HTTP_LEVEL_300
+                                           + NGX_HTTP_LEVEL_400;
         switch (error) {
+            case NGX_HTTP_TOO_LONG_HEADER_LINE:
             case NGX_HTTP_TO_HTTPS:
             case NGX_HTTPS_CERT_ERROR:
             case NGX_HTTPS_NO_CERT:
Index: src/http/ngx_http_request.c
===================================================================
--- src/http/ngx_http_request.c	(revision 3165)
+++ src/http/ngx_http_request.c	(working copy)
@@ -995,7 +995,9 @@
                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
                                   "client sent too long header line: \"%*s\"",
                                   len, r->header_name_start);
-                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+
+                    r->lingering_close = 1;
+                    ngx_http_finalize_request(r, NGX_HTTP_TOO_LONG_HEADER_LINE);
                     return;
                 }
             }


More information about the nginx mailing list