Skip to content

axon-web

Axon HTTP framework β€” Landing page + M14 framework implementation.

axon-web is the HTTP framework for the Axon ecosystem. It includes:

  • A landing page (deployed to GitLab Pages from public/)
  • A radix-tree HTTP request router (tools/router.py)
  • A composable middleware pipeline (tools/middleware.py)
  • Built-in middleware: RequestLogger, Cors, RecoverFromPanic (tools/builtin_middleware.py)
  • A static file server (tools/static_server.py)
  • A JSON codec (tools/json_codec.py)
  • A WebSocket protocol implementation (tools/websocket.py)
  • An HTTP/1.1 request parser (tools/http_parser.py)

Important: public/ is the landing page. It is not the HTTP framework.

axon-web ships a growing Python web framework in tools/. Each module has a dedicated doc in docs/:

ModuleWhat it doesDoc
router.pyRadix-tree HTTP request routerdocs/router.md
middleware.pyComposable middleware pipelinedocs/middleware.md
builtin_middleware.pyRequestLogger, Cors, RecoverFromPanicdocs/middleware.md
static_server.pyStatic file serverdocs/static-server.md
json_codec.pyJSON encode/decodedocs/json-codec.md
websocket.pyWebSocket protocol (RFC 6455)docs/websocket.md
http_parser.pyHTTP/1.1 request parser (RFC 7230)docs/http-parser.md
template_engine.pyHTML templating (Django/Jinja2-style)docs/template-engine.md
html_builder.pyTyped, XSS-safe HTML builder DSLdocs/html-builder.md
tls.pyHTTPS / TLS termination (OpenSSL FFI)docs/tls.md
serve_demo.pyDemo HTTP serverβ€”
serve_tls_demo.pyDemo HTTP+HTTPS serverdocs/tls.md
axon-web/
β”œβ”€β”€ public/ # Landing page (deployed to GitLab Pages)
β”‚ β”œβ”€β”€ index.html
β”‚ β”œβ”€β”€ style.css
β”‚ └── main.js
β”œβ”€β”€ tools/
β”‚ β”œβ”€β”€ router.py # M14: HTTP request router (radix tree)
β”‚ β”œβ”€β”€ middleware.py # M14: middleware pipeline
β”‚ β”œβ”€β”€ builtin_middleware.py # M14: built-in middleware (RequestLogger, Cors, RecoverFromPanic)
β”‚ β”œβ”€β”€ static_server.py # M14: static file server
β”‚ β”œβ”€β”€ json_codec.py # M14: JSON codec
β”‚ β”œβ”€β”€ websocket.py # M14: WebSocket protocol (RFC 6455)
β”‚ β”œβ”€β”€ http_parser.py # M14: HTTP/1.1 request parser (RFC 7230)
β”‚ β”œβ”€β”€ template_engine.py # M14: HTML templating engine
β”‚ β”œβ”€β”€ tls.py # M14: TLS/HTTPS termination (OpenSSL via stdlib ssl)
β”‚ β”œβ”€β”€ serve_demo.py # M14: demo HTTP server
β”‚ └── serve_tls_demo.py # M14: demo HTTP+HTTPS server
β”œβ”€β”€ tests/
β”‚ β”œβ”€β”€ test_router.py # Router tests (28 tests)
β”‚ β”œβ”€β”€ test_router_properties.py # Property-based router tests
β”‚ β”œβ”€β”€ test_middleware.py # Middleware tests
β”‚ β”œβ”€β”€ test_websocket.py # WebSocket tests
β”‚ └── ... # Other M14 test suites
β”œβ”€β”€ docs/
β”‚ β”œβ”€β”€ router.md # Router documentation
β”‚ β”œβ”€β”€ middleware.md # Middleware documentation
β”‚ β”œβ”€β”€ websocket.md # WebSocket documentation
β”‚ β”œβ”€β”€ http_parser.md # HTTP parser documentation
β”‚ └── ... # Other M14 docs
β”œβ”€β”€ .gitlab-ci.yml # CI: lint, tests, perf gates
└── README.md # This file
from router import Router
from middleware import Request, Response
router = Router()
@router.get("/")
def home(req):
return Response(200, {}, b"hello")
@router.get("/users/:id")
def get_user(req):
return Response(200, {}, f"user {req.path_params['id']}".encode())
resp = router.dispatch(Request("GET", "/users/42", {}, b""))
assert resp.status == 200

See docs/router.md for the full router reference.

axon-web implements an HTTP server framework in pure Axon:

  • M14 modules: HTTP router (radix tree), middleware pipeline, JSON encoder/decoder, WebSocket protocol upgrade, static file serving, HTML templating, HTTP/2 HPACK + multiplexing, zero-copy request parser, TLS/SSL via OpenSSL FFI

See the M14 Milestone Roadmap below.

The src/ directory contains the Axon framework modules. These are type-declared stubs (no runtime implementation yet) that establish the public API for the M14 framework:

src/
β”œβ”€β”€ router.axs # HTTP request router (radix tree) β€” axon-web#1
β”œβ”€β”€ middleware.axs # Composable middleware pipeline β€” axon-web#2
β”œβ”€β”€ json.axs # JSON encoder/decoder β€” axon-web#3
β”œβ”€β”€ static.axs # Static file server β€” axon-web#4
β”œβ”€β”€ websocket.axs # WebSocket protocol (RFC 6455) β€” axon-web#5
└── http_parser.axs # HTTP/1.1 request parser β€” axon-web#12

Each module provides:

  • Type declarations (enums, structs, function pointers)
  • Public API (pub functions)
  • Stub implementations that return safe defaults (no-ops, error codes)

The Python prototype of these modules lives in tools/ (e.g., tools/router.py). The Axon modules are the native implementation; the Python versions serve as the reference implementation and for property-based testing.

  • router.new() β†’ Router β€” Create an empty router
  • router.add(r, method, path, handler) β†’ i32 β€” Register a route
  • router.get/post/put/delete/patch(r, path, handler) β€” HTTP verb sugar
  • router.lookup(r, method, path, out_params) β†’ Handler β€” Find a route
  • router.set_not_found(r, handler) β€” Set the 404 handler
  • router.route_count(r) β†’ i64 β€” Number of registered routes
  • router.free(r) β€” Free all memory
  • middleware.new() β†’ Pipeline β€” Create an empty pipeline
  • middleware.use(p, mw) β€” Add a middleware
  • middleware.set_error_handler(p, h) β€” Set the error handler
  • middleware.execute(p, req) β†’ Response β€” Process a request
  • middleware.free(p) β€” Free all memory
  • json.decode(input, out_value) β†’ i32 β€” Parse JSON
  • json.decode_string/int/bool(input, out) β€” Convenience for primitives
  • json.encode(value, out_str) β†’ i32 β€” Serialize JSON
  • json.encode_string/int/bool(val, out_str) β€” Convenience for primitives
  • json.free(value) β€” Free a JsonValue tree
  • json.null/of_bool/of_int/of_float/of_string β€” Value constructors
  • static.validate_path(path) β†’ i32 β€” Path traversal check
  • static.mime_for_path(path) β†’ string β€” MIME type lookup
  • static.file_exists(path) β†’ bool β€” File existence check
  • static.file_size(path) β†’ i64 β€” File size
  • static.compute_etag(path, out) β†’ i32 β€” ETag generation
  • static.parse_range(header, out_start, out_end) β†’ i32 β€” Range request parsing
  • static.list_directory(path, out_entries, out_count) β†’ i32 β€” List dir
  • static.try_serve_index(dir, out_path) β†’ i32 β€” Find index.html
  • static.read_file(path, out_data, out_len) β†’ i32 β€” Read file
  • websocket.new() β†’ Connection β€” Create a connection (Connecting state)
  • websocket.accept_upgrade(headers, count, out) β†’ i32 β€” Validate and accept upgrade
  • websocket.parse_frame(buf, len, out) β†’ i64 β€” Parse a frame from bytes
  • websocket.serialize_frame(frame, out_buf, out_len) β†’ i32 β€” Serialize a frame
  • websocket.mask_payload(payload, len, mask_key) β€” XOR masking (involutory)
  • websocket.send_text(conn, msg) β†’ i32 β€” Send a text frame
  • websocket.send_binary(conn, data, len) β†’ i32 β€” Send a binary frame
  • websocket.send_ping(conn) β†’ i32 β€” Send a ping
  • websocket.send_pong(conn, payload, len) β†’ i32 β€” Send a pong
  • websocket.close(conn, code, reason) β†’ i32 β€” Graceful close
  • websocket.compute_accept_key(key, out) β†’ i32 β€” RFC 6455 Β§4.2.2
  • websocket.free(conn) β€” Free connection memory
  • http_parser.parse_request(buf, len, out) β†’ i32 β€” Parse HTTP request from bytes
  • http_parser.method_to_string(method) β†’ string β€” Method enum to string
  • http_parser.string_to_method(s, out) β†’ i32 β€” String to method enum
  • http_parser.parse_query_params(query, out_params, out_count) β†’ i32 β€” Parse query string
  • http_parser.get_header(req, name) β†’ string β€” Case-insensitive header lookup
  • http_parser.has_header(req, name) β†’ bool β€” Header existence check
  • http_parser.content_type(req) β†’ string β€” Get Content-Type
  • http_parser.is_keep_alive(req) β†’ bool β€” Connection persistence check
  • http_parser.free(req) β€” Free request memory
JobStageWhat it lints/testsStatus
lint:htmllintpublic/*.html via tidy⚠️ allow_failure
lint:csslintpublic/**/*.css via stylelint@15.11.0⚠️ allow_failure
lint:jslintpublic/**/*.js via eslint@8.57.0⚠️ allow_failure
pagesdeployDeploys public/ to GitLab Pagesβœ… Active
test:axon-e2etestAxon golden file tests (activates when .axs files exist)⏳ Dormant
test:axon-checktestAxon type checking (activates when .axs files exist)⏳ Dormant
perf:regression-checkperformanceBinary size and compile time gates⚠️ allow_failure

Note: The lint jobs validate the landing page in public/, not the HTTP framework. The framework doesn’t exist yet.

TicketModulePriority
#1HTTP request router (radix tree)Critical
#2Middleware pipeline architectureCritical
#3JSON encoder/decoderHigh
#4Static file serving and cachingHigh
#5WebSocket protocol upgradeHigh
#6HTML templating engineMedium
#10TLS/SSL termination (OpenSSL FFI)Medium
#11HTTP/2 HPACK + multiplexingMedium
#12Zero-copy HTTP request parser (SIMD)Medium
Terminal window
# HTML
tidy -q -e public/index.html
# CSS
npx stylelint "public/**/*.css"
# JS
npx eslint "public/**/*.js"
Terminal window
pytest tests/
Terminal window
axonc test

The tests/test_router.axs and tests/test_json.axs files are smoke tests for the framework stubs. They register routes / call encode/decode functions and verify the stubs don’t crash. As the framework is implemented, these will grow into full behavioral test suites.

See docs/CONTRIBUTING.md for contributor onboarding, and docs/architecture.md for the planned architecture.

PackageDescriptionStatus
axon-langCompiler & runtimeβœ… Active
axon-stdStandard libraryβœ… Active
axon-pkgPackage manager🚧 WIP
axon-dbDatabase driversπŸ“‹ Planned
axon-uiGUI framework (M11/M12/M19)πŸ“‹ Scaffolding
axon-webHTTP framework (M14)πŸ“‹ Scaffolding

See project license file.