r46996 - apply patch from lukasa, refs #8193
hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Tue, 15 Mar 2016 06:47:59 -0600 (MDT)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: hawkowl
Date: Tue Mar 15 06:47:54 2016
New Revision: 46996
Added:
branches/httpchannel-proxy-8193-2/twisted/topfiles/8193.misc
Modified:
branches/httpchannel-proxy-8193-2/twisted/web/http.py
branches/httpchannel-proxy-8193-2/twisted/web/test/test_web.py
Log:
apply patch from lukasa, refs #8193
Modified: branches/httpchannel-proxy-8193-2/twisted/web/http.py
==============================================================================
--- branches/httpchannel-proxy-8193-2/twisted/web/http.py (original)
+++ branches/httpchannel-proxy-8193-2/twisted/web/http.py Tue Mar 15 06:47:54 2016
@@ -97,11 +97,14 @@
from twisted.python.components import proxyForInterface
from twisted.internet import interfaces, reactor, protocol, address
from twisted.internet.defer import Deferred
+from twisted.internet.interfaces import IProtocol
from twisted.protocols import policies, basic
from twisted.web.iweb import IRequest, IAccessLogFormatter
from twisted.web.http_headers import Headers
+H2_ENABLED = False
+
from twisted.web._responses import (
SWITCHING,
@@ -1978,6 +1981,88 @@
+class _GenericHTTPChannelProtocol(proxyForInterface(IProtocol, "_channel")):
+ """
+ A proxy object that wraps one of the HTTP protocol objects, and switches
+ between them depending on TLS negotiated protocol.
+
+ @ivar _negotiatedProtocol: The protocol negotiated with ALPN or NPN, if
+ any.
+ @type _negotiatedProtocol: Either a bytestring containing the ALPN token
+ for the negotiated protocol, or C{None} if no protocol has yet been
+ negotiated.
+
+ @ivar _channel: The object capable of behaving like a L{HTTPChannel} that
+ is backing this object. By default this is a L{HTTPChannel}, but if a
+ HTTP protocol upgrade takes place this may be a different channel
+ object. Must implement L{IProtocol}.
+ @type _channel: L{HTTPChannel}
+
+ @ivar _requestFactory: A callable to use to build L{IRequest} objects.
+ @type _requestFactory: L{IRequest}
+
+ @ivar _site: A reference to the creating L{twisted.web.server.Site} object.
+ @type _site: L{twisted.web.server.Site}
+ """
+ _negotiatedProtocol = None
+ _requestFactory = Request
+ _site = None
+
+
+ @property
+ def requestFactory(self):
+ return self._channel.requestFactory
+
+
+ @requestFactory.setter
+ def requestFactory(self, value):
+ self._requestFactory = value
+ self._channel.requestFactory = value
+
+
+ @property
+ def site(self):
+ return self._channel.site
+
+
+ @site.setter
+ def site(self, value):
+ self._site = value
+ self._channel.site = value
+
+
+ def dataReceived(self, data):
+ """
+ A override of L{IProtocol.dataReceived} that checks what protocol we're
+ using.
+ """
+ if self._negotiatedProtocol is None:
+ try:
+ negotiatedProtocol = self.transport.negotiatedProtocol
+ except AttributeError:
+ # Plaintext HTTP, always HTTP/1.1
+ negotiatedProtocol = b'http/1.1'
+
+ if negotiatedProtocol is None:
+ negotiatedProtocol = b'http/1.1'
+
+ if negotiatedProtocol == b'h2' and H2_ENABLED:
+ raise AssertionError("HTTP/2 support is not yet merged.")
+
+ self._negotiatedProtocol = negotiatedProtocol
+
+ return self._channel.dataReceived(data)
+
+
+
+def _genericHTTPChannelProtocolFactory(self):
+ """
+ Returns an appropriately initialized _GenericHTTPChannelProtocol.
+ """
+ return _GenericHTTPChannelProtocol(HTTPChannel())
+
+
+
class HTTPFactory(protocol.ServerFactory):
"""
Factory for HTTP server.
@@ -2001,7 +2086,7 @@
timestamps.
"""
- protocol = HTTPChannel
+ protocol = _genericHTTPChannelProtocolFactory
logPath = None
Modified: branches/httpchannel-proxy-8193-2/twisted/web/test/test_web.py
==============================================================================
--- branches/httpchannel-proxy-8193-2/twisted/web/test/test_web.py (original)
+++ branches/httpchannel-proxy-8193-2/twisted/web/test/test_web.py Tue Mar 15 06:47:54 2016
@@ -320,7 +320,7 @@
else:
validator = b"If-Not-Match: " + etag
for line in [b"GET / HTTP/1.1", validator, b""]:
- self.channel.lineReceived(line)
+ self.channel.dataReceived(line + b'\r\n')
result = self.transport.getvalue()
self.assertEqual(httpCode(result), http.OK)
self.assertEqual(httpBody(result), b"correct")
@@ -346,7 +346,7 @@
"""
for line in [b"GET / HTTP/1.1",
b"If-Modified-Since: " + http.datetimeToString(100), b""]:
- self.channel.lineReceived(line)
+ self.channel.dataReceived(line + b'\r\n')
result = self.transport.getvalue()
self.assertEqual(httpCode(result), http.NOT_MODIFIED)
self.assertEqual(httpBody(result), b"")
@@ -414,7 +414,7 @@
with an empty response body.
"""
for line in [b"GET / HTTP/1.1", b"If-None-Match: MatchingTag", b""]:
- self.channel.lineReceived(line)
+ self.channel.dataReceived(line + b'\r\n')
result = self.transport.getvalue()
self.assertEqual(httpHeader(result, b"ETag"), b"MatchingTag")
self.assertEqual(httpCode(result), http.NOT_MODIFIED)
@@ -432,7 +432,7 @@
"""
for line in [b"GET /with-content-type HTTP/1.1",
b"If-None-Match: MatchingTag", b""]:
- self.channel.lineReceived(line)
+ self.channel.dataReceived(line + b'\r\n')
result = self.transport.getvalue()
self.assertEqual(httpCode(result), http.NOT_MODIFIED)
self.assertEqual(httpBody(result), b"")
@@ -1311,7 +1311,7 @@
"""
self.site._logDateTime = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
25, 'Oct', 2004, 12, 31, 59)
- self.request.requestHeaders.addRawHeader(b'user-agent',
+ self.request.requestHeaders.addRawHeader(b'user-agent',
b'Malicious Web" Evil')
self.assertLogs(
b'"1.2.3.4" - - [25/Oct/2004:12:31:59 +0000] '