#http-framework #http #http-service #web #web-framework #server

aero

A progressive, idiomatic, and minimalist framework for building Rust HTTP services

4 releases

0.1.4 Jun 5, 2022
0.1.3 Jun 4, 2022
0.1.1 Jun 4, 2022
0.1.0 Jun 4, 2022

#631 in HTTP server

MIT license

40KB
358 lines

Aero

crates.io

🚀 A progressive, idiomatic, and minimalist framework for building Rust HTTP services.

  • idiomatic router
  • composable middlewares
fn main() {
    let mut app = Aero::new("127.0.0.1:3000");

    app.get("/", |ctx: &mut Context, next: Next| {
        ctx.send_text("Hello, world!");
    });

    app.get("/hello", |ctx: &mut Context, next: Next| {
        ctx.send_text("Hello, world!");
    });

    println!("Listening on http://{}", app.socket_addr);

    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(app.run());
}

wip...

  • clean code
  • response json
  • route
  • body parser
  • file orgnanize
  • api orgnanize
  • publish
  • test

Installation

Add the following line to your Cargo.toml file:

aero = "0.1.3"

Dev

cargo fmt -- */**.rs
cargo run

Usage

  • router

let mut app = Aero::new("127.0.0.1:3000");

let mut router = Router::new("/api");
router.get("/book", |ctx: &mut Context, next: Next| {
    ctx.send_text("hello, is's /api/book");
    next(ctx);
});

app.mount(router);

println!("Listening on http://{}", app.socket_addr);
  • json response

#[derive(Serialize, Deserialize)]
pub struct Book {
    id: i32,
    name: String,
    price: f32,
}

let mut app = Aero::new("127.0.0.1:3000");

let mut router = Router::new("/api");
router.get("/book", |ctx: &mut Context, next: Next| {
    ctx.send_json(Book {
        id: 123,
        name: "asd".to_string(),
        price: 123.3,
    });
    next(ctx);
});
app.mount(router);

app.get("/hello", |ctx: &mut Context, next: Next| {
    ctx.send_text("Hello, world!");
});

println!("Listening on http://{}", app.socket_addr);
  • middleware

let mut app = Aero::new("127.0.0.1:3000");

app.hold("/", |ctx: &mut Context, next: Next| {
    println!("middleware start -> {}", ctx.req.path);
    next(ctx);
    println!("middleware end -> {}", ctx.req.path);
});

app.hold("/", |ctx: &mut Context, next: Next| {
    let start = Instant::now();
    next(ctx);
    let duration = start.elapsed();
    println!(
        "[access] {} {} cost {:?}ms",
        ctx.req.method,
        ctx.req.path,
        duration.as_millis()
    );
});

app.get("/hello", |ctx: &mut Context, next: Next| {
    // some heavy task
    thread::sleep(Duration::from_millis(100));
    ctx.send_text("Hello, world!");
});

println!("Listening on http://{}", app.socket_addr);

examples are listed at examples

Benckmark

Cooper@CooperdeMBP Rust % autocannon http://127.0.0.1:3000/api/shipping/orders
Running 10s test @ http://127.0.0.1:3000/api/shipping/orders
10 connections


┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬──────┐
│ Stat    │ 2.5%50%97.5%99%  │ Avg     │ Stdev   │ Max  │
├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼──────┤
│ Latency │ 0 ms │ 0 ms │ 0 ms  │ 0 ms │ 0.01 ms │ 0.04 ms │ 8 ms │
└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴──────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat      │ 1%2.5%50%97.5%   │ Avg     │ Stdev   │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Req/Sec   │ 46431464315279953887524002055.7946410   │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Bytes/Sec │ 15.2 MB15.2 MB17.3 MB17.6 MB17.1 MB674 kB  │ 15.2 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘

Req/Bytes counts sampled once per second.
# of samples: 10

524k requests in 10.01s, 171 MB read

License

MIT

Dependencies

~4–12MB
~104K SLoC