gruvi.http – HTTP Client and Server

The gruvi.http module implements a HTTP client and server.

The client and server are relatively complete implementations of the HTTP protocol. Some of the supported features are: keepalive, pipelining, chunked transfers and trailers.

Some general notes about the implementation:

  • Both HTTP/1.0 and HTTP/1.1 are supported. The client will by default make requests with HTTP/1.1. The server always responds in the same version as the request.
  • Connections are kept alive by default. This means that you need to make sure you close connections when they are no longer needed.
  • Any headers that are passed in by application code must not be “Hop by hop” headers. These headers may only be used by HTTP implementations themselves, such as the client and server in this module.

Some important points about the use of binary versus unicode types in the API:

  • Data that is passed into the API that ends up in the HTTP header, such as the HTTP version string, method, and headers, must be of the string type. This means str on Python 3, and str or unicode on Python 2. However, if the string type is unicode aware (all except str on Python 2), you must make sure that it only contains code points that are defined in ISO-8859-1, which is the default HTTP encoding specified in RFC2606.
  • In theory, HTTP headers can support unicode code points outside ISO-8859-1 if encoded according to the scheme in RFC2047. However this method is very poorly supported and rarely used, and Gruvi therefore does not offer any special support for it. If you must use this feature for some reason, you can pre-encode the headers into this encoding and pass them already encoded.
  • Data that is passed to the API and ends up in the HTTP body can be either of the binary type or of the string type (bytes, str or unicode, the latter only on Python 2). If passing a unicode aware type, then the data is encoded before adding it to the body. The encoding must be passed into the client or server by passing a “Content-Type” header with a “charset” parameter. If no encoding is provided, then ISO-8859-1 is assumed. Note that ISO-8859-1 is not able to express any code points outside latin1. This means that if you pass a body with non-latin1 code points, and you fail to set the “charset” parameter, then you will get a UnicodeEncodeError exception.
exception gruvi.http.HttpError

Exception that is raised in case of HTTP protocol errors.

class gruvi.http.HttpRequest(transport, protocol)

A HTTP request.

Instances of this class are returned by HttpProtocol.request(). This class allows you to write the request body yourself using the write() and end_request() methods. This can be useful if you need to send a large input that cannot be easily presented as as a file-like object or a generator, or if you want to use “chunked” encoding trailers.

start_request(method, url, headers=None, body=None)

Start a new HTTP request.

This method is called by HttpProtocol.request(). It creates a new HTTP request header and sends it to the transport.

The body parameter is a hint that specifies the body that will be sent in the future, but it will not actually send it. This method tries to deduce the Content-Length of the body that follows from it.

write(buf)

Write buf to the request body.

end_request(trailers=None)

End the request body.

The optional trailers argument can be used to add trailers. This requires “chunked” encoding.

class gruvi.http.HttpResponse(message)

A HTTP response.

Instances of this class are returned by HttpProtocol.getresponse(). This class allows you to get access to all information related to a HTTP response, including the HTTP headers and body.

version

The HTTP version as a (major, minor) tuple.

status

The HTTP status code, as an integer.

headers

The response headers, as a list of (name, value) pairs.

trailers

The response trailers, as a list of (name, value) pairs.

The trailers will only be available after the entire response has been read. Most servers do not generate trailers.

get_header(name, default=None)

Return the value of HTTP header name.

If the header does not exist, return default.

get_trailer(name, default=None)

Return a the value of a HTTP trailer name.

If the trailer does not exist, return default.

body

A gruvi.StreamReader instance for reading the response body.

read(size=-1)

A alias for self.body.read().

read1(size=-1)

A alias for self.body.read1().

readline(limit=-1, delim='n')

A alias for self.body.readline().

readlines(hint=-1)

A alias for self.body.readlines().

class gruvi.http.HttpProtocol(server_side, application=None, server_name=None, version='1.1', timeout=None)

Bases: gruvi.MessageProtocol

HTTP protocol implementation.

The server_side argument specifies whether this is a client or server side protocol.

If this is a server side protocol, the wsgi_application argument is mandatory and it must be a WSGI application callable.

The server_name argument can be used to override the server name for server side protocols. If not provided, then the socket name of the listening socket will be used.

server_side

Return whether the protocol is server-side.

server_name

Return the server name.

request(method, url, headers=, []body='')

Make a new HTTP request.

The method argument is the HTTP method to be used. It must be specified as a string, for example 'GET' or 'POST'. The url argument specifies the URL and must be a string as well.

The optional headers argument specifies extra HTTP headers to use in the request. It must be a list of (name, value) tuples, with name and value a string.

The optional body argument may be used to specify a body to include in the request. It must be a bytes or str instance, a file-like object, or an iterable producing bytes or str instances. The default value for the body is the empty string b'' which sends an empty body. To send potentially very large bodies, use the file or iterator interface. Using these interfaces will send the body under the “chunked” transfer encoding. This has the added advantage that the body size does not need to be known up front.

The body may also be the None, which means that you need to send the request body yourself. This is explained below.

This method sends the request header, and if a body was specified, the request body as well. It then returns a HttpRequest instance.

If however you passsed a body of None then you must use the HttpRequest.write() and HttpRequest.end_request() methods if the HttpRequest instance to send the request body yourself. This functionality is only useful if you want to sent trailers with the HTTP “chunked” encoding. Trailers are not normally used.

The response to the request can be obtained by calling the getresponse() method.

You may make multiple requests before reading a response. This is called pipelining, and can improve per request latency greatly. For every request that you make, you must call getresponse() exactly once. The remote HTTP implementation will send by the responses in the same order as the requests.

This method is a switchpoint.

getresponse(timeout=-1)

Wait for and return a HTTP response.

The return value is a HttpResponse instance. When this method returns, only the response header has been read. The response body can be read using the HttpResponse.read() and similar methods.

Note that it is required that you read the entire body of each response if you use HTTP pipelining. Specifically, it is an error to call getresponse() when the body of the response returned by a previous invocation has not yet been fully read.

This method is a switchpoint.

class gruvi.http.HttpClient(timeout=None)

Bases: gruvi.Client

A HTTP client.

The optional timeout argument can be used to specify a timeout for the various network operations used within the client.

getresponse(timeout=-1)

An alias for self.protocol.getresponse().

request(method, url, headers=, []body='')

An alias for self.protocol.request().

class gruvi.http.HttpServer(application, server_name=None, timeout=None)

Bases: gruvi.Server

A HTTP server.

The constructor takes the following arguments. The wsgi_handler argument must be a WSGI callable. See PEP 333.

The optional server_name argument can be used to specify a server name. This might be needed by the WSGI application to construct absolute URLs. If not provided, then the host portion of the address passed to listen() will be used.

The optional timeout argument can be used to specify a timeout for the various network operations used within the server.

Previous topic

Included Protocols (specific high-level API)

Next topic

gruvi.jsonrpc – JSON-RPC Client and Server