Unencoded Location: header when redirecting

Were seeing the following behavior in nginx 1.4.6:

  • User navigates to location w/ spaces in the URL
    (“http://example.org/When%20Harry%20Met%20Sally”). The location points
    to a directory on the filesystem with spaces in its name ("/items/When
    Harry Met Sally).

  • nginx returns 301 Moved Permanently with the Location: URL unencoded
    and a trailing slash added:

Location: http://example.org/When Harry Met Sally/

  • Some software (i.e. PHP) will automatically follow the redirect, but
    because it expects an encoded Location: header, it sends exactly what
    was returned from the server. (Note that curl, wget, and others will
    fixup unencoded Location: headers, but thats not what HTTP spec
    requires.)

  • nginx will normally process URLs with spaces in them, but because of
    its request parsing algorithm, it fails w/ a 400 Bad Request when it
    sees the uppercase H in Harry in the URL
    (#196 (Inconsistent behavior on uri's with unencoded spaces followed by H) – nginx).

In other words, this is the transaction chain:

C: GET http://example.org/When%20Harry%20Met%20Sally HTTP/1.1

S: HTTP/1.1 301 Moved Permanently
S: Location: http://example.org/When Harry Met Sally/

C: GET http://example.org/When Harry Met Sally/ HTTP/1.1

S: 400 Bad Request

I believe the 301 originates from within the nginx code itself
(ngx_http_static_module.c:147-193?) and not from our rewrite rules. As
I read the HTTP spec, Location: must be encoded.

Jim