Replacement for twisted.web.iweb.IRequest
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bin
src/txrequest
.gitignore
.travis.yml
AUTHORS
LICENSE
README.rst
coverage.conf
setup.cfg
setup.py
tox.ini

README.rst

txrequest

Build Status Code Coverage Requirements Status Python Version Compatibility

txrequest is a library containing an HTTP Request object API for Twisted, meant to replace the IRequest interface and implementations in twisted.web.

txrequest is not an attempt at a an async version of requests. For that, see treq.

txrequest and Klein

The intention is for this new API to work its way into Klein (and possibly twisted.web) inconjunction with a new API for route handler methods. In the interim, a txroute decorator is provided to stack under Klein.route.

In Klein today, you might something write this code:

@klein.route("/async/hello")
def hello(self, request: IRequest) -> str:
    """
    Say hello.
    """
    who = request.getHeader(b"User-Agent").decode("iso-8859-1")
    body = "Hello, {}!".format(who)

    request.setResponseCode(200)

    request.setHeader("Content-Type", "text/plain; charset=UTF-8")
    request.setHeader("ETag", "0")

    return message.encode("utf-8")

Above, the author indicates the desired response code and response headers by setting them onto the request object.

This is an odd abstraction; the request represents the request data from the client, not the response data sent to the client, and it arguably should be immutable. Worse, getHeader looks up a value in the request headers, where setHeader sets a value in the response headers.

Also, the response body is provided as it's own return value, disconnected from the response code and headers. This is problematic in cases where a response

Finally, this API requires that header data be expressed as bytes instead of text.

The new API takes an IHTTPRequest and returns a IHTTPResponse:

@klein.route("/async/hello")
@txroute
def hello(self, request: IHTTPRequest) -> IHTTPResponse:
    """
    Say hello.
    """
    who = request.headers.getValues("User-Agent")[-1:]
    message = "Hello, {}!".format(who)

    headers = MutableHTTPHeaders()
    headers.addValue("Content-Type", "text/plain; charset=UTF-8")
    headers.addValue("ETag", "0")

    return FrozenHTTPResponse(
        status=200,
        headers=headers,
        body=message.encode("utf-8"),
    )

Here a single response object, encapsulating the entire response is returned.

Request Object

For testing, creating a request object in the new API is straightforward:

request = FrozenHTTPRequest(
    method = "GET",
    uri = URL.fromText("/foo"),
    headers = FrozenHTTPHeaders(
        ("X-Foo", "Foo Value"),
        ("X-Bar", "Bar Value"),
    ),
)

Creating an IRequest is not as straightforward.