Showing with 85 additions and 2 deletions.
  1. +74 −2 src/twisted/web/http.py
  2. +11 −0 src/twisted/web/test/test_http.py
76 changes: 74 additions & 2 deletions src/twisted/web/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def _parseHeader(line):
return (key, pdict)


from zope.interface import implementer, provider
from zope.interface import Attribute, Interface, implementer, provider

# twisted imports
from twisted.python.compat import (
Expand All @@ -112,6 +112,7 @@ def _parseHeader(line):
H2Connection = None
H2_ENABLED = False


from twisted.web._responses import (
SWITCHING,

Expand All @@ -133,6 +134,7 @@ def _parseHeader(line):

RESPONSES)


if _PY3:
_intTypes = int
else:
Expand Down Expand Up @@ -377,6 +379,75 @@ def parseContentRange(header):



class _IDeprecatedHTTPChannelToRequestInterface(Interface):
"""
The interface L{HTTPChannel} expects of L{Request}.
"""

requestHeaders = Attribute(
"A L{http_headers.Headers} instance giving all received HTTP request "
"headers.")

responseHeaders = Attribute(
"A L{http_headers.Headers} instance holding all HTTP response "
"headers to be sent.")


def connectionLost(reason):
"""
The underlying connection has been lost.
@param reason: A failure instance indicating the reason why
the connection was lost.
@type reason: L{twisted.python.failure.Failure}
"""


def gotLength(length):
"""
Called when L{HTTPChannel} has determined the length, if any,
of the incoming request's body.
@param length: The length of the request's body.
@type length: L{int} if the request declares its body's length
and L{None} if it does not.
"""


def handleContentChunk(data):
"""
Deliver a received chunk of body data to the request. Note
this does not imply chunked transfer encoding.
@param data: The received chunk.
@type data: L{bytes}
"""


def parseCookies():
"""
Parse the request's cookies out of received headers.
"""


def requestReceived(command, path, version):
"""
Called when the entire request, including its body, has been
received.
@param command: The request's HTTP command.
@type command: L{bytes}
@param path: The request's path. Note: this is actually what
RFC7320 calls the URI.
@type path: L{bytes}
@param version: The request's HTTP version.
@type version: L{bytes}
"""



class StringTransport:
"""
I am a StringIO wrapper that conforms for the transport API. I support
Expand Down Expand Up @@ -549,7 +620,8 @@ def rawDataReceived(self, data):
_QUEUED_SENTINEL = object()


@implementer(interfaces.IConsumer)
@implementer(interfaces.IConsumer,
_IDeprecatedHTTPChannelToRequestInterface)
class Request:
"""
A HTTP request.
Expand Down
11 changes: 11 additions & 0 deletions src/twisted/web/test/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from urllib.parse import urlparse, urlunsplit, clear_cache

from zope.interface import provider
from zope.interface.verify import verifyObject

from twisted.python.compat import (_PY3, iterbytes, networkString, unicode,
intToBytes, NativeStringIO)
Expand Down Expand Up @@ -2719,6 +2720,16 @@ def test_finishCleansConnection(self):
self.assertEqual(trans.producerState, 'producing')


def test_provides_IDeprecatedHTTPChannelToRequestInterface(self):
"""
L{http.Request} provides
L{http._IDeprecatedHTTPChannelToRequestInterface}, which
defines the interface used by L{http.HTTPChannel}.
"""
req = http.Request(DummyChannel(), False)
verifyObject(http._IDeprecatedHTTPChannelToRequestInterface, req)



class MultilineHeadersTests(unittest.TestCase):
"""
Expand Down