From 0adf05246ca93431640e4789d5fb40628a86901f Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Fri, 18 Nov 2016 10:15:16 +0000 Subject: [PATCH 1/2] Add a custom override of buildProtocol. --- daphne/http_protocol.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/daphne/http_protocol.py b/daphne/http_protocol.py index a30cbed..74d4239 100755 --- a/daphne/http_protocol.py +++ b/daphne/http_protocol.py @@ -275,11 +275,6 @@ class WebRequest(http.Request): }) -class HTTPProtocol(http.HTTPChannel): - - requestFactory = WebRequest - - class HTTPFactory(http.HTTPFactory): """ Factory which takes care of tracking which protocol @@ -288,8 +283,6 @@ class HTTPFactory(http.HTTPFactory): routed appropriately. """ - protocol = HTTPProtocol - def __init__(self, channel_layer, action_logger=None, timeout=120, websocket_timeout=86400, ping_interval=20, ping_timeout=30, ws_protocols=None, root_path="", websocket_connect_timeout=30, proxy_forwarded_address_header=None, proxy_forwarded_port_header=None): http.HTTPFactory.__init__(self) self.channel_layer = channel_layer @@ -309,6 +302,15 @@ class HTTPFactory(http.HTTPFactory): self.ws_factory.reply_protocols = self.reply_protocols self.root_path = root_path + def buildProtocol(self, addr): + """ + Builds protocol instances. This override is used to ensure we use our + own Request object instead of the default. + """ + protocol = http.HTTPFactory.buildProtocol(self, addr) + protocol.requestFactory = WebRequest + return protocol + def reply_channels(self): return self.reply_protocols.keys() From 9d708cda965c1541652f05c766a304b6b447dc11 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Fri, 18 Nov 2016 10:22:03 +0000 Subject: [PATCH 2/2] Implement IProtocolNegotiationFactory. --- daphne/http_protocol.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/daphne/http_protocol.py b/daphne/http_protocol.py index 74d4239..3aac00a 100755 --- a/daphne/http_protocol.py +++ b/daphne/http_protocol.py @@ -5,7 +5,10 @@ import six import time import traceback +from zope.interface import implementer + from six.moves.urllib_parse import unquote, unquote_plus +from twisted.internet.interfaces import IProtocolNegotiationFactory from twisted.protocols.policies import ProtocolWrapper from twisted.web import http @@ -275,6 +278,7 @@ class WebRequest(http.Request): }) +@implementer(IProtocolNegotiationFactory) class HTTPFactory(http.HTTPFactory): """ Factory which takes care of tracking which protocol @@ -370,3 +374,18 @@ class HTTPFactory(http.HTTPFactory): # Ping check else: protocol.check_ping() + + # IProtocolNegotiationFactory + def acceptableProtocols(self): + """ + Protocols this server can speak after ALPN negotiation. Currently that + is HTTP/1.1 and optionally HTTP/2. Websockets cannot be negotiated + using ALPN, so that doesn't go here: anyone wanting websockets will + negotiate HTTP/1.1 and then do the upgrade dance. + """ + baseProtocols = [b'http/1.1'] + + if http.H2_ENABLED: + baseProtocols.insert(0, b'h2') + + return baseProtocols