Fix python 3 support

This commit is contained in:
Andrew Godwin 2016-02-05 17:23:49 -08:00
parent 1889680fd0
commit bac3c14bfa
4 changed files with 92 additions and 8 deletions

View File

@ -70,19 +70,21 @@ class WebRequest(http.Request):
self.content.seek(0, 0) self.content.seek(0, 0)
# Calculate query string # Calculate query string
query_string = "" query_string = ""
if "?" in self.uri: if b"?" in self.uri:
query_string = self.uri.split("?", 1)[1] query_string = self.uri.split(b"?", 1)[1]
# Sanitize headers # Sanitize headers
headers = {} headers = {}
for name, value in self.requestHeaders.getAllRawHeaders(): for name, value in self.requestHeaders.getAllRawHeaders():
# Prevent CVE-2015-0219 # Prevent CVE-2015-0219
if "_" in name: if b"_" in name:
continue continue
headers[name.lower()] = value[0] headers[name.lower().decode("latin1")] = value[0]
# Send message # Send message
self.factory.channel_layer.send("http.request", { self.factory.channel_layer.send("http.request", {
"reply_channel": self.reply_channel, "reply_channel": self.reply_channel,
"method": self.method, # TODO: Correctly say if it's 1.1 or 1.0
"http_version": "1.1",
"method": self.method.decode("ascii"),
"path": self.path, "path": self.path,
"scheme": "http", "scheme": "http",
"query_string": query_string, "query_string": query_string,
@ -110,13 +112,13 @@ class WebRequest(http.Request):
raise ValueError("Got multiple Response messages!") raise ValueError("Got multiple Response messages!")
self._got_response_start = True self._got_response_start = True
# Write code # Write code
self.setResponseCode(message['status']) self.setResponseCode(message['status'], message.get("status_text", None))
# Write headers # Write headers
for header, value in message.get("headers", {}): for header, value in message.get("headers", {}):
self.setHeader(header.encode("utf8"), value.encode("utf8")) self.setHeader(header.encode("utf8"), value)
# Write out body # Write out body
if "content" in message: if "content" in message:
http.Request.write(self, message['content'].encode("utf8")) http.Request.write(self, message['content'])
# End if there's no more content # End if there's no more content
if not message.get("more_content", False): if not message.get("more_content", False):
self.finish() self.finish()

0
daphne/tests/__init__.py Normal file
View File

77
daphne/tests/test_http.py Normal file
View File

@ -0,0 +1,77 @@
from __future__ import unicode_literals
from unittest import TestCase
from asgiref.inmemory import ChannelLayer
from twisted.test import proto_helpers
from ..http_protocol import HTTPFactory
class TestHTTPProtocol(TestCase):
"""
Tests that the HTTP protocol class correctly generates and parses messages.
"""
def setUp(self):
self.channel_layer = ChannelLayer()
self.factory = HTTPFactory(self.channel_layer)
self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
self.tr = proto_helpers.StringTransport()
self.proto.makeConnection(self.tr)
def assertStartsWith(self, data, prefix):
real_prefix = data[:len(prefix)]
self.assertEqual(real_prefix, prefix)
def test_basic(self):
"""
Tests basic HTTP parsing
"""
# Send a simple request to the protocol
self.proto.dataReceived(
b"GET /test/?foo=bar HTTP/1.1\r\n" +
b"Host: somewhere.com\r\n" +
b"\r\n"
)
# Get the resulting message off of the channel layer
_, message = self.channel_layer.receive_many(["http.request"])
self.assertEqual(message['http_version'], "1.1")
self.assertEqual(message['method'], "GET")
self.assertEqual(message['scheme'], "http")
self.assertEqual(message['path'], b"/test/")
self.assertEqual(message['query_string'], b"foo=bar")
self.assertEqual(message['headers'], {"host": b"somewhere.com"})
self.assertFalse(message.get("body", None))
self.assertTrue(message['reply_channel'])
# Send back an example response
self.factory.dispatch_reply(
message['reply_channel'],
{
"status": 201,
"status_text": b"Created",
"content": b"OH HAI",
"headers": [["X-Test", b"Boom!"]],
}
)
# Make sure that comes back right on the protocol
self.assertEqual(self.tr.value(), b"HTTP/1.1 201 Created\r\nTransfer-Encoding: chunked\r\nX-Test: Boom!\r\n\r\n6\r\nOH HAI\r\n0\r\n\r\n")
def test_custom_status_text(self):
"""
Tests basic HTTP parsing
"""
# Send a simple request to the protocol
self.proto.dataReceived(
b"GET /test/?foo=bar HTTP/1.0\r\n" +
b"\r\n"
)
# Send back an example response
_, message = self.channel_layer.receive_many(["http.request"])
self.factory.dispatch_reply(
message['reply_channel'],
{
"status": 484,
"status_text": b"Daphne Is Awesome",
}
)
# Make sure that comes back right on the protocol
self.assertStartsWith(self.tr.value(), b"HTTP/1.0 484 Daphne Is Awesome\r\n")

View File

@ -20,6 +20,11 @@ setup(
zip_safe=False, zip_safe=False,
packages=find_packages(), packages=find_packages(),
include_package_data=True, include_package_data=True,
install_requires=[
'asgiref',
'twisted>=15.5',
'autobahn>=0.12',
],
entry_points={'console_scripts': [ entry_points={'console_scripts': [
'daphne = daphne.cli:CommandLineInterface.entrypoint', 'daphne = daphne.cli:CommandLineInterface.entrypoint',
]}, ]},