NOTE: This library was renamed to Servlin.
A modular HTTP server library in Rust.
forbid(unsafe_code)
- Threaded request handlers:
FnOnce(Request) -> Response + 'static + Clone + Send + Sync
- Uses async code internally for excellent performance under load
- JSON
- Server-Sent Events (SSE)
- Saves large request bodies to temp files
- Sends 100-Continue
- Limits number of threads and connections
- Modular: roll your own logging, write custom versions of internal methods, etc.
- No macros or complicated type params
- Good test coverage (63%)
- New, not proven in production.
- To do:
- Request timeouts
chunked
transfer-encoding for request bodies- gzip
- brotli
- TLS
- automatically getting TLS certs via ACME
- Drop idle connections when approaching connection limit.
- Denial-of-Service mitigation: source throttling, minimum throughput
- Complete functional test suite
- Missing load tests
- Disk space usage limits
Complete examples: examples/
.
Simple example:
use beatrice::{
print_log_response,
socket_addr_127_0_0_1,
HttpServerBuilder,
Request,
Response
};
use beatrice::reexport::{safina_executor, safina_timer};
use serde::Deserialize;
use serde_json::json;
use std::sync::Arc;
use temp_dir::TempDir;
struct State {}
fn hello(_state: Arc<State>, req: &Request) -> Result<Response, Response> {
#[derive(Deserialize)]
struct Input {
name: String,
}
let input: Input = req.json()?;
Ok(Response::json(200, json!({"message": format!("Hello, {}!", input.name)}))
.unwrap())
}
fn handle_req(state: Arc<State>, req: &Request) -> Result<Response, Response> {
match (req.method(), req.url().path()) {
("GET", "/ping") => Ok(Response::text(200, "ok")),
("POST", "/hello") => hello(state, req),
_ => Ok(Response::text(404, "Not found")),
}
}
let state = Arc::new(State {});
let request_handler = move |req: Request| {
print_log_response(&req, handle_req(state, &req))
};
let cache_dir = TempDir::new().unwrap();
safina_timer::start_timer_thread();
let executor = safina_executor::Executor::new(1, 9).unwrap();
executor.block_on(
HttpServerBuilder::new()
.listen_addr(socket_addr_127_0_0_1(8000))
.max_conns(1000)
.small_body_len(64 * 1024)
.receive_large_bodies(cache_dir.path())
.spawn_and_join(request_handler)
).unwrap();
Metric output format: x/y
x = unsafe code used by the build
y = total unsafe code found in the crate
Symbols:
π = No `unsafe` usage found, declares #![forbid(unsafe_code)]
β = No `unsafe` usage found, missing #![forbid(unsafe_code)]
β’οΈ = `unsafe` usage found
Functions Expressions Impls Traits Methods Dependency
0/0 0/0 0/0 0/0 0/0 π beatrice 0.3.2
0/0 4/4 0/0 0/0 2/2 β’οΈ βββ async-fs 1.5.0
0/0 51/51 14/14 0/0 0/0 β’οΈ β βββ async-lock 2.5.0
0/0 106/116 4/8 0/0 0/0 β’οΈ β β βββ event-listener 2.5.2
0/0 28/28 4/4 0/0 0/0 β’οΈ β βββ blocking 1.2.0
0/0 0/0 0/0 0/0 0/0 π β β βββ async-channel 1.6.1
0/0 155/155 2/2 0/0 1/1 β’οΈ β β β βββ concurrent-queue 1.2.2
0/0 0/0 0/0 0/0 0/0 π β β β β βββ cache-padded 1.2.0
0/0 106/116 4/8 0/0 0/0 β’οΈ β β β βββ event-listener 2.5.2
0/0 30/30 2/2 0/0 0/0 β’οΈ β β β βββ futures-core 0.3.21
1/1 802/802 4/4 0/0 10/10 β’οΈ β β βββ async-task 4.2.0
0/0 26/26 2/2 0/0 0/0 β’οΈ β β βββ atomic-waker 1.0.0
0/0 0/0 0/0 0/0 0/0 π β β βββ fastrand 1.7.0
0/0 0/0 0/0 0/0 0/0 β β β βββ futures-lite 1.12.0
0/0 0/0 0/0 0/0 0/0 π β β β βββ fastrand 1.7.0
0/0 30/30 2/2 0/0 0/0 β’οΈ β β β βββ futures-core 0.3.21
0/0 0/0 0/0 0/0 0/0 β β β β βββ futures-io 0.3.21
36/37 2067/2144 0/0 0/0 21/21 β’οΈ β β β βββ memchr 2.5.0
1/21 10/368 0/2 0/0 5/40 β’οΈ β β β β βββ libc 0.2.126
0/0 0/0 0/0 0/0 0/0 π β β β βββ parking 2.0.0
0/0 11/165 0/0 0/0 2/2 β’οΈ β β β βββ pin-project-lite 0.2.9
0/0 21/21 0/0 0/0 4/4 β’οΈ β β β βββ waker-fn 1.1.0
1/1 75/117 4/6 0/0 2/3 β’οΈ β β βββ once_cell 1.12.0
0/0 0/0 0/0 0/0 0/0 β β βββ futures-lite 1.12.0
0/0 0/0 0/0 0/0 0/0 π βββ async-net 1.6.1
0/0 22/22 0/0 0/0 0/0 β’οΈ β βββ async-io 1.7.0
0/0 155/155 2/2 0/0 1/1 β’οΈ β β βββ concurrent-queue 1.2.2
0/0 0/0 0/0 0/0 0/0 β β β βββ futures-lite 1.12.0
1/21 10/368 0/2 0/0 5/40 β’οΈ β β βββ libc 0.2.126
1/1 16/18 1/1 0/0 0/0 β’οΈ β β βββ log 0.4.17
0/0 0/0 0/0 0/0 0/0 β β β β βββ cfg-if 1.0.0
0/0 5/5 0/0 0/0 0/0 β’οΈ β β β βββ serde 1.0.137
0/0 0/0 0/0 0/0 0/0 β β β β βββ serde_derive 1.0.137
0/0 12/12 0/0 0/0 3/3 β’οΈ β β β βββ proc-macro2 1.0.39
0/0 4/4 0/0 0/0 0/0 β’οΈ β β β β βββ unicode-ident 1.0.0
0/0 0/0 0/0 0/0 0/0 β β β β βββ quote 1.0.18
0/0 12/12 0/0 0/0 3/3 β’οΈ β β β β βββ proc-macro2 1.0.39
0/0 50/50 3/3 0/0 2/2 β’οΈ β β β βββ syn 1.0.96
0/0 12/12 0/0 0/0 3/3 β’οΈ β β β βββ proc-macro2 1.0.39
0/0 0/0 0/0 0/0 0/0 β β β β βββ quote 1.0.18
0/0 4/4 0/0 0/0 0/0 β’οΈ β β β βββ unicode-ident 1.0.0
1/1 75/117 4/6 0/0 2/3 β’οΈ β β βββ once_cell 1.12.0
0/0 0/0 0/0 0/0 0/0 π β β βββ parking 2.0.0
0/0 0/9 1/6 0/0 0/0 β’οΈ β β βββ polling 2.2.0
0/0 0/0 0/0 0/0 0/0 β β β β βββ cfg-if 1.0.0
1/21 10/368 0/2 0/0 5/40 β’οΈ β β β βββ libc 0.2.126
1/1 16/18 1/1 0/0 0/0 β’οΈ β β β βββ log 0.4.17
0/0 24/24 0/0 0/0 3/3 β’οΈ β β βββ slab 0.4.6
0/0 5/5 0/0 0/0 0/0 β’οΈ β β β βββ serde 1.0.137
3/6 528/641 2/4 0/0 3/4 β’οΈ β β βββ socket2 0.4.4
1/21 10/368 0/2 0/0 5/40 β’οΈ β β β βββ libc 0.2.126
0/0 21/21 0/0 0/0 4/4 β’οΈ β β βββ waker-fn 1.1.0
0/0 28/28 4/4 0/0 0/0 β’οΈ β βββ blocking 1.2.0
0/0 0/0 0/0 0/0 0/0 β β βββ futures-lite 1.12.0
0/0 0/0 0/0 0/0 0/0 π βββ fixed-buffer 0.5.0
0/0 0/0 0/0 0/0 0/0 β β βββ futures-io 0.3.21
0/0 0/0 0/0 0/0 0/0 β βββ futures-io 0.3.21
0/0 0/0 0/0 0/0 0/0 β βββ futures-lite 1.12.0
0/0 0/0 0/0 0/0 0/0 β βββ include_dir 0.7.2
0/0 0/0 0/0 0/0 0/0 β β βββ include_dir_macros 0.7.2
0/0 12/12 0/0 0/0 3/3 β’οΈ β βββ proc-macro2 1.0.39
0/0 0/0 0/0 0/0 0/0 β β βββ quote 1.0.18
0/0 0/0 0/0 0/0 0/0 π βββ permit 0.1.4
0/0 0/0 0/0 0/0 0/0 π βββ safe-regex 0.2.5
0/0 0/0 0/0 0/0 0/0 π β βββ safe-regex-macro 0.2.5
0/0 0/0 0/0 0/0 0/0 π β βββ safe-proc-macro2 1.0.36
0/0 0/0 0/0 0/0 0/0 π β β βββ unicode-xid 0.2.3
0/0 0/0 0/0 0/0 0/0 π β βββ safe-regex-compiler 0.2.5
0/0 0/0 0/0 0/0 0/0 π β βββ safe-proc-macro2 1.0.36
0/0 0/0 0/0 0/0 0/0 π β βββ safe-quote 1.0.15
0/0 0/0 0/0 0/0 0/0 π β βββ safe-proc-macro2 1.0.36
0/0 0/0 0/0 0/0 0/0 π βββ safina-executor 0.3.3
0/0 0/0 0/0 0/0 0/0 π β βββ safina-sync 0.2.4
0/0 0/0 0/0 0/0 0/0 π β βββ safina-threadpool 0.2.4
0/0 0/0 0/0 0/0 0/0 π βββ safina-sync 0.2.4
0/0 0/0 0/0 0/0 0/0 π βββ safina-timer 0.1.11
1/1 75/117 4/6 0/0 2/3 β’οΈ β βββ once_cell 1.12.0
0/0 5/5 0/0 0/0 0/0 β’οΈ βββ serde 1.0.137
0/0 4/7 0/0 0/0 0/0 β’οΈ βββ serde_json 1.0.81
0/0 7/7 0/0 0/0 0/0 β’οΈ β βββ itoa 1.0.2
7/9 587/723 0/0 0/0 2/2 β’οΈ β βββ ryu 1.0.10
0/0 5/5 0/0 0/0 0/0 β’οΈ β βββ serde 1.0.137
0/0 0/0 0/0 0/0 0/0 π βββ serde_urlencoded 0.7.1
0/0 2/2 0/0 0/0 0/0 β’οΈ β βββ form_urlencoded 1.0.1
0/0 0/0 0/0 0/0 0/0 β β β βββ matches 0.1.9
0/0 3/3 0/0 0/0 0/0 β’οΈ β β βββ percent-encoding 2.1.0
0/0 7/7 0/0 0/0 0/0 β’οΈ β βββ itoa 1.0.2
7/9 587/723 0/0 0/0 2/2 β’οΈ β βββ ryu 1.0.10
0/0 5/5 0/0 0/0 0/0 β’οΈ β βββ serde 1.0.137
0/0 0/0 0/0 0/0 0/0 π βββ temp-dir 0.1.11
0/0 0/0 0/0 0/0 0/0 π βββ temp-file 0.1.7
0/0 0/0 0/0 0/0 0/0 β βββ url 2.2.2
0/0 2/2 0/0 0/0 0/0 β’οΈ βββ form_urlencoded 1.0.1
0/0 0/0 0/0 0/0 0/0 β βββ idna 0.2.3
0/0 0/0 0/0 0/0 0/0 β β βββ matches 0.1.9
0/0 0/0 0/0 0/0 0/0 π β βββ unicode-bidi 0.3.8
0/0 5/5 0/0 0/0 0/0 β’οΈ β β βββ serde 1.0.137
0/0 20/20 0/0 0/0 0/0 β’οΈ β βββ unicode-normalization 0.1.19
0/0 0/0 0/0 0/0 0/0 π β βββ tinyvec 1.6.0
0/0 5/5 0/0 0/0 0/0 β’οΈ β βββ serde 1.0.137
0/0 0/0 0/0 0/0 0/0 β β βββ tinyvec_macros 0.1.0
0/0 0/0 0/0 0/0 0/0 β βββ matches 0.1.9
0/0 3/3 0/0 0/0 0/0 β’οΈ βββ percent-encoding 2.1.0
0/0 5/5 0/0 0/0 0/0 β’οΈ βββ serde 1.0.137
50/76 4670/5574 43/58 0/0 60/97
See rust-webserver-comparison.md.
- v0.3.2 - Renaming project to 'servlin'.
- v0.3.1 - Add
Response::include_dir
. - v0.3.0
- Add
RequestBody::StaticBytes
. - Add
ResponseBody::StaticBytes
. - Remove
impl From<&[u8]>
forRequestBody
andResponseBody
.
- Add
- v0.2.0 - Make
print_log_response
easier to use. - v0.1.0 - First published version
- Fix limitations above
- Support HEAD responses that have Content-Length set and no body.
- Update
rust-webserver-comparison.md
- Add missing data
- Add other servers from https://www.arewewebyet.org/topics/frameworks/
- Rearrange
- Generate geiger reports for each web server
License: MIT OR Apache-2.0