Why does my WSGI app always get URL decoded path in environ['PATH_INFO']?
Question: I have a simple bare WSGI application:

    
    
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type','text/html')])
        print('PATH_INFO:', environ['PATH_INFO'])
        return [b'<p>Hello World</p>']
    
    if __name__ == '__main__':
        from wsgiref import simple_server
        server = simple_server.make_server('0.0.0.0', 8080, application)
        server.serve_forever()
    

I make two requests:

    
    
    C:\>curl "http://localhost:8080/<foo>"
    <p>Hello World</p>
    C:\>curl "http://localhost:8080/%3Cfoo%3E"
    <p>Hello World</p>
    

I get this output:

    
    
    C:\code>python foo.py
    PATH_INFO: /<foo>
    127.0.0.1 - - [09/Mar/2014 13:48:39] "GET /<foo> HTTP/1.1" 200 18
    PATH_INFO: /<foo>
    127.0.0.1 - - [09/Mar/2014 13:48:47] "GET /%3Cfoo%3E HTTP/1.1" 200 18
    

See how my application gets the URL decoded path `/foo` even when the client
requests `/%3Cfoo%3E`.

It shows that wsgiref.simple_server ensures that my application always gets
the URL-decoded path in `environ['PATH_INFO']`.

But I can't find this behavior documented anywhere in PEP-3333. Can you please
point me to an official documentation that documents this behavior?


Answer: The value of REQUEST_URI from the actual HTTP request line, if the server
makes it available, would be:

    
    
    REQUEST_URI: '/%3Cfoo%3E'
    

This is probably the case even if you used:

    
    
    curl "http://localhost:8080/<foo>"
    

because curl would encode the URL before sending to use the % escapes.

REQUEST_URI is not I believe covered by any RFC but is a variable provided by
many servers. You cannot rely on its presence though, so don't write your WSGI
application to depend on it existing.

The web server will decode the % escapes in REQUEST_URI before processing it.
The result which will end up in PATH_INFO will thus always be:

    
    
    PATH_INFO: '/<foo>'
    

The decoding is covered by the CGI and related RFCs that WSGI builds on.

See for example:

  * <http://www.ietf.org/rfc/rfc3875>
  * <http://www.ietf.org/rfc/rfc2396>

