No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Particle Feast f0c34e0c7a
Some checks are pending
Python / lint (push) Waiting to run
Python / test (push) Waiting to run
Python / build (push) Waiting to run
update private hostname with public one
2026-10-14 14:34:03 -07:00
.forgejo/workflows ci: update image to use "python" tag 2025-09-26 12:34:51 -07:00
src/ht2p test: add tests for HTTPRoute#matches() 2025-09-20 10:02:01 -07:00
.gitignore dev[git]: add .python/ to .gitignore 2025-09-19 17:08:45 -07:00
.tool-versions dev[asdf]: add python version 2025-09-19 17:07:46 -07:00
LICENSE move from codeberg.org/canterberry to compuforge.local/particle 2026-10-13 15:21:44 -07:00
pyproject.toml release: increment project minor version 2025-09-19 17:10:49 -07:00
README.md update private hostname with public one 2026-10-14 14:34:03 -07:00

ht2p

stars open issues open pull requests ci status

ht2p is a minimal http server and routing engine for python.

Installing

pip install --index=https://canterberry.cc/python ht2p

Usage

Here's a basic example of a server using the default settings and one route.

from ht2p import HTTPRoute, HTTPServer


class HelloRoute(HTTPRoute):
    def on_request(self, request):
        request.write_json({"message": "Hello, world!"})


with HTTPServer(routes=[HelloRoute("GET", r"^/$")]) as server:
    try:
        server.serve_forever()
    except:
        pass

API Reference

All units within this package without an underscore (_) prefix are public interfaces. Some of the more useful ones are described below. If your desired behavior is not documented below, then inspect the source code for advanced usage.

HTTPServer(ip_address: str?, tcp_port: int?, log_level: str?, logger: ht2p.Logger?, routes: list[ht2p.HTTPRoute]?)

The HTTPServer constructor expects the following keyword arguments:

Name Type Description Default
ip_address string listen on this IP address "127.0.0.1"
tcp_port uint16 listen on this TCP port 8765
log_level string the minimum logging level (DEBUG, INFO, WARN, ERROR, CRITICAL) "INFO"
logger ht2p.Logger use this logger (mutually exclusive with log_level) None
routes ht2p.HTTPRoute[] match requests using these routes []

HTTPRoute(method: str, path: str)

The HTTPRoute constructor requires the following positional arguments.

Name Type Description
method string match the request method to this string
path string match the request path to this regular expression string

Further, classes extending HTTPRoute should implement the on_request() method.

#on_request(self, request: ht2p.HTTPRequest)

This method is called whenever the route matches a request. It is expected to process the request and prepare a response.

There are no concurrency guarantees for this method. Assume that multiple calls can be concurrently in progress.

HTTPRequest

#body: bytes

Returns the full raw request body.

#context: dict[str][any]

Returns a mutable dictionary for ephemeral state throughout the lifecycle of this request. Any non-serializable values stored in this context MUST be removed before processing has completed. Values remaining in this context when request processing has completed will be included in #inspect() output, and may be included in access logs.

#duration_ms: int

Returns the time elapsed since processing began for this request, rounded up to the nearest millisecond.

#end()

Flushes the response buffers, indicating no further activity for this request.

#header(name: str, default_value: str?): list[str]

List the HTTP header values for the given header name.

#inspect(): dict[str][any]

Describes this request in serializable form. Suitable for logging.

#is_terminal: bool

Returns True if the TCP connection should be closed after this request has been processed. Otherwise, returns False.

#method: str

Get the HTTP method for this request.

#path: str

Get the resource path for this request.

#protocol_name: str

Get the name of the protocol for this request. It will always be "HTTP".

#protocol_version: str

Get the protocol version of this request. One of: "1.0", "1.1", or "2"

#query: dict[str][list[str]]

Get the query parameters for this request.

#resource: str

Get the full resource URI for this request, including the query string.

#set_header(name: str, value: str)

Appends a header to the response with the given name and value. This method does not replace existing headers with the same name.

#set_status(code: int, message: str)

Sets the response status code and message to the given values.

#write(content: bytes)

Write the given content as the response body. This method does not set either the Content-Length or Content-Type response headers.

#write_json(content: any)

Stringify the given content as JSON and write it as the response body. Automatically sets Content-Length and Content-Type response headers.

License

ht2p © 2025 by Devin Canterberry is licensed under CC BY-NC-SA 4.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/4.0/

This project may not be used, in whole or in part, for AI training.