sark 0.13.0

Simple Asynchronous Rust webKit - Server
Documentation
use std::net::SocketAddr;

use o3::buffer::Shared;
use sark::{HttpServer, Tcp, Throughput, app, driver, listener, tcp};
use sark_core::http::{IterStream, Stream};

#[sark_gen::request(ordered)]
struct DownloadRequest {
    #[path("n")]
    pub n: usize,
}

type ChunkStream = Stream<IterStream<std::iter::Map<std::ops::Range<usize>, fn(usize) -> Shared>>>;

const MAX_CONNECTIONS: usize = 1024;

#[sark_gen::handler]
fn download(request: DownloadRequest, _state: &()) -> ChunkStream {
    let n = request.n.min(10_000);
    let mk: fn(usize) -> Shared = |i| Shared::from(format!("chunk {i}\n").into_bytes());
    Stream::from_chunks((0..n).map(mk)).header(b"content-type", b"text/plain; charset=utf-8")
}

sark_gen::define_route! {
    DownloadApp: () => {
        GET "/download/:n" => stream(capacity = MAX_CONNECTIONS) download,
    }
}

fn main() -> std::io::Result<()> {
    const HTTP_LISTENER_ID: u8 = 0;
    const DATE_UPDATER_ID: u8 = 1;
    let bind: SocketAddr = std::env::var("BIND")
        .unwrap_or_else(|_| "127.0.0.1:8080".to_string())
        .parse()
        .expect("invalid BIND");

    let server = HttpServer::<HTTP_LISTENER_ID, DATE_UPDATER_ID, Throughput>::new(
        listener::config::Config::<Tcp> {
            bind,
            max_connections: MAX_CONNECTIONS,
            backlog: 1024,
            stream: tcp::stream::Config {
                no_delay: Some(true),
                ..Default::default()
            },
            transport: tcp::listener::Config {
                reuse_port: true,
                ..Default::default()
            },
            egress: Default::default(),
        },
        std::time::Duration::from_secs(10),
    );

    eprintln!("sark download example: GET http://{bind}/download/<n>");

    server.run(
        vec![0u16],
        |_cpu| driver::Config::for_tcp_profile::<Throughput>(MAX_CONNECTIONS),
        |server, session| {
            let timer = sark::Timer::new();
            server.serve(
                session,
                DownloadApp::new(
                    &(),
                    &timer,
                    app::Config {
                        task_capacity: MAX_CONNECTIONS,
                    },
                ),
                None,
            )
        },
    )
}