blazingly-http 0.1.1

Adapter-neutral HTTP layer for Blazingly: middleware hooks, request extensions, and OpenAPI serving
Documentation

blazingly-http

Adapter-neutral HTTP dispatch for the Blazingly framework: a compiled router, typed request and response values, synchronous middleware hooks, and an in-memory test client over the executable operation graph.

This crate sits between blazingly-executor, which compiles the operation graph, and the byte-level adapters (blazingly-native today). It defines Request and Response, the borrowed HttpRequestView that adapters implement over their receive buffers, the HttpMiddleware interception points, HttpApp for serving paths, and TestApp for in-memory dispatch. It is an ordinary library and is usable standalone: given an ExecutableApp, it routes and dispatches requests entirely in memory with no socket, no async runtime, and no facade — the example below is a complete program. The blazingly facade re-exports these types and adds the macro layer that derives operations from handler signatures; without it, operations are built explicitly, as shown.

[dependencies]
blazingly-core = "0.1"
blazingly-executor = "0.1"
blazingly-http = "0.1"
futures-lite = "2"
use blazingly_core::{HttpMethod, OperationDescriptor, ResponseDescriptor, TypeDescriptor};
use blazingly_executor::{ExecutableApp, ExecutableOperation, ExecutionOutcome, OperationFuture};
use blazingly_http::{Request, TestApp};

fn health() -> ExecutableOperation {
    let descriptor = OperationDescriptor::new(
        HttpMethod::Get,
        "/health",
        "app.health",
        "Reports liveness",
        None,
        vec![ResponseDescriptor::success(
            200,
            Some(TypeDescriptor::new("Health")),
        )],
    )
    .expect("operation id is valid");
    ExecutableOperation::typed(descriptor, |_input| {
        Ok(Box::pin(async {
            ExecutionOutcome::Success {
                status: 200,
                headers: Vec::new(),
                body: Some(b"\"ok\"".to_vec()),
                background: Vec::new(),
            }
        }) as OperationFuture)
    })
}

fn main() {
    let app = ExecutableApp::new([health()]).expect("operation graph compiles");
    let test = TestApp::new(&app);
    let response = futures_lite::future::block_on(test.call(Request::get("/health")));
    assert_eq!(response.status(), 200);
    assert_eq!(response.body(), b"\"ok\"");
}

futures-lite only blocks on the returned future; dispatch is a plain Future, so any executor works.

Links