diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index f93b3a3143..cea1dd5057 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -85,7 +85,13 @@ class WSGIRequestHandler(simple_server.WSGIRequestHandler, object): return self.client_address[0] def log_message(self, format, *args): - msg = "[%s] %s\n" % (self.log_date_time_string(), format % args) + + msg = "[%s]" % self.log_date_time_string() + try: + msg += "%s\n" % (format % args) + except UnicodeDecodeError: + # e.g. accessing the server via SSL on Python 2 + msg += "\n" # Utilize terminal colors, if available if args[1][0] == '2': @@ -100,6 +106,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 diff --git a/tests/servers/test_basehttp.py b/tests/servers/test_basehttp.py new file mode 100644 index 0000000000..8ee99d4eaa --- /dev/null +++ b/tests/servers/test_basehttp.py @@ -0,0 +1,27 @@ +import sys + +from django.core.handlers.wsgi import WSGIRequest +from django.core.servers.basehttp import WSGIRequestHandler +from django.test import TestCase +from django.test.client import RequestFactory +from django.utils.six import BytesIO, StringIO + + +class WSGIRequestHandlerTestCase(TestCase): + def test_https(self): + request = WSGIRequest(RequestFactory().get('/').environ) + request.makefile = lambda *args, **kwargs: BytesIO() + + handler = WSGIRequestHandler(request, '192.168.0.2', None) + + _stderr = sys.stderr + sys.stderr = StringIO() + try: + handler.log_message("GET %s %s", str('\x16\x03'), "4") + self.assertIn( + "You're accessing the developement server over HTTPS, " + "but it only supports HTTP.", + sys.stderr.getvalue() + ) + finally: + sys.stderr = _stderr