April 2024 - This site, and Kamaelia are being updated. There is significant work needed, and PRs are welcome.

Kamaelia.Protocol.HTTP.HTTPRequestHandler

HTTP Server

The fundamental parts of a webserver - an HTTP request parser and a request handler/response generator. One instance of this component can handle one TCP connection. Use a SimpleServer or similar component to allow several concurrent HTTP connections to the server.

Example Usage

def createhttpserver():
return HTTPServer(HTTPResourceGlue.createRequestHandler)

SimpleServer(protocol=createhttpserver, port=80).run()

This defines a function which creates a HTTPServer instance with HTTPResourceGlue.createRequestHandler as the request handler component creator function. This function is then called by SimpleServer for every new TCP connection.

How does it work?

HTTPServer creates and links to a HTTPParser and HTTPRequestHandler component. Data received over TCP is forwarded to the HTTPParser and the output of HTTPRequestHandler forwarded to the TCP component's inbox for sending.

See HTTPParser (in HTTPParser.py) and HTTPRequestHandler (below) for details of how these components work.

HTTPServer accepts a single parameter - a request handler function which is passed onto and used by HTTPRequestHandler to generate request handler components. This allows different HTTP server setups to run on different ports serving completely different content.

HTTP Request Handler

HTTPRequestHandler accepts parsed HTTP requests (from HTTPParser) and outputs appropriate responses to those requests.

How does it work?

HTTPServer creates 2 subcomponents - HTTPParser and HTTPRequestHandler which handle the processing of requests and the creation of responses respectively.

Both requests and responses are handled in a stepwise manner (as opposed to processing a whole request or response in one go) to reduce latency and cope well with bottlenecks.

One request handler (self.handler) component is used per request - the particular component instance (including parameters, component state) is picked by a function called createRequestHandler - a function specified by the user. A suitable definition of this function is available in HTTPResourceGlue.py.

Generally you will have a handler spawned for each new request, terminating after completing the sending of the response. However, it is also possible to use a 'persistent' component if you do the required jiggery-pokery to make sure that at any one time this component is not servicing more than one request simultaenously ('cause it wouldn't work).

What does it support?

Components as request handlers (hurrah!).

3 different ways in which the response data (body) can be terminated:

Chunked transfer encoding

This is the most complex of the 3 ways and was introduced in HTTP/1.1. Its performance is slightly worse that the other 2 as multiple length-lines have to be added to the data stream. It is recommended for responses whose size is not known in advance as it allows keep-alive connections (more than one HTTP request per TCP connection).

Explicit length

This is the easiest of the 3 ways but requires the length of the response to be known before it is sent. It uses a header 'Content-Length' to indicate this value. This method is prefered for any response whose length is known in advance.

Connection: close

This method closes (or half-closes) the TCP connection when the response is complete. This is highly inefficient when the client wishes to download several resources as a new TCP connection must be created and destroyed for each resource. This method is retained for HTTP/1.0 compatibility. It is however preferred for responses that do not have a true end, e.g. a continuous stream over HTTP as the alternative, chunked transfer encoding, has poorer performance.

The choice of these three methods is determined at runtime by the characteristics of the first response part produced by the request handler and the version of HTTP that the client supports (chunked requires 1.1 or higher).

What may need work?
  • HTTP standards-compliance (e.g.¬†handling of version numbers for a start)

  • Requests for byte ranges, cache control (though these may be better implemented

    in each request handler)

  • Performance tuning (also in HTTPParser)

  • Prevent many MBs of data being queued up because TCPClient finds it has a slow

    upload to the remote host


Kamaelia.Protocol.HTTP.HTTPRequestHandler.HTTPRequestHandler

class HTTPRequestHandler(Axon.Component.component)

HTTPRequestHandler() -> new HTTPRequestHandler component capable of fulfilling the requests received over a single connection after they have been parsed by HTTPParser

Inboxes

  • control : Signal component termination
  • _handlercontrol : Signals from the request handler
  • inbox : Raw HTTP requests
  • _handlerinbox : Output from the request handler

Outboxes

  • debug : Information to aid debugging
  • outbox : HTTP responses
  • signal : Signal connection to close
  • _handleroutbox : POST data etc. for the request handler
  • _handlersignal : Signals for the request handler

Methods defined here

Warning!

You should be using the inbox/outbox interface, not these methods (except construction). This documentation is designed as a roadmap as to their functionalilty for maintainers and new component developers.

__init__(self, requestHandlerFactory)

_sendChunkChunked(self, resource)

Send some more of the resource's data, for a response that uses chunked transfer-encoding

_sendChunkExplicit(self, resource)

Send some more of the resource's data, having already sent a content-length header

_sendEndChunked(self)

Called when a chunk-encoded response ends

_sendEndClose(self)

Called when a connection: close terminated response ends

_sendEndExplicit(self)

Called when a response that had a content-length header ends

checkRequestValidity(self, request)

connectResourceHandler(self)

Link to the resource handler we've created so we can receive its output

createHandler(self, request)

debug(self, msg)

determineConnectionType(self, request)

disconnectResourceHandler(self)

Disconnect the now finished resource handler

formResponseHeader(self, resource, protocolversion[, lengthMethod])

forwardBodyChunks(self)

handleRequest(self, request)

isValidRequest(self, request)

main(self)

resourceUTF8Encode(self, resource)

Encode a resource's unicode data as utf-8 octets

sendMessageChunks(self, msg)

setChunkingModeMethod(self, msg, request)

setUpRequestHandler(self, request)

shutdownRequestHandler(self, lengthMethod)

updateShouldShutdown(self)

Feedback

Got a problem with the documentation? Something unclear that could be clearer? Want to help improve it? Constructive criticism is very welcome - especially if you can suggest a better rewording!

Please leave you feedback here in reply to the documentation thread in the Kamaelia blog.

-- Automatic documentation generator, 05 Jun 2009 at 03:01:38 UTC/GMT