Skip to main content

Parse, modify, and compile HTTP/1.1 messages.

Project description

🏃‍♂️ httpq

A module to parse, modify, and compile HTTP/1.1 messages with a simple built-in state machine.

Installing

pip install httpq

Documentation

Documentation can be found here.

Using

httpq has three methods to initialize a httpq.Request and httpq.Response object.

__init__

Easily initialize an HTTP message.

import httpq

req = httpq.Request(
    method="GET",
    target="/get",
    protocol="HTTP/1.1",
    headers={"Host": "httpbin.org", "Content-Length": 12},
    body="Hello world!",
)

resp = httpq.Response(
    protocol="HTTP/1.1",
    status=200,
    reason="OK",
    headers={"Content-Length": 12},
    body="Hello world!",
)

parse

Parses an entire raw HTTP message.

req = httpq.Request.parse(
    "GET /get HTTP/1.1\r\n"
    "Host: httpbin.org\r\n"
    "Content-Length: 12\r\n"
    "\r\n"
    "Hello world!"
)

resp = httpq.Response.parse(
    "HTTP/1.1 200 OK\r\n"
    "Content-Length: 12\r\n"
    "\r\n"
    "Hello world!"
)

feed

Parse chunks of a raw HTTP message.

req = httpq.Request()
req.feed("GET /get HTTP/1.1\r\n")
req.feed("Host: httpbin.org\r\n")
req.feed("Content-Length: 18\r\n")
req.feed("\r\n")
req.feed("Hello world!")

resp = httpq.Response()
resp.feed("HTTP/1.1 200 OK\r\n")
resp.feed("Content-Length: 12\r\n")
resp.feed("\r\n")
resp.feed("Hello world!")

The feed mechanism, different from the other two methods of initializing a message, is intended to be used with the built-in state machine.

When parsing a message from a stream the state machine keeps track of where in the message the parser is. This allows more advance parsing and mechanism to be built.

import socket
import httpq

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("httpbin.org", 80))

req = httpq.Request(
    method="GET",
    target="/get",
    protocol="HTTP/1.1",
    headers={"Host": "httpbin.org"},
)
s.sendall(req.raw)

resp = httpq.Response()
while resp.step_state() != httpq.state.BODY:
    resp.feed(s.recv(10))

while len(resp.body) != resp.headers["Content-Length"]:
    body += s.recv(10)

Note that the feed mechanism is used in conjunction with the step_state method. This allows the state machine to be stepped through and the parser to be advanced. We can use this parse until the body of the message, and then use the captured headers to parse the body.

Modifying and Comparisons

httpq also comes, out-of-the-box, with an intuitive method to modify and compare message values without caring about type:

import httpq

req = httpq.Request(
    method="GET",
    target="/get",
    protocol="HTTP/1.1",
    headers={"Host": "httpbin.org", "Content-Length": 12},
    body="Hello world!",
)

resp = httpq.Response(
    protocol="HTTP/1.1",
    status=404,
    reason="Not Found",
    headers={"Content-Length": 12},
    body="Hello world!",
)

# string, bytes, and int are all valid values for any field.
req.method = "POST"
req.target = b"/"

resp.status = 200
resp.reason = "OK"
resp.headers += {"Accept": "*/*"}

Internally every value of a request or response is saved as an Item, a special object type that allows easy setting and comparisons on the fly.

resp.status == 200      # >>> True
resp.status == "200"    # >>> True
resp.status == b"200"   # >>> True

Once the object is modified to the user's preference utilizing the Request and Response object is as easy as calling a property (specifically .raw):

print(req.raw)
print(resp.raw)
b'POST / HTTP/1.1\r\nHost: httpbin.org\r\nContent-Length: 12\r\n\r\nHello world!'
b'HTTP/1.1 200 OK\r\nContent-Length: 12\r\nAccept: */*\r\n\r\nHello world!'

Uniquely, the __str__ method returns the objects with arrows to make obvious of its type:

print(req)
print(resp)
→ POST / HTTP/1.1
→ Host: httpbin.org
→ Content-Length: 12
→ 
→ Hello world!

← HTTP/1.1 200 OK
← Content-Length: 12
← Accept: */*
← 
← Hello world!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

httpq-1.0.0.tar.gz (11.4 kB view hashes)

Uploaded Source

Built Distribution

httpq-1.0.0-py3-none-any.whl (5.5 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page