pulse_http 0.2.0

Async HTTP/1.1 framework on Tokio — raw TCP, routing, middleware, no Hyper
Documentation
use criterion::{Criterion, criterion_group, criterion_main};
use pulse_http::{
    Request, Response, Router, State, headers::Headers, parse_multipart, parse_urlencoded,
};
use std::{hint::black_box, net::IpAddr};

fn sample_headers() -> &'static [u8] {
    b"GET /hello/akshat?x=1 HTTP/1.1\r\n\
Host: localhost:3000\r\n\
User-Agent: pulse-bench\r\n\
Accept: */*\r\n\
Connection: keep-alive\r\n\
Content-Type: application/json\r\n\
\r\n"
}

fn sample_multipart() -> (&'static [u8], &'static str) {
    let body = b"\
--abc\r\n\
Content-Disposition: form-data; name=\"password\"\r\n\
\r\n\
secret\r\n\
--abc\r\n\
Content-Disposition: form-data; name=\"file\"; filename=\"note.txt\"\r\n\
Content-Type: text/plain\r\n\
\r\n\
hello world file bytes\r\n\
--abc--\r\n";
    (body, "multipart/form-data; boundary=abc")
}

fn bench_parse_headers(c: &mut Criterion) {
    let raw = sample_headers();
    c.bench_function("parse_headers", |b| {
        b.iter(|| Headers::parse(black_box(raw)).unwrap())
    });
}

fn bench_parse_urlencoded(c: &mut Criterion) {
    let body = "name=akshat&email=a%40b.com&msg=hello+world&count=42";
    c.bench_function("parse_urlencoded", |b| {
        b.iter(|| parse_urlencoded(black_box(body)).unwrap())
    });
}

fn bench_parse_multipart(c: &mut Criterion) {
    let (body, content_type) = sample_multipart();
    c.bench_function("parse_multipart", |b| {
        b.iter(|| parse_multipart(black_box(body), black_box(content_type)).unwrap())
    });
}

fn bench_router_match(c: &mut Criterion) {
    let router = Router::new()
        .get("/health", |_req: Request| async { Response::ok("ok") })
        .get("/hello/:name", |_req: Request| async { Response::ok("hi") })
        .post("/echo", |_req: Request| async { Response::ok("echo") });

    let raw = b"GET /hello/akshat HTTP/1.1\r\nHost: x\r\n\r\n";
    let headers = Headers::parse(raw).unwrap();
    let ip: IpAddr = "127.0.0.1".parse().unwrap();

    c.bench_function("router_match_param", |b| {
        b.iter(|| {
            let mut req =
                Request::from_headers(headers.clone(), Vec::new(), State::new(), ip).unwrap();
            router.match_route(black_box(&mut req)).unwrap();
        })
    });
}

criterion_group!(
    benches,
    bench_parse_headers,
    bench_parse_urlencoded,
    bench_parse_multipart,
    bench_router_match
);
criterion_main!(benches);