Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#23398 closed New feature (fixed)

Attempting to access a manage.py runserver instance over HTTPS raises UnicodeDecodeError

Reported by: Robert Rollins Owned by: Flavio Curella
Component: HTTP handling Version: 1.6
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

I realize that the runserver command is not designed to function over HTTPS, but it would be much more useful for users who don't realize that (like the 1-hour-ago version of me) if the exception that Django throws from HTTPS access attempts was not an apparently random UnicodeDecodeError from the logging system.

Right now, with Django 1.6.5, attempting to access any URL on a runserver instance over HTTPS will result in this traceback being shown multiple times in the server console:

Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/SocketServer.py", line 560, in process_request_thread
    self.finish_request(request, client_address)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/SocketServer.py", line 322, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/srv/ads/django/tmtpds/ve/lib/python2.6/site-packages/django/core/servers/basehttp.py", line 126, in __init__
    super(WSGIRequestHandler, self).__init__(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/SocketServer.py", line 617, in __init__
    self.handle()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/wsgiref/simple_server.py", line 131, in handle
    if not self.parse_request(): # An error code has been sent, just exit
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/BaseHTTPServer.py", line 289, in parse_request
    self.send_error(400, "Bad request syntax (%r)" % requestline)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/BaseHTTPServer.py", line 357, in send_error
    self.send_response(code, message)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/BaseHTTPServer.py", line 374, in send_response
    self.log_request(code)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/BaseHTTPServer.py", line 411, in log_request
    self.requestline, str(code), str(size))
  File "/srv/ads/django/tmtpds/ve/lib/python2.6/site-packages/django/core/servers/basehttp.py", line 138, in log_message
    msg = "[%s] %s\n" % (self.log_date_time_string(), format % args)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xcd in position 12: ordinal not in range(128)

It's not always exactly the same byte having problems, but it's always line 138 in django/core/servers/basehttp.py. The server is attempting to log an "HTTP 400: Bad request syntax" error, but it's failing to decode the URL from what it seems to think is unicode to ascii. From my googling, it appears that this is happening because the browser encrypts the URL, and runserver is getting that encrypted URL and having no idea what to do with it.

It would be really helpful for uniformed users like my past self if this error were reported as "You can't use HTTPS with runserver" rather than what we're currently getting.

Change History (13)

comment:1 Changed 7 years ago by Aymeric Augustin

Triage Stage: UnreviewedAccepted
Type: BugNew feature

Yes, I recently saw that nginx does something smart like this, it's a nice touch.

comment:2 Changed 7 years ago by Aymeric Augustin

Has patch: set
Needs tests: set

In fact there are two fairly independant parts to this ticket.

  1. A bug: UnicodeDecodeError is raised. This is most likely a regression introduced when we ported Django to Python 3.
  1. A feature request: providing a helpful message when the dev server receives a HTTPS request.

Here's the fix for 1 and a quick proposal for 2.

diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
index 010b5e0..c522d1b 100644
--- a/django/core/servers/basehttp.py
+++ b/django/core/servers/basehttp.py
@@ -135,7 +136,7 @@ class WSGIRequestHandler(simple_server.WSGIRequestHandler, object):
                 or self.path == '/favicon.ico'):
             return
 
-        msg = "[%s] %s\n" % (self.log_date_time_string(), format % args)
+        msg = str("[%s] %s\n") % (self.log_date_time_string(), format % args)
 
         # Utilize terminal colors, if available
         if args[1][0] == '2':
@@ -150,6 +151,10 @@ class WSGIRequestHandler(simple_server.WSGIRequestHandler, object):
         elif args[1] == '404':
             msg = self.style.HTTP_NOT_FOUND(msg)
         elif args[1][0] == '4':
+            # 0x16 = Handshake, 0x03 = SSL 3.0 or TLS 1.x
+            if args[0].startswith(str('\x16\x03')):
+                msg = ("You're accessing the developement server over HTTPS, "
+                       "but it only supports HTTP.\n")
             msg = self.style.HTTP_BAD_REQUEST(msg)
         else:
             # Any 5XX, or any other response

comment:3 Changed 7 years ago by Flavio Curella

should we split this ticket into two? (unicode and https?)

comment:4 Changed 7 years ago by Flavio Curella

Has patch: unset
Owner: changed from nobody to Flavio Curella
Status: newassigned

comment:5 Changed 7 years ago by Flavio Curella

not sure how or even where to look for existing tests that could be extended. Any pointer is appreciated

comment:6 Changed 7 years ago by Flavio Curella

Needs tests: unset

unchecked 'needs tests' as this might be too hard to test for, or not worth it

comment:7 Changed 7 years ago by Collin Anderson

Has patch: set
Needs tests: set

comment:8 Changed 7 years ago by Collin Anderson

Needs tests: unset

sorry i merge-confliced your change :)

comment:9 Changed 7 years ago by Collin Anderson

depends on #23429.

comment:10 Changed 7 years ago by Tim Graham

Patch needs improvement: set

Test fails on Python 3.

comment:11 Changed 7 years ago by Flavio Curella

test fixed

comment:12 Changed 7 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

In c53f2451a83fc081c1886d07c390cf0447b1143f:

Fixed #23398 -- Added helpful error message when runserver is accessed via HTTPS

comment:13 Changed 7 years ago by Aymeric Augustin

Thanks for completing the patch!

Note: See TracTickets for help on using tickets.
Back to Top