r47304 - Revert r47104: "Merge hide-request-transport-8191-5: Hide the transport backing the HTTPChannel object from twisted.web Resource objects."
hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Sat, 23 Apr 2016 01:51:48 -0600 (MDT)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: hawkowl
Date: Sat Apr 23 01:51:33 2016
New Revision: 47304
Removed:
trunk/twisted/web/topfiles/8191.misc
Modified:
trunk/twisted/web/http.py
trunk/twisted/web/server.py
trunk/twisted/web/test/requesthelper.py
trunk/twisted/web/test/test_http.py
trunk/twisted/web/test/test_proxy.py
trunk/twisted/web/test/test_web.py
trunk/twisted/web/wsgi.py
Log:
Revert r47104: "Merge hide-request-transport-8191-5: Hide the transport backing the HTTPChannel object from twisted.web Resource objects."
Reopens: #8191
Modified: trunk/twisted/web/http.py
==============================================================================
--- trunk/twisted/web/http.py (original)
+++ trunk/twisted/web/http.py Sat Apr 23 01:51:33 2016
@@ -91,7 +91,6 @@
# twisted imports
from twisted.python.compat import (
_PY3, unicode, intToBytes, networkString, nativeString)
-from twisted.python.constants import NamedConstant, Names
from twisted.python.deprecate import deprecated
from twisted.python import log
from twisted.python.versions import Version
@@ -569,16 +568,6 @@
which this request was received is closed and which is C{True} after
that.
@type _disconnected: C{bool}
-
- @ivar _queuedHeaders: A L{tuple} of items that would normally be passed to
- L{HTTPChannel.writeHeaders}. Used when the response is queued to store
- the eventual headers.
- @type _queuedHeaders: A L{tuple} of HTTP version (:{bytes}), status code
- (L{int}), reason phrase (L{bytes}), and headers (L{list} of L{tuple}s
- of C{(bytes, bytes)}.
-
- @ivar _send100: Whether to send a 100-Continue response when unqueued.
- @type _send100: L{bool}
"""
producer = None
finished = 0
@@ -597,8 +586,6 @@
content = None
_forceSSL = 0
_disconnected = False
- _queuedHeaders = None
- _send100 = False
def __init__(self, channel, queued):
"""
@@ -607,7 +594,7 @@
the transport?
"""
self.notifications = []
- self._channel = channel
+ self.channel = channel
self.queued = queued
self.requestHeaders = Headers()
self.received_cookies = {}
@@ -615,59 +602,9 @@
self.cookies = [] # outgoing cookies
if queued:
- self._transport = StringTransport()
+ self.transport = StringTransport()
else:
- self._transport = self._channel
-
-
- def __getattr__(self, attr):
- # This is implemented to deprecate some properties of this object.
- if attr == 'transport':
- warnings.warn(
- "twisted.web.http.Request.transport was deprecated in Twisted "
- "16.2.0. Call directly into the Request object instead.",
- category=DeprecationWarning,
- stacklevel=2
- )
- attr = '_transport'
- elif attr == 'channel':
- warnings.warn(
- "twisted.web.http.Request.channel was deprecated in Twisted "
- "16.2.0. Call directly into the Request object instead.",
- category=DeprecationWarning,
- stacklevel=2
- )
- attr = '_channel'
-
- try:
- return self.__dict__[attr]
- except KeyError:
- raise AttributeError(
- "'%s' object has no attribute '%s'" %
- (self.__class__.__name__, attr)
- )
-
-
- def __setattr__(self, attr, value):
- # This is implemented to deprecate some properties of this object.
- if attr == 'transport':
- warnings.warn(
- "twisted.web.http.Request.transport was deprecated in Twisted "
- "16.2.0. Call directly into the Request object instead.",
- category=DeprecationWarning,
- stacklevel=2
- )
- attr = '_transport'
- elif attr == 'channel':
- warnings.warn(
- "twisted.web.http.Request.channel was deprecated in Twisted "
- "16.2.0. Call directly into the Request object instead.",
- category=DeprecationWarning,
- stacklevel=2
- )
- attr = '_channel'
-
- self.__dict__[attr] = value
+ self.transport = self.channel.transport
def _cleanup(self):
@@ -677,8 +614,8 @@
if self.producer:
log.err(RuntimeError("Producer was not unregistered for %s" % self.uri))
self.unregisterProducer()
- self._channel.requestDone(self)
- del self._channel
+ self.channel.requestDone(self)
+ del self.channel
try:
self.content.close()
except OSError:
@@ -705,19 +642,14 @@
self.queued = 0
# set transport to real one and send any buffer data
- data = self._transport.getvalue()
- self._transport = self._channel
- if self._send100:
- self.channel._send100Continue()
- if self._queuedHeaders:
- self._transport.writeHeaders(*self._queuedHeaders)
- self._queuedHeaders = None
+ data = self.transport.getvalue()
+ self.transport = self.channel.transport
if data:
- self._transport.write(data)
+ self.transport.write(data)
# if we have producer, register it with transport
if (self.producer is not None) and not self.finished:
- self._transport.registerProducer(self.producer, self.streamingProducer)
+ self.transport.registerProducer(self.producer, self.streamingProducer)
# if we're finished, clean up
if self.finished:
@@ -801,8 +733,8 @@
# cache the client and server information, we'll need this later to be
# serialized and sent with the request so CGIs will work remotely
- self.client = self._channel.getPeer()
- self.host = self._channel.getHost()
+ self.client = self.channel.transport.getPeer()
+ self.host = self.channel.transport.getHost()
# Argument processing
args = self.args
@@ -829,7 +761,7 @@
self.args.update(cgiArgs)
except:
# It was a bad request.
- self._channel._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.channel.transport)
return
self.content.seek(0, 0)
@@ -879,14 +811,14 @@
if streaming:
producer.pauseProducing()
else:
- self._channel.registerProducer(producer, streaming)
+ self.transport.registerProducer(producer, streaming)
def unregisterProducer(self):
"""
Unregister the producer.
"""
if not self.queued:
- self._channel.unregisterProducer()
+ self.transport.unregisterProducer()
self.producer = None
@@ -948,11 +880,11 @@
if self.chunked:
# write last chunk and closing CRLF
- self._transport.write(b"0\r\n\r\n")
+ self.transport.write(b"0\r\n\r\n")
# log request
- if hasattr(self._channel, "factory"):
- self._channel.factory.log(self)
+ if hasattr(self.channel, "factory"):
+ self.channel.factory.log(self)
self.finished = 1
if not self.queued:
@@ -973,10 +905,11 @@
if not self.startedWriting:
self.startedWriting = 1
version = self.clientproto
- code = intToBytes(self.code)
- reason = self.code_message
-
- headers = []
+ l = []
+ l.append(
+ version + b" " +
+ intToBytes(self.code) + b" " +
+ self.code_message + b"\r\n")
# if we don't have a content length, we send data in
# chunked mode, so that we can support pipelining in
@@ -984,7 +917,7 @@
if ((version == b"HTTP/1.1") and
(self.responseHeaders.getRawHeaders(b'content-length') is None) and
self.method != b"HEAD" and self.code not in NO_BODY_CODES):
- headers.append((b'Transfer-Encoding', b'chunked'))
+ l.append(b'Transfer-Encoding: chunked\r\n')
self.chunked = 1
if self.lastModified is not None:
@@ -1008,15 +941,14 @@
category=DeprecationWarning, stacklevel=2)
# Backward compatible cast for non-bytes values
value = networkString('%s' % (value,))
- headers.append((name, value))
+ l.extend([name, b": ", value, b"\r\n"])
for cookie in self.cookies:
- headers.append((b'Set-Cookie', cookie))
+ l.append(b'Set-Cookie: ' + cookie + b'\r\n')
- if self.queued:
- self._queuedHeaders = (version, code, reason, headers)
- else:
- self._channel.writeHeaders(version, code, reason, headers)
+ l.append(b"\r\n")
+
+ self.transport.writeSequence(l)
# if this is a "HEAD" request, we shouldn't return any data
if self.method == b"HEAD":
@@ -1031,9 +963,9 @@
self.sentLength = self.sentLength + len(data)
if data:
if self.chunked:
- self._transport.writeSequence(toChunk(data))
+ self.transport.writeSequence(toChunk(data))
else:
- self._transport.write(data)
+ self.transport.write(data)
def addCookie(self, k, v, expires=None, domain=None, path=None,
max_age=None, comment=None, secure=None, httpOnly=False):
@@ -1332,9 +1264,7 @@
"""
if self._forceSSL:
return True
- transport = getattr(
- getattr(self, '_channel', None), 'transport', None
- )
+ transport = getattr(getattr(self, 'channel', None), 'transport', None)
if interfaces.ISSLTransport(transport, None) is not None:
return True
return False
@@ -1409,31 +1339,13 @@
Clean up anything which can't be useful anymore.
"""
self._disconnected = True
- self._channel = None
+ self.channel = None
if self.content is not None:
self.content.close()
for d in self.notifications:
d.errback(reason)
self.notifications = []
-
- def loseConnection(self):
- """
- Pass the loseConnection through to the underlying channel.
- """
- self._channel.loseConnection()
-
-
- def _send100Continue(self):
- """
- Sends a "100 Continue" status code, where 100 Continue is supported.
- """
- if not self.queued:
- self._channel._send100Continue()
- else:
- self._send100 = True
-
-
Request.getClient = deprecated(
Version("Twisted", 15, 0, 0),
"Twisted Names to resolve hostnames")(Request.getClient)
@@ -1673,25 +1585,6 @@
-class _ChannelSendState(Names):
- """
- Defines a collection of states that indicate what portion of a HTTP
- response has already been sent on L{HTTPChannel}. Used to enforce that
- callers of methods on the L{HTTPChannel} are calling them at the
- appropriate times and to prevent callers from sending invalid HTTP
- responses.
-
- The state of the channel send state goes from C{IDLE} (the previous
- response is complete), optionally to C{SENT_100_CONTINUE}, and then to
- C{SENT_HEADERS} When the response is complete, the state is reset to
- C{IDLE}.
- """
- IDLE = NamedConstant()
- SENT_100_CONTINUE = NamedConstant()
- SENT_HEADERS = NamedConstant()
-
-
-
class HTTPChannel(basic.LineReceiver, policies.TimeoutMixin):
"""
A receiver for HTTP requests.
@@ -1734,7 +1627,6 @@
# the request queue
self.requests = []
self._transferDecoder = None
- self._sendState = _ChannelSendState.IDLE
def connectionMade(self):
@@ -1750,7 +1642,7 @@
self._receivedHeaderSize += len(line)
if (self._receivedHeaderSize > self.totalHeadersSize):
- self._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.transport)
return
if self.__first_line:
@@ -1774,13 +1666,13 @@
parts = line.split()
if len(parts) != 3:
- self._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.transport)
return
command, request, version = parts
try:
command.decode("ascii")
except UnicodeDecodeError:
- self._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.transport)
return
self._command = command
@@ -1825,7 +1717,7 @@
try:
header, data = line.split(b':', 1)
except ValueError:
- self._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.transport)
return
header = header.lower()
@@ -1834,7 +1726,7 @@
try:
self.length = int(data)
except ValueError:
- self._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.transport)
self.length = None
return
self._transferDecoder = _IdentityTransferDecoder(
@@ -1854,7 +1746,7 @@
self._receivedHeaderCount += 1
if self._receivedHeaderCount > self.maxHeaders:
- self._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.transport)
return
@@ -1885,7 +1777,7 @@
try:
self._transferDecoder.dataReceived(data)
except _MalformedChunkedDataError:
- self._respondToBadRequestAndDisconnect()
+ _respondToBadRequestAndDisconnect(self.transport)
def allHeadersReceived(self):
@@ -1898,7 +1790,7 @@
expectContinue = req.requestHeaders.getRawHeaders(b'expect')
if (expectContinue and expectContinue[0].lower() == b'100-continue' and
self._version == b'HTTP/1.1'):
- req._send100Continue()
+ req.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n")
def checkPersistence(self, request, version):
@@ -1953,8 +1845,6 @@
del self.requests[0]
if self.persistent:
- self._sendState = _ChannelSendState.IDLE
-
# notify next request it can start writing
if self.requests:
self.requests[0].noLongerQueued()
@@ -1974,157 +1864,20 @@
request.connectionLost(reason)
- def writeHeaders(self, version, code, reason, headers):
- """
- Called by L{Request} objects to write a complete set of HTTP headers to
- a transport.
-
- @param version: The HTTP version in use.
- @type version: L{bytes}
-
- @param code: The HTTP status code to write.
- @type code: L{bytes}
-
- @param reason: The HTTP reason phrase to write.
- @type reason: L{bytes}
-
- @param headers: The headers to write to the transport.
- @type headers: L{twisted.web.http_headers.Headers}
- """
- assert self._sendState in (
- _ChannelSendState.IDLE, _ChannelSendState.SENT_100_CONTINUE
- )
- responseLine = version + b" " + code + b" " + reason + b"\r\n"
- headerSequence = [responseLine]
- headerSequence.extend(
- name + b': ' + value + b"\r\n" for name, value in headers
- )
- headerSequence.append(b"\r\n")
- self.transport.writeSequence(headerSequence)
- self._sendState = _ChannelSendState.SENT_HEADERS
-
-
- def registerProducer(self, producer, streaming):
- """
- Register to receive data from a producer.
-
- This sets self to be a consumer for a producer. When this object runs
- out of data (as when a send(2) call on a socket succeeds in moving the
- last data from a userspace buffer into a kernelspace buffer), it will
- ask the producer to resumeProducing().
-
- For L{IPullProducer} providers, C{resumeProducing} will be called once
- each time data is required.
-
- For L{IPushProducer} providers, C{pauseProducing} will be called
- whenever the write buffer fills up and C{resumeProducing} will only be
- called when it empties.
-
- @type producer: L{IProducer} provider
- @param producer: The L{IProducer} that will be producing data.
-
- @type streaming: L{bool}
- @param streaming: C{True} if C{producer} provides L{IPushProducer},
- C{False} if C{producer} provides L{IPullProducer}.
-
- @raise RuntimeError: If a producer is already registered.
-
- @return: C{None}
- """
- return self.transport.registerProducer(producer, streaming)
-
-
- def unregisterProducer(self):
- """
- Stop consuming data from a producer, without disconnecting.
-
- @return: C{None}
- """
- return self.transport.unregisterProducer()
-
-
- def write(self, data):
- """
- Called by L{Request} objects to write response data.
-
- @param data: The data chunk to write to the stream.
- @type data: L{bytes}
-
- @return: C{None}
- """
- assert self._sendState == _ChannelSendState.SENT_HEADERS
- self.transport.write(data)
-
-
- def writeSequence(self, iovec):
- """
- Write a list of strings to the HTTP response.
-
- @param iovec: A list of byte strings to write to the stream.
- @type data: L{list} of L{bytes}
-
- @return: C{None}
- """
- assert self._sendState == _ChannelSendState.SENT_HEADERS
- self.transport.writeSequence(iovec)
-
-
- def getPeer(self):
- """
- Get the remote address of this connection.
-
- @return: An L{IAddress} provider.
- """
- return self.transport.getPeer()
-
-
- def getHost(self):
- """
- Get the local address of this connection.
-
- @return: An L{IAddress} provider.
- """
- return self.transport.getHost()
-
-
- def loseConnection(self):
- """
- Closes the connection. Will write any data that is pending to be sent
- on the network, but if this response has not yet been written to the
- network will not write anything.
-
- @return: C{None}
- """
- # TODO: Does this need to be smarter, particularly about queued
- # responses?
- return self.transport.loseConnection()
-
-
- def _send100Continue(self):
- """
- Sends a 100 Continue response, used to signal to clients that further
- processing will be performed.
- """
- assert self._sendState == _ChannelSendState.IDLE
- self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n")
- self._sendState = _ChannelSendState.SENT_100_CONTINUE
+def _respondToBadRequestAndDisconnect(transport):
+ """
+ This is a quick and dirty way of responding to bad requests.
- def _respondToBadRequestAndDisconnect(self):
- """
- This is a quick and dirty way of responding to bad requests.
+ As described by HTTP standard we should be patient and accept the
+ whole request from the client before sending a polite bad request
+ response, even in the case when clients send tons of data.
- As described by HTTP standard we should be patient and accept the
- whole request from the client before sending a polite bad request
- response, even in the case when clients send tons of data.
- """
- # FIXME: There is nothing in this method to ensure that the response it
- # sends is not intermingled with some other response body being written
- # at the same time. Clearly this isn't the end of the world: the method
- # has been arund a little while. Still, this should probably be
- # refactored.
- self.transport.write(b"HTTP/1.1 400 Bad Request\r\n\r\n")
- self.transport.loseConnection()
+ @param transport: Transport handling connection to the client.
+ @type transport: L{interfaces.ITransport}
+ """
+ transport.write(b"HTTP/1.1 400 Bad Request\r\n\r\n")
+ transport.loseConnection()
Modified: trunk/twisted/web/server.py
==============================================================================
--- trunk/twisted/web/server.py (original)
+++ trunk/twisted/web/server.py Sat Apr 23 01:51:33 2016
@@ -110,10 +110,10 @@
def getStateToCopyFor(self, issuer):
x = self.__dict__.copy()
- del x['_transport']
+ del x['transport']
# XXX refactor this attribute out; it's from protocol
# del x['server']
- del x['_channel']
+ del x['channel']
del x['content']
del x['site']
self.content.seek(0, 0)
@@ -164,7 +164,7 @@
"""
# get site from channel
- self.site = self._channel.site
+ self.site = self.channel.site
# set various default headers
self.setHeader(b'server', version)
Modified: trunk/twisted/web/test/requesthelper.py
==============================================================================
--- trunk/twisted/web/test/requesthelper.py (original)
+++ trunk/twisted/web/test/requesthelper.py Sat Apr 23 01:51:33 2016
@@ -53,9 +53,6 @@
def registerProducer(self, producer, streaming):
self.producers.append((producer, streaming))
- def unregisterProducer(self):
- pass
-
def loseConnection(self):
self.disconnected = True
@@ -74,56 +71,6 @@
pass
- def writeHeaders(self, version, code, reason, headers):
- response_line = version + b" " + code + b" " + reason + b"\r\n"
- headerSequence = [response_line]
- headerSequence.extend(
- name + b': ' + value + b"\r\n" for name, value in headers
- )
- headerSequence.append(b"\r\n")
- self.transport.writeSequence(headerSequence)
-
-
- def getPeer(self):
- return self.transport.getPeer()
-
-
- def getHost(self):
- return self.transport.getHost()
-
-
- def registerProducer(self, producer, streaming):
- self.transport.registerProducer(producer, streaming)
-
-
- def unregisterProducer(self):
- self.transport.unregisterProducer()
-
-
- def write(self, data):
- self.transport.write(data)
-
-
- def writeSequence(self, iovec):
- self.transport.writeSequence(iovec)
-
-
- def loseConnection(self):
- self.transport.loseConnection()
-
-
- def endRequest(self):
- pass
-
-
- @property
- def producers(self):
- return self.transport.producers
-
- def _send100Continue(self):
- self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n")
-
-
class DummyRequest(object):
"""
Modified: trunk/twisted/web/test/test_http.py
==============================================================================
--- trunk/twisted/web/test/test_http.py (original)
+++ trunk/twisted/web/test/test_http.py Sat Apr 23 01:51:33 2016
@@ -338,105 +338,6 @@
-class ResponseWriteOrderingTests(unittest.TestCase):
- requests = (
- b"GET / HTTP/1.1\r\n"
- b"Accept: text/html\r\n"
- b"\r\n"
- b"GET / HTTP/1.1\r\n"
- b"\r\n")
-
-
- def setUp(self):
- self.transport = StringTransport()
- self.channel = http.HTTPChannel()
- self.channel.requestFactory = http.Request
- self.channel.makeConnection(self.transport)
- self.channel.dataReceived(self.requests)
-
-
- def test_cannotWriteBeforeHeaders(self):
- """
- The L{HTTPChannel} forbids writes before headers are sent.
- """
- self.assertRaises(
- AssertionError,
- self.channel.write,
- b"some response data",
- )
-
-
- def test_cannot100ContinueAfterHeaders(self):
- """
- The L{HTTPChannel} forbids sending 100 Continue after headers were
- sent.
- """
- self.channel.writeHeaders(b"HTTP/1.1", b"200", b"OK", [])
- self.assertRaises(
- AssertionError,
- self.channel._send100Continue,
- )
-
-
- def test_cannotSendHeadersTwice(self):
- """
- The L{HTTPChannel} forbids sending a header block twice.
- """
- self.channel.writeHeaders(b"HTTP/1.1", b"200", b"OK", [])
- self.assertRaises(
- AssertionError,
- self.channel.writeHeaders,
- b"HTTP/1.1",
- b"200",
- b"OK",
- [],
- )
-
-
- def test_completingRequestAllows100ContinueAfterHeaders(self):
- """
- The L{HTTPChannel} allows a 100 Continue once a request is complete.
- """
- self.channel.writeHeaders(b"HTTP/1.1", b"200", b"OK", [])
- self.channel.requestDone(self.channel.requests[0])
- self.channel._send100Continue()
-
- self.assertEqual(
- self.transport.value(),
- b"HTTP/1.1 200 OK\r\n\r\nHTTP/1.1 100 Continue\r\n\r\n",
- )
-
-
- def test_completingRequestAllowsNewHeaders(self):
- """
- The L{HTTPChannel} allows sending a new header block after headers are
- complete.
- """
- self.channel.writeHeaders(b"HTTP/1.1", b"200", b"OK", [])
- self.channel.requestDone(self.channel.requests[0])
- self.channel.writeHeaders(b"HTTP/1.1", b"204", b"No Content", [])
-
- self.assertEqual(
- self.transport.value(),
- b"HTTP/1.1 200 OK\r\n\r\nHTTP/1.1 204 No Content\r\n\r\n",
- )
-
-
- def test_canWriteAfterHeaders(self):
- """
- The L{HTTPChannel} allows writing data after headers.
- """
- headers = [(b'Content-Length', b'5')]
- self.channel.writeHeaders(b"HTTP/1.1", b"200", b"OK", headers)
- self.channel.write(b'hello')
-
- self.assertEqual(
- self.transport.value(),
- b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello",
- )
-
-
-
class HTTPLoopbackTests(unittest.TestCase):
expectedHeaders = {b'request': b'/foo/bar',
@@ -1361,7 +1262,7 @@
content.append(self.content.read())
method.append(self.method)
path.append(self.path)
- decoder.append(self._channel._transferDecoder)
+ decoder.append(self.channel._transferDecoder)
testcase.didRequest = True
self.finish()
@@ -1841,12 +1742,10 @@
For an HTTP 1.0 request, L{http.Request.write} sends an HTTP 1.0
Response-Line and whatever response headers are set.
"""
- channel = DummyChannel()
+ req = http.Request(DummyChannel(), False)
trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
- req._transport = trans
+ req.transport = trans
req.setResponseCode(200)
req.clientproto = b"HTTP/1.0"
@@ -1865,12 +1764,10 @@
L{http.Request.write} casts non-bytes header value to bytes
transparently.
"""
- channel = DummyChannel()
+ req = http.Request(DummyChannel(), False)
trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
- req._transport = trans
+ req.transport = trans
req.setResponseCode(200)
req.clientproto = b"HTTP/1.0"
@@ -1899,12 +1796,10 @@
Response-Line, whatever response headers are set, and uses chunked
encoding for the response body.
"""
- channel = DummyChannel()
+ req = http.Request(DummyChannel(), False)
trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
- req._transport = trans
+ req.transport = trans
req.setResponseCode(200)
req.clientproto = b"HTTP/1.1"
@@ -1926,12 +1821,10 @@
L{http.Request.write} sends an HTTP Response-Line, whatever response
headers are set, and a last-modified header with that time.
"""
- channel = DummyChannel()
+ req = http.Request(DummyChannel(), False)
trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
- req._transport = trans
+ req.transport = trans
req.setResponseCode(200)
req.clientproto = b"HTTP/1.0"
@@ -2086,7 +1979,7 @@
# Then something goes wrong and content should get closed.
req.connectionLost(Failure(ConnectionLost("Finished")))
self.assertTrue(content.closed)
- self.assertIdentical(req._channel, None)
+ self.assertIdentical(req.channel, None)
def test_registerProducerTwiceFails(self):
@@ -2139,7 +2032,7 @@
# This is a roundabout assertion: http.StringTransport doesn't
# implement registerProducer, so Request.registerProducer can't have
# tried to call registerProducer on the transport.
- self.assertIsInstance(req._transport, http.StringTransport)
+ self.assertIsInstance(req.transport, http.StringTransport)
def test_registerProducerWhenQueuedDoesntRegisterPullProducer(self):
@@ -2158,7 +2051,7 @@
# This is a roundabout assertion: http.StringTransport doesn't
# implement registerProducer, so Request.registerProducer can't have
# tried to call registerProducer on the transport.
- self.assertIsInstance(req._transport, http.StringTransport)
+ self.assertIsInstance(req.transport, http.StringTransport)
def test_registerProducerWhenNotQueuedRegistersPushProducer(self):
@@ -2170,7 +2063,7 @@
req = http.Request(DummyChannel(), False)
producer = DummyProducer()
req.registerProducer(producer, True)
- self.assertEqual([(producer, True)], req._transport.producers)
+ self.assertEqual([(producer, True)], req.transport.producers)
def test_registerProducerWhenNotQueuedRegistersPullProducer(self):
@@ -2182,7 +2075,7 @@
req = http.Request(DummyChannel(), False)
producer = DummyProducer()
req.registerProducer(producer, False)
- self.assertEqual([(producer, False)], req._transport.producers)
+ self.assertEqual([(producer, False)], req.transport.producers)
def test_connectionLostNotification(self):
@@ -2194,7 +2087,7 @@
request = http.Request(d, True)
finished = request.notifyFinish()
request.connectionLost(Failure(ConnectionLost("Connection done")))
- self.assertIdentical(request._channel, None)
+ self.assertIdentical(request.channel, None)
return self.assertFailure(finished, ConnectionLost)
@@ -2290,10 +2183,10 @@
producer from the request and the request's transport.
"""
req = http.Request(DummyChannel(), False)
- req._transport = StringTransport()
+ req.transport = StringTransport()
req.registerProducer(DummyProducer(), False)
req.unregisterProducer()
- self.assertEqual((None, None), (req.producer, req._transport.producer))
+ self.assertEqual((None, None), (req.producer, req.transport.producer))
def test_unregisterNonQueuedStreamingProducer(self):
@@ -2302,10 +2195,10 @@
producer from the request and the request's transport.
"""
req = http.Request(DummyChannel(), False)
- req._transport = StringTransport()
+ req.transport = StringTransport()
req.registerProducer(DummyProducer(), True)
req.unregisterProducer()
- self.assertEqual((None, None), (req.producer, req._transport.producer))
+ self.assertEqual((None, None), (req.producer, req.transport.producer))
def test_unregisterQueuedNonStreamingProducer(self):
@@ -2370,141 +2263,6 @@
factory.logFile.getvalue())
- def test_transportDeprecated(self):
- """
- L{http.Request.transport} will raise a L{DeprecationWarning} if
- accessed.
- """
- channel = DummyChannel()
- trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
-
- # This should fire a warning.
- req.transport
-
- warnings = self.flushWarnings([self.test_transportDeprecated])
- self.assertEqual(1, len(warnings))
- self.assertEqual(warnings[0]['category'], DeprecationWarning)
- self.assertEqual(
- warnings[0]['message'],
- "twisted.web.http.Request.transport was deprecated in "
- "Twisted 16.2.0. Call directly into the Request object instead."
- )
-
-
- def test_transportSetDeprecated(self):
- """
- L{http.Request.transport} will raise a L{DeprecationWarning} if set.
- """
- channel = DummyChannel()
- trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
-
- # This should fire a warning.
- req.transport = object()
-
- warnings = self.flushWarnings([self.test_transportSetDeprecated])
- self.assertEqual(1, len(warnings))
- self.assertEqual(warnings[0]['category'], DeprecationWarning)
- self.assertEqual(
- warnings[0]['message'],
- "twisted.web.http.Request.transport was deprecated in "
- "Twisted 16.2.0. Call directly into the Request object instead."
- )
-
-
- def test_channelDeprecated(self):
- """
- L{http.Request.channel} will raise a L{DeprecationWarning} if
- accessed.
- """
- channel = DummyChannel()
- trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
-
- # This should fire a warning.
- req.channel
-
- warnings = self.flushWarnings([self.test_channelDeprecated])
- self.assertEqual(1, len(warnings))
- self.assertEqual(warnings[0]['category'], DeprecationWarning)
- self.assertEqual(
- warnings[0]['message'],
- "twisted.web.http.Request.channel was deprecated in Twisted "
- "16.2.0. Call directly into the Request object instead."
- )
-
-
- def test_channelSetDeprecated(self):
- """
- L{http.Request.channel} will raise a L{DeprecationWarning} if set.
- """
- channel = DummyChannel()
- trans = StringTransport()
- channel.transport = trans
- req = http.Request(channel, False)
-
- # This should fire a warning.
- req.channel = object()
-
- warnings = self.flushWarnings([self.test_channelSetDeprecated])
- self.assertEqual(1, len(warnings))
- self.assertEqual(warnings[0]['category'], DeprecationWarning)
- self.assertEqual(
- warnings[0]['message'],
- "twisted.web.http.Request.channel was deprecated in Twisted "
- "16.2.0. Call directly into the Request object instead."
- )
-
-
- def test_sendHeadersWhenUnqueued(self):
- """
- Unqueueing a L{Request} sends headers properly.
- """
- transport = StringTransport()
- channel = DummyChannel()
- channel.transport = transport
- request = http.Request(channel, True)
- request.gotLength(123)
- request.requestReceived(b"GET", b"/", b"HTTP/1.1")
- request.write(b'test data')
-
- self.assertEqual(transport.value(), b'')
-
- request.noLongerQueued()
-
- self.assertEqual(
- transport.value(),
- b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n9\r\n"
- b"test data\r\n"
- )
-
-
- def test_send100ContinueWhenUnqueued(self):
- """
- Unqueueing a L{Request} sends any 100-Continue repsonse properly.
- """
- transport = StringTransport()
- channel = DummyChannel()
- channel.transport = transport
- request = http.Request(channel, True)
- request.gotLength(123)
- request.requestReceived(b"GET", b"/", b"HTTP/1.1")
- request._send100Continue()
-
- self.assertEqual(transport.value(), b'')
-
- request.noLongerQueued()
-
- self.assertEqual(
- transport.value(),
- b"HTTP/1.1 100 Continue\r\n\r\n"
- )
-
-
class MultilineHeadersTests(unittest.TestCase):
"""
Modified: trunk/twisted/web/test/test_proxy.py
==============================================================================
--- trunk/twisted/web/test/test_proxy.py (original)
+++ trunk/twisted/web/test/test_proxy.py Sat Apr 23 01:51:33 2016
@@ -123,14 +123,6 @@
self.lostReason = reason
- def getPeer(self):
- return self.transport.getPeer()
-
-
- def getHost(self):
- return self.transport.getHost()
-
-
class ProxyClientTests(TestCase):
"""
Modified: trunk/twisted/web/test/test_web.py
==============================================================================
--- trunk/twisted/web/test/test_web.py (original)
+++ trunk/twisted/web/test/test_web.py Sat Apr 23 01:51:33 2016
@@ -554,8 +554,8 @@
fail = failure.Failure(Exception("Oh no!"))
request.processingFailed(fail)
- self.assertNotIn(b"Oh no!", request._transport.getvalue())
- self.assertIn(b"Processing Failed", request._transport.getvalue())
+ self.assertNotIn(b"Oh no!", request.transport.getvalue())
+ self.assertIn(b"Processing Failed", request.transport.getvalue())
# Since we didn't "handle" the exception, flush it to prevent a test
# failure
@@ -574,7 +574,7 @@
fail = failure.Failure(Exception("Oh no!"))
request.processingFailed(fail)
- self.assertIn(b"Oh no!", request._transport.getvalue())
+ self.assertIn(b"Oh no!", request.transport.getvalue())
# Since we didn't "handle" the exception, flush it to prevent a test
# failure
@@ -594,7 +594,7 @@
fail = failure.Failure(Exception(u"\u2603"))
request.processingFailed(fail)
- self.assertIn(b"☃", request._transport.getvalue())
+ self.assertIn(b"☃", request.transport.getvalue())
# Since we didn't "handle" the exception, flush it to prevent a test
# failure
@@ -823,11 +823,11 @@
def testGoodMethods(self):
req = self._getReq()
req.requestReceived(b'GET', b'/newrender', b'HTTP/1.0')
- self.assertEqual(req._transport.getvalue().splitlines()[-1], b'hi hi')
+ self.assertEqual(req.transport.getvalue().splitlines()[-1], b'hi hi')
req = self._getReq()
req.requestReceived(b'HEH', b'/newrender', b'HTTP/1.0')
- self.assertEqual(req._transport.getvalue().splitlines()[-1], b'ho ho')
+ self.assertEqual(req.transport.getvalue().splitlines()[-1], b'ho ho')
def testBadMethods(self):
req = self._getReq()
@@ -855,7 +855,7 @@
req = self._getReq()
req.requestReceived(b'HEAD', b'/newrender', b'HTTP/1.0')
self.assertEqual(req.code, 200)
- self.assertEqual(-1, req._transport.getvalue().find(b'hi hi'))
+ self.assertEqual(-1, req.transport.getvalue().find(b'hi hi'))
def test_unsupportedHead(self):
@@ -866,7 +866,7 @@
resource = HeadlessResource()
req = self._getReq(resource)
req.requestReceived(b"HEAD", b"/newrender", b"HTTP/1.0")
- body = req._transport.getvalue()
+ headers, body = req.transport.getvalue().split(b'\r\n\r\n')
self.assertEqual(req.code, 200)
self.assertEqual(body, b'')
@@ -887,7 +887,7 @@
request.requestReceived(b"GET", b"/newrender", b"HTTP/1.0")
- body = request._transport.getvalue()
+ headers, body = request.transport.getvalue().split(b'\r\n\r\n')
self.assertEqual(request.code, 500)
expected = [
'',
@@ -988,7 +988,7 @@
req.requestReceived(b'POST', b'/gettableresource?'
b'value=<script>bad', b'HTTP/1.0')
self.assertEqual(req.code, 405)
- renderedPage = req._transport.getvalue()
+ renderedPage = req.transport.getvalue()
self.assertNotIn(b"<script>bad", renderedPage)
self.assertIn(b'<script>bad', renderedPage)
@@ -1003,7 +1003,7 @@
req = self._getReq()
req.requestReceived(b'<style>bad', b'/gettableresource', b'HTTP/1.0')
self.assertEqual(req.code, 501)
- renderedPage = req._transport.getvalue()
+ renderedPage = req.transport.getvalue()
self.assertNotIn(b"<style>bad", renderedPage)
self.assertIn(b'<style>bad', renderedPage)
Modified: trunk/twisted/web/wsgi.py
==============================================================================
--- trunk/twisted/web/wsgi.py (original)
+++ trunk/twisted/web/wsgi.py Sat Apr 23 01:51:33 2016
@@ -506,7 +506,7 @@
def wsgiError(started, type, value, traceback):
err(Failure(value, type, traceback), "WSGI application error")
if started:
- self.request.loseConnection()
+ self.request.transport.loseConnection()
else:
self.request.setResponseCode(INTERNAL_SERVER_ERROR)
self.request.finish()