class documentation

class twisted.web.http.HTTPChannel(basic.LineReceiver, policies.TimeoutMixin): (source)

Known subclasses: twisted.web.proxy.Proxy, twisted.web.proxy.ReverseProxy

Implements interfaces: twisted.internet.interfaces.IConsumer, twisted.internet.interfaces.IPushProducer, twisted.internet.interfaces.ITransport

View In Hierarchy

A receiver for HTTP requests.

The HTTPChannel provides interfaces.ITransport and interfaces.IConsumer to the Request objects it creates. It also implements interfaces.IPushProducer to self.transport, allowing the transport to pause it.

Instance Variable MAX_LENGTH Maximum length for initial request line and each line from the header.
Instance Variable maxHeaders Maximum number of headers allowed per request.
Instance Variable totalHeadersSize Maximum bytes for request line plus all headers from the request.
Instance Variable abortTimeout The number of seconds to wait after we attempt to shut the transport down cleanly to give up and forcibly terminate it. This is only used when we time a connection out, to prevent errors causing the FD to get leaked. If this is None, we will wait forever.
Instance Variable length Undocumented
Instance Variable persistent Undocumented
Method __init__ Undocumented
Instance Variable requests Undocumented
Method connectionMade Called when a connection is made.
Method lineReceived Called for each line from request until the end of headers when it enters binary mode.
Method headerReceived Do pre-processing (for content-length) and store this header away. Enforce the per-request header limit.
Method allContentReceived Undocumented
Method dataReceived Data was received from the network. Process it.
Method rawDataReceived Override this for when raw data is received.
Method allHeadersReceived Undocumented
Method checkPersistence Check if the channel should close or not.
Method requestDone Called by first request in queue when it is done.
Method timeoutConnection Called when the connection times out.
Method forceAbortClient No summary
Method connectionLost Called when the connection is shut down.
Method isSecure Return True if this channel is using a secure transport.
Method writeHeaders Called by Request objects to write a complete set of HTTP headers to a transport.
Method write Called by Request objects to write response data.
Method writeSequence Write a list of strings to the HTTP response.
Method getPeer Get the remote address of this connection.
Method getHost Get the local address of this connection.
Method loseConnection 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.
Method registerProducer Register to receive data from a producer.
Method unregisterProducer Stop consuming data from a producer, without disconnecting.
Method stopProducing Stop producing data.
Method pauseProducing Pause producing data.
Method resumeProducing Resume producing data.
Instance Variable _transferDecoder None or a decoder instance if the request body uses the chunked Transfer-Encoding.
Instance Variable _receivedHeaderSize Bytes received so far for the header.
Instance Variable _handlingRequest Whether a request is currently being processed.
Instance Variable _dataBuffer Any data that has been received from the connection while processing an outstanding request.
Instance Variable _networkProducer Either the transport, if it provides interfaces.IPushProducer, or a null implementation of interfaces.IPushProducer. Used to attempt to prevent the transport from producing excess data when we're responding to a request.
Instance Variable _requestProducer If the Request object or anything it calls registers itself as an interfaces.IProducer, it will be stored here. This is used to create a producing pipeline: pause/resume producing methods will be propagated from the transport, through the HTTPChannel instance, to the c{_requestProducer}.

The reason we proxy through the producing methods rather than the old behaviour (where we literally just set the Request object as the producer on the transport) is because we want to be able to exert backpressure on the client to prevent it from sending in arbitrarily many requests without ever reading responses. Essentially, if the client never reads our responses we will eventually stop reading its requests.

Instance Variable _requestProducerStreaming A boolean that tracks whether the producer on the Request side of this channel has registered itself as a interfaces.IPushProducer or an interfaces.IPullProducer.
Instance Variable _waitingForTransport A boolean that tracks whether the transport has asked us to stop producing. This is used to keep track of what we're waiting for: if the transport has asked us to stop producing then we don't want to unpause the transport until it asks us to produce again.
Instance Variable _abortingCall The twisted.internet.base.DelayedCall that will be used to forcibly close the transport if it doesn't close cleanly.
Instance Variable _optimisticEagerReadSize When a resource takes a long time to answer a request (via twisted.web.server.NOT_DONE_YET, hopefully one day by a Deferred), we would like to be able to let that resource know about the underlying transport disappearing as promptly as possible, via Request.notifyFinish, and therefore via self.requests[...].connectionLost() on this HTTPChannel.

However, in order to simplify application logic, we implement head-of-line blocking, and do not relay pipelined requests to the application until the previous request has been answered. This means that said application cannot dispose of any entity-body that comes in from those subsequent requests, which may be arbitrarily large, and it may need to be buffered in memory.

To implement this tradeoff between prompt notification when possible (in the most frequent case of non-pipelined requests) and correct behavior when not (say, if a client sends a very long-running GET request followed by a PUT request with a very large body) we will continue reading pipelined requests into self._dataBuffer up to a given limit.

_optimisticEagerReadSize is the number of bytes we will accept from the client and buffer before pausing the transport.

This behavior has been in place since Twisted 17.9.0 .

Instance Variable __header Undocumented
Instance Variable __first_line Undocumented
Class Variable __content Undocumented
Instance Variable _savedTimeOut Undocumented
Instance Variable _receivedHeaderCount Undocumented
Class Variable _log Undocumented
Instance Variable _command Undocumented
Instance Variable _path Undocumented
Instance Variable _version Undocumented
Method _finishRequestBody Undocumented
Method _maybeChooseTransferDecoder If the provided header is content-length or transfer-encoding, choose the appropriate decoder if any.
Method _send100Continue Sends a 100 Continue response, used to signal to clients that further processing will be performed.
Method _respondToBadRequestAndDisconnect This is a quick and dirty way of responding to bad requests.

Inherited from LineReceiver:

Class Variable delimiter The line-ending delimiter to use. By default this is b'\r\n'.
Instance Variable line_mode Undocumented
Method clearLineBuffer Clear buffered data.
Method setLineMode Sets the line-mode of this receiver.
Method setRawMode Sets the raw mode of this receiver. Further data received will be sent to rawDataReceived rather than lineReceived.
Method sendLine Sends a line to the other end of the connection.
Method lineLengthExceeded Called when the maximum line length has been reached. Override if it needs to be dealt with in some special way.
Instance Variable _buffer Undocumented
Instance Variable _busyReceiving Undocumented

Inherited from Protocol (via LineReceiver):

Class Variable factory Undocumented
Method logPrefix Return a prefix matching the class name, to identify log messages related to this protocol instance.

Inherited from BaseProtocol (via LineReceiver, Protocol):

Instance Variable connected Undocumented
Instance Variable transport Undocumented
Method makeConnection Make a connection to a transport and a server.

Inherited from _PauseableMixin (via LineReceiver):

Instance Variable paused Undocumented

Inherited from TimeoutMixin:

Instance Variable timeOut The number of seconds after which to timeout the connection.
Method callLater Wrapper around reactor.callLater for test purpose.
Method resetTimeout Reset the timeout count down.
Method setTimeout Change the timeout period
Instance Variable __timeoutCall Undocumented
Method __timedOut Undocumented
MAX_LENGTH = (source)
Maximum length for initial request line and each line from the header.
_transferDecoder = (source)
None or a decoder instance if the request body uses the chunked Transfer-Encoding.
(type: _ChunkedTransferDecoder)
maxHeaders = (source)
Maximum number of headers allowed per request.
(type: int)
totalHeadersSize = (source)
Maximum bytes for request line plus all headers from the request.
(type: int)
_receivedHeaderSize = (source)
Bytes received so far for the header.
(type: int)
_handlingRequest = (source)
Whether a request is currently being processed.
(type: bool)
_dataBuffer = (source)
Any data that has been received from the connection while processing an outstanding request.
(type: list of bytes)
_networkProducer = (source)
Either the transport, if it provides interfaces.IPushProducer, or a null implementation of interfaces.IPushProducer. Used to attempt to prevent the transport from producing excess data when we're responding to a request.
(type: interfaces.IPushProducer)
_requestProducer = (source)
If the Request object or anything it calls registers itself as an interfaces.IProducer, it will be stored here. This is used to create a producing pipeline: pause/resume producing methods will be propagated from the transport, through the HTTPChannel instance, to the c{_requestProducer}.

The reason we proxy through the producing methods rather than the old behaviour (where we literally just set the Request object as the producer on the transport) is because we want to be able to exert backpressure on the client to prevent it from sending in arbitrarily many requests without ever reading responses. Essentially, if the client never reads our responses we will eventually stop reading its requests.

(type: interfaces.IPushProducer)
_requestProducerStreaming = (source)
A boolean that tracks whether the producer on the Request side of this channel has registered itself as a interfaces.IPushProducer or an interfaces.IPullProducer.
(type: bool or None)
_waitingForTransport = (source)
A boolean that tracks whether the transport has asked us to stop producing. This is used to keep track of what we're waiting for: if the transport has asked us to stop producing then we don't want to unpause the transport until it asks us to produce again.
(type: bool)
abortTimeout = (source)
The number of seconds to wait after we attempt to shut the transport down cleanly to give up and forcibly terminate it. This is only used when we time a connection out, to prevent errors causing the FD to get leaked. If this is None, we will wait forever.
(type: int)
_abortingCall = (source)
The twisted.internet.base.DelayedCall that will be used to forcibly close the transport if it doesn't close cleanly.
(type: twisted.internet.base.DelayedCall)
_optimisticEagerReadSize = (source)
When a resource takes a long time to answer a request (via twisted.web.server.NOT_DONE_YET, hopefully one day by a Deferred), we would like to be able to let that resource know about the underlying transport disappearing as promptly as possible, via Request.notifyFinish, and therefore via self.requests[...].connectionLost() on this HTTPChannel.

However, in order to simplify application logic, we implement head-of-line blocking, and do not relay pipelined requests to the application until the previous request has been answered. This means that said application cannot dispose of any entity-body that comes in from those subsequent requests, which may be arbitrarily large, and it may need to be buffered in memory.

To implement this tradeoff between prompt notification when possible (in the most frequent case of non-pipelined requests) and correct behavior when not (say, if a client sends a very long-running GET request followed by a PUT request with a very large body) we will continue reading pipelined requests into self._dataBuffer up to a given limit.

_optimisticEagerReadSize is the number of bytes we will accept from the client and buffer before pausing the transport.

This behavior has been in place since Twisted 17.9.0 .

(type: int)
length = (source)

Undocumented

(type: int)
persistent = (source)

Undocumented

__header = (source)

Undocumented

__first_line = (source)

Undocumented

(type: int)
__content = (source)

Undocumented

_savedTimeOut = (source)

Undocumented

_receivedHeaderCount = (source)

Undocumented

(type: int)
_log = (source)

Undocumented

def __init__(self): (source)

Undocumented

requests = (source)

Undocumented

(type: list)
def connectionMade(self): (source)

Called when a connection is made.

This may be considered the initializer of the protocol, because it is called when the connection is completed. For clients, this is called once the connection to the server has been established; for servers, this is called after an accept() call stops blocking and a socket has been received. If you need to send any greeting or initial message, do it here.

def lineReceived(self, line): (source)

Called for each line from request until the end of headers when it enters binary mode.

_command = (source)

Undocumented

_path = (source)

Undocumented

_version = (source)

Undocumented

def _finishRequestBody(self, data): (source)

Undocumented

def _maybeChooseTransferDecoder(self, header, data): (source)

If the provided header is content-length or transfer-encoding, choose the appropriate decoder if any.

Returns True if the request can proceed and False if not.

def headerReceived(self, line): (source)

Do pre-processing (for content-length) and store this header away. Enforce the per-request header limit.

ParameterslineA line from the header section of a request, excluding the line delimiter. (type: bytes)
ReturnsA flag indicating whether the header was valid. (type: bool)
def allContentReceived(self): (source)

Undocumented

def dataReceived(self, data): (source)

Data was received from the network. Process it.

def rawDataReceived(self, data): (source)

Override this for when raw data is received.

def allHeadersReceived(self): (source)

Undocumented

def checkPersistence(self, request, version): (source)

Check if the channel should close or not.

ParametersrequestThe request most recently received over this channel against which checks will be made to determine if this connection can remain open after a matching response is returned.
versionThe version of the request. (type: bytes)
ReturnsA flag which, if True, indicates that this connection may remain open to receive another request; if False, the connection must be closed in order to indicate the completion of the response to request. (type: bool)
def requestDone(self, request): (source)

Called by first request in queue when it is done.

def timeoutConnection(self): (source)

Called when the connection times out.

Override to define behavior other than dropping the connection.

def forceAbortClient(self): (source)

Called if abortTimeout seconds have passed since the timeout fired, and the connection still hasn't gone away. This can really only happen on extremely bad connections or when clients are maliciously attempting to keep connections open.

def connectionLost(self, reason): (source)

Called when the connection is shut down.

Clear any circular references here, and any external references to this Protocol. The connection has been closed.

ParametersreasonUndocumented (type: twisted.python.failure.Failure)
def isSecure(self): (source)

Return True if this channel is using a secure transport.

Normally this method returns True if this instance is using a transport that implements interfaces.ISSLTransport.

ReturnsTrue if this request is secure (type: bool)
def writeHeaders(self, version, code, reason, headers): (source)

Called by Request objects to write a complete set of HTTP headers to a transport.

ParametersversionThe HTTP version in use. (type: bytes)
codeThe HTTP status code to write. (type: bytes)
reasonThe HTTP reason phrase to write. (type: bytes)
headersThe headers to write to the transport. (type: twisted.web.http_headers.Headers)
def write(self, data): (source)

Called by Request objects to write response data.

ParametersdataThe data chunk to write to the stream. (type: bytes)
ReturnsNone
def writeSequence(self, iovec): (source)

Write a list of strings to the HTTP response.

ParametersiovecA list of byte strings to write to the stream. (type: list of bytes)
ReturnsNone
def getPeer(self): (source)

Get the remote address of this connection.

ReturnsAn IAddress provider.
def getHost(self): (source)

Get the local address of this connection.

ReturnsAn IAddress provider.
def loseConnection(self): (source)

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.

ReturnsNone
def registerProducer(self, producer, streaming): (source)

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 IPullProducer providers, resumeProducing will be called once each time data is required.

For IPushProducer providers, pauseProducing will be called whenever the write buffer fills up and resumeProducing will only be called when it empties.

ParametersproducerThe IProducer that will be producing data. (type: IProducer provider)
streamingTrue if producer provides IPushProducer, False if producer provides IPullProducer. (type: bool)
ReturnsNone
RaisesRuntimeErrorIf a producer is already registered.
def unregisterProducer(self): (source)

Stop consuming data from a producer, without disconnecting.

ReturnsNone
def stopProducing(self): (source)

Stop producing data.

The HTTPChannel doesn't *actually* implement this, beacuse the assumption is that it will only be called just before loseConnection is called. There's nothing sensible we can do other than call loseConnection anyway.

def pauseProducing(self): (source)

Pause producing data.

This will be called by the transport when the send buffers have been filled up. We want to simultaneously pause the producing Request object and also pause our transport.

The logic behind pausing the transport is specifically to avoid issues like https://twistedmatrix.com/trac/ticket/8868. In this case, our inability to send does not prevent us handling more requests, which means we increasingly queue up more responses in our send buffer without end. The easiest way to handle this is to ensure that if we are unable to send our responses, we will not read further data from the connection until the client pulls some data out. This is a bit of a blunt instrument, but it's ok.

Note that this potentially interacts with timeout handling in a positive way. Once the transport is paused the client may run into a timeout which will cause us to tear the connection down. That's a good thing!

def resumeProducing(self): (source)

Resume producing data.

This will be called by the transport when the send buffer has dropped enough to actually send more data. When this happens we can unpause any outstanding Request producers we have, and also unpause our transport.

def _send100Continue(self): (source)

Sends a 100 Continue response, used to signal to clients that further processing will be performed.

def _respondToBadRequestAndDisconnect(self): (source)

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.

API Documentation for Twisted, generated by pydoctor 20.12.1 at 2021-02-28 19:53:36.