Skip to main content

llhttp in python

Project description

pyllhttp

Python wrapper for llhttp

A simple Python wrapper around llhttp, the HTTP parser for Node.js.

Install

llhttp via PyPI, or pip install llhttp

Usage

import llhttp
from pprint import pprint

pprint({"version": llhttp.version})

class request_parser(llhttp.Request):
    headers = {}

    url = b''
    current_header_field = None
    current_header_value = None

    def on_message_begin(self):
        print(f"MESSAGE BEGIN")

    def on_url(self, url):
        self.url += url
        self.pause()

    def on_url_complete(self):
        print(f"URL {self.url}")

    def on_header_field(self, field):
        assert self.current_header_value is None
        if self.current_header_field is None:
            self.current_header_field = bytearray(field)
        else:
            self.current_header_field += field

    def on_header_field_complete(self):
        self.current_header_field = self.current_header_field.decode('iso-8859-1').lower()
        assert self.current_header_field not in self.headers

    def on_header_value(self, value):
        assert self.current_header_field is not None
        if self.current_header_value is None:
            self.current_header_value = bytearray(value)
        else:
            self.current_header_value += value

    def on_header_value_complete(self):
        assert self.current_header_field is not None
        self.current_header_value = bytes(self.current_header_value)
        print(f"HEADER {self.current_header_field}: {self.current_header_value}")
        self.headers[self.current_header_field] = self.current_header_value
        self.current_header_field = None
        self.current_header_value = None

    def on_headers_complete(self):
        assert self.current_header_field is None
        assert self.current_header_value is None

    def on_message_complete(self):
        print("MESSAGE COMPLETE")

parser = request_parser()

assert parser.lenient_headers is not True
parser.lenient_headers = True
parser.reset()
assert parser.lenient_headers is True

buffer = b"GET /test HTTP/1.1\r\nlOl:wut\r\nOH: hai\r\n\r\n"
while buffer:
    consumed = parser.execute(buffer[:2])
    buffer = buffer[consumed:]
    if parser.is_paused:
        print("UNPAUSING")
        parser.unpause()

parser.finish()
pprint({
    "method": parser.method,
    "url": parser.url,
    "version": f"{parser.major}.{parser.minor}",
    "headers": parser.headers,
})
{'version': '3.0.0'}
MESSAGE BEGIN
UNPAUSING
UNPAUSING
UNPAUSING
URL b'/test'
HEADER lol: b'wut'
HEADER oh: b'hai'
MESSAGE COMPLETE
{'headers': {'lol': b'wut', 'oh': b'hai'},
 'method': 'GET',
 'url': b'/test',
 'version': '1.1'}

Extra

This project is a toy, started to reacquaint myself with Python c-api modules. If you find it useful, please let me know.

The version number tracks the version of the incorporated llhttp.

License: MIT

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

llhttp-6.0.9.0.tar.gz (42.4 kB view details)

Uploaded Source

File details

Details for the file llhttp-6.0.9.0.tar.gz.

File metadata

  • Download URL: llhttp-6.0.9.0.tar.gz
  • Upload date:
  • Size: 42.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.2

File hashes

Hashes for llhttp-6.0.9.0.tar.gz
Algorithm Hash digest
SHA256 701e93cbc53189bdf06550b82820bb87b795f4a62716d861b8418679dce9a792
MD5 a458bb8f0f30efc405b68cdeaf42f367
BLAKE2b-256 5514b15172bc24a30bf7fc068aea506277e953edc09ec6e49a2bde5abe934345

See more details on using hashes here.

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