Expand description
§NOTE: This library was renamed to Servlin.
§Beatrice
A modular HTTP server library in Rust.
§Features
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%)
§Limitations
- 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
§Examples
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();
§Cargo Geiger Safety Report
§Alternatives
See rust-webserver-comparison.md.
§Changelog
- 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
§TO DO
- 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
Modules§
- This part of the library is not covered by the semver guarantees. If you use these in your program, a minor version upgrade could break your build.
Structs§
- Wraps a
String
that contains only US-ASCII chars. - Builds an HTTP server.
Enums§
- Struct returned by
RequestBody::async_reader
andResponseBody::async_reader
. - Struct returned by
RequestBody::reader
andResponseBody::reader
.