spaces in URI
Igor Sysoev
igor at sysoev.ru
Sat Jun 12 00:35:13 MSD 2010
On Fri, Jun 11, 2010 at 04:07:10PM -0400, Peter Portante wrote:
> Hi Igor,
>
> This is working great. Thank you!
>
> Should we be prepared to maintain this as a patch on the 0.8 stream, or
> would some variation of this fix be folded into 0.8 (via some config setting
> or as the new behavior)?
>
> And while we are at it, how stable is 0.8? I thought I had seen some
> discussion of 0.8 being marked "stable" soon. Just curious.
Here is a new patch that encodes these spaces as %20 while talking
to a proxied backend. I'm going to commit the patch in next 0.8.41.
0.8 is stable, use it.
> Thanks,
>
> -peter
>
>
> On 6/11/10 4:09 AM, "Igor Sysoev" <igor at sysoev.ru> wrote:
>
> > On Fri, Jun 11, 2010 at 02:54:35AM -0400, Peter Portante wrote:
> >
> >> Hi Folks,
> >>
> >> We are running into a small problem with bad HTTP clients.
> >>
> >> We have sold a bunch of hardware with embedded HTTP clients which don't
> >> URL-encode the parameter values. For example:
> >>
> >> GET /a/r?did=X234 567 Y HTTP/1.1
> >>
> >> We were using a pair of Apache servers behind a hardware load-balancer and
> >> switched our environment to front those Apache servers with a pair of Nginx
> >> servers. We actually use those Nginx servers for a number of other web sites
> >> we serve.
> >>
> >> When we made this switch, these particular clients stopped working. Nginx is
> >> responding immediately after receiving the "GET" line above with "400 Bad
> >> Request". This *is* valid behavior on Nginx's part, as according to our
> >> understanding of the HTTP protocol, no spaces are allowed in the request
> >> URI.
> >>
> >> Apache is apparently rather forgiving on this front. Is there some setting
> >> or configuration parameter in Nginx that would make it more forgiving of
> >> these spaces in the request URI?
> >>
> >> If there is not, would it be difficult for us to modify Nginx to make it
> >> more forgiving? If so, any pointers as to where to start?
> >>
> >> Our other options we can think of are:
> >>
> >> 1. route HTTP traffic from these clients to Apache servers
> >> 2. leave them dead in the water until customers complain so we can tell them
> >> to upgrade their firmware for the fix
> >>
> >> Thanks for any help or pointers you can offer.
> >
> > Try the attached patch against 0.8.40.
> >
>
--
Igor Sysoev
http://sysoev.ru/en/
-------------- next part --------------
Index: src/http/ngx_http_request.c
===================================================================
--- src/http/ngx_http_request.c (revision 2933)
+++ src/http/ngx_http_request.c (working copy)
@@ -756,6 +756,7 @@
r->unparsed_uri.len = r->uri_end - r->uri_start;
r->unparsed_uri.data = r->uri_start;
+ r->valid_unparsed_uri = r->space_in_uri ? 0 : 1;
r->method_name.len = r->method_end - r->request_start + 1;
r->method_name.data = r->request_line.data;
Index: src/http/ngx_http_core_module.c
===================================================================
--- src/http/ngx_http_core_module.c (revision 2933)
+++ src/http/ngx_http_core_module.c (working copy)
@@ -824,10 +824,6 @@
r->phase_handler = cmcf->phase_engine.server_rewrite_index;
}
- if (r->unparsed_uri.len) {
- r->valid_unparsed_uri = 1;
- }
-
r->valid_location = 1;
#if (NGX_HTTP_GZIP)
r->gzip_tested = 0;
Index: src/http/ngx_http_request.h
===================================================================
--- src/http/ngx_http_request.h (revision 2933)
+++ src/http/ngx_http_request.h (working copy)
@@ -437,6 +437,9 @@
/* URI with "+" */
unsigned plus_in_uri:1;
+ /* URI with " " */
+ unsigned space_in_uri:1;
+
unsigned invalid_header:1;
unsigned add_uri_to_alias:1;
Index: src/http/ngx_http_parse.c
===================================================================
--- src/http/ngx_http_parse.c (revision 2933)
+++ src/http/ngx_http_parse.c (working copy)
@@ -112,8 +112,10 @@
sw_schema_slash_slash,
sw_host,
sw_port,
+ sw_host_http_09,
sw_after_slash_in_uri,
sw_check_uri,
+ sw_check_uri_http_09,
sw_uri,
sw_http_09,
sw_http_H,
@@ -357,7 +359,7 @@
*/
r->uri_start = r->schema_end + 1;
r->uri_end = r->schema_end + 2;
- state = sw_http_09;
+ state = sw_host_http_09;
break;
default:
return NGX_HTTP_PARSE_INVALID_REQUEST;
@@ -383,13 +385,35 @@
*/
r->uri_start = r->schema_end + 1;
r->uri_end = r->schema_end + 2;
- state = sw_http_09;
+ state = sw_host_http_09;
break;
default:
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
break;
+ /* space+ after "http://host[:port] " */
+ case sw_host_http_09:
+ switch (ch) {
+ case ' ':
+ break;
+ case CR:
+ r->http_minor = 9;
+ state = sw_almost_done;
+ break;
+ case LF:
+ r->http_minor = 9;
+ goto done;
+ case 'H':
+ r->http_protocol.data = p;
+ state = sw_http_H;
+ break;
+ default:
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ break;
+
+
/* check "/.", "//", "%", and "\" (Win32) in URI */
case sw_after_slash_in_uri:
@@ -401,7 +425,7 @@
switch (ch) {
case ' ':
r->uri_end = p;
- state = sw_http_09;
+ state = sw_check_uri_http_09;
break;
case CR:
r->uri_end = p;
@@ -466,7 +490,7 @@
break;
case ' ':
r->uri_end = p;
- state = sw_http_09;
+ state = sw_check_uri_http_09;
break;
case CR:
r->uri_end = p;
@@ -503,6 +527,30 @@
}
break;
+ /* space+ after URI */
+ case sw_check_uri_http_09:
+ switch (ch) {
+ case ' ':
+ break;
+ case CR:
+ r->http_minor = 9;
+ state = sw_almost_done;
+ break;
+ case LF:
+ r->http_minor = 9;
+ goto done;
+ case 'H':
+ r->http_protocol.data = p;
+ state = sw_http_H;
+ break;
+ default:
+ r->space_in_uri = 1;
+ state = sw_check_uri;
+ break;
+ }
+ break;
+
+
/* URI */
case sw_uri:
@@ -549,7 +597,9 @@
state = sw_http_H;
break;
default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
+ r->space_in_uri = 1;
+ state = sw_uri;
+ break;
}
break;
Index: src/http/modules/ngx_http_proxy_module.c
===================================================================
--- src/http/modules/ngx_http_proxy_module.c (revision 2933)
+++ src/http/modules/ngx_http_proxy_module.c (working copy)
@@ -911,7 +911,7 @@
loc_len = (r->valid_location && ctx->vars.uri.len) ?
plcf->location.len : 0;
- if (r->quoted_uri || r->internal) {
+ if (r->quoted_uri || r->space_in_uri || r->internal) {
escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
r->uri.len - loc_len, NGX_ESCAPE_URI);
}
More information about the nginx
mailing list