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 serde::Deserialize;
use serde_json::json;
use servlin::{
socket_addr_127_0_0_1,
Error,
HttpServerBuilder,
Request,
Response
};
use servlin::log::log_request_and_response;
use servlin::reexport::{safina_executor, safina_timer};
use std::sync::Arc;
use temp_dir::TempDir;
struct State {}
fn hello(_state: Arc<State>, req: Request) -> Result<Response, Error> {
#[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, Error> {
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| {
log_request_and_response(req, |req| handle_req(state, req)).unwrap()
};
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(8271))
.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 ๐ servlin 0.4.0
0/0 0/4 0/0 0/0 0/2 โ โโโ async-fs 1.6.0
0/4 0/230 0/40 0/0 0/12 โ โ โโโ async-lock 2.8.0
0/0 0/116 0/8 0/0 0/0 โ โ โ โโโ event-listener 2.5.3
0/0 0/28 0/4 0/0 0/0 โ โ โโโ blocking 1.3.1
0/0 0/0 0/0 0/0 0/0 ๐ โ โ โโโ async-channel 1.9.0
0/0 0/168 0/2 0/0 0/1 โ โ โ โ โโโ concurrent-queue 2.2.0
0/4 0/94 0/16 0/0 0/3 โ โ โ โ โ โโโ crossbeam-utils 0.8.16
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โ โโโ cfg-if 1.0.0
0/0 0/116 0/8 0/0 0/0 โ โ โ โ โโโ event-listener 2.5.3
0/0 0/37 0/2 0/0 0/0 โ โ โ โ โโโ futures-core 0.3.28
0/4 0/230 0/40 0/0 0/12 โ โ โ โโโ async-lock 2.8.0
0/1 0/858 0/4 0/0 0/12 โ โ โ โโโ async-task 4.4.0
0/0 0/33 0/2 0/0 0/0 โ โ โ โโโ atomic-waker 1.1.1
0/0 0/0 0/0 0/0 0/0 ๐ โ โ โโโ fastrand 1.9.0
0/0 0/0 0/0 0/0 0/0 โ โ โ โโโ futures-lite 1.13.0
0/0 0/0 0/0 0/0 0/0 ๐ โ โ โ โโโ fastrand 1.9.0
0/0 0/37 0/2 0/0 0/0 โ โ โ โ โโโ futures-core 0.3.28
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โโโ futures-io 0.3.28
0/41 0/2501 0/2 0/0 0/147 โ โ โ โ โโโ memchr 2.6.3
0/2 0/20 0/1 0/0 0/0 โ โ โ โ โ โโโ log 0.4.20
0/0 0/5 0/0 0/0 0/0 โ โ โ โ โ โโโ serde 1.0.188
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โ โโโ serde_derive 1.0.188
0/0 0/15 0/0 0/0 0/3 โ โ โ โ โ โโโ proc-macro2 1.0.67
0/0 0/4 0/0 0/0 0/0 โ โ โ โ โ โ โโโ unicode-ident 1.0.12
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โ โโโ quote 1.0.33
0/0 0/15 0/0 0/0 0/3 โ โ โ โ โ โ โโโ proc-macro2 1.0.67
0/0 0/79 0/3 0/0 0/2 โ โ โ โ โ โโโ syn 2.0.37
0/0 0/15 0/0 0/0 0/3 โ โ โ โ โ โโโ proc-macro2 1.0.67
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โ โโโ quote 1.0.33
0/0 0/4 0/0 0/0 0/0 โ โ โ โ โ โโโ unicode-ident 1.0.12
0/0 0/0 0/0 0/0 0/0 ๐ โ โ โ โโโ parking 2.1.0
0/0 0/191 0/0 0/0 0/2 โ โ โ โ โโโ pin-project-lite 0.2.13
0/0 0/21 0/0 0/0 0/4 โ โ โ โ โโโ waker-fn 1.1.0
0/2 0/20 0/1 0/0 0/0 โ โ โ โโโ log 0.4.20
0/0 0/0 0/0 0/0 0/0 โ โ โโโ futures-lite 1.13.0
โ [build-dependencies]
0/0 0/0 0/0 0/0 0/0 โ โ โโโ autocfg 1.1.0
0/0 0/0 0/0 0/0 0/0 ๐ โโโ async-net 1.7.0
โ [build-dependencies]
0/0 0/0 0/0 0/0 0/0 โ โ โโโ autocfg 1.1.0
0/0 0/4 0/0 0/0 0/0 โ โ โโโ async-io 1.13.0
0/4 0/230 0/40 0/0 0/12 โ โ โ โโโ async-lock 2.8.0
0/0 0/0 0/0 0/0 0/0 โ โ โ โโโ cfg-if 1.0.0
0/0 0/168 0/2 0/0 0/1 โ โ โ โโโ concurrent-queue 2.2.0
0/0 0/0 0/0 0/0 0/0 โ โ โ โโโ futures-lite 1.13.0
0/2 0/20 0/1 0/0 0/0 โ โ โ โโโ log 0.4.20
0/0 0/0 0/0 0/0 0/0 ๐ โ โ โโโ parking 2.1.0
0/1 0/250 0/16 0/4 0/5 โ โ โ โโโ polling 2.8.0
โ โ โ [build-dependencies]
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โโโ autocfg 1.1.0
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โโโ cfg-if 1.0.0
0/60 0/502 0/2 0/0 0/50 โ โ โ โ โโโ libc 0.2.148
0/2 0/20 0/1 0/0 0/0 โ โ โ โ โโโ log 0.4.20
0/371 0/6690 0/2 0/0 0/22 โ โ โ โโโ rustix 0.37.23
โ โ โ [build-dependencies]
0/1 0/232 0/2 0/0 0/4 โ โ โ โ โโโ cc 1.0.83
0/60 0/502 0/2 0/0 0/50 โ โ โ โ โโโ libc 0.2.148
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โโโ bitflags 1.3.2
0/0 0/100 0/0 0/0 0/0 โ โ โ โ โโโ errno 0.3.3
0/60 0/502 0/2 0/0 0/50 โ โ โ โ โ โโโ libc 0.2.148
0/0 0/666 0/36 0/2 0/14 โ โ โ โ โโโ io-lifetimes 1.0.11
0/60 0/502 0/2 0/0 0/50 โ โ โ โ โ โโโ libc 0.2.148
0/6 0/673 0/4 0/0 0/4 โ โ โ โ โ โโโ socket2 0.4.9
0/60 0/502 0/2 0/0 0/50 โ โ โ โ โ โโโ libc 0.2.148
0/0 0/7 0/0 0/0 0/0 โ โ โ โ โโโ itoa 1.0.9
0/60 0/502 0/2 0/0 0/50 โ โ โ โ โโโ libc 0.2.148
0/0 0/24 0/0 0/0 0/3 โ โ โ โโโ slab 0.4.9
โ โ โ [build-dependencies]
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โโโ autocfg 1.1.0
0/0 0/5 0/0 0/0 0/0 โ โ โ โ โโโ serde 1.0.188
0/6 0/673 0/4 0/0 0/4 โ โ โ โโโ socket2 0.4.9
0/0 0/21 0/0 0/0 0/4 โ โ โ โโโ waker-fn 1.1.0
โ โ [build-dependencies]
0/0 0/0 0/0 0/0 0/0 โ โ โ โโโ autocfg 1.1.0
0/0 0/28 0/4 0/0 0/0 โ โ โโโ blocking 1.3.1
0/0 0/0 0/0 0/0 0/0 โ โ โโโ futures-lite 1.13.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.28
0/0 0/0 0/0 0/0 0/0 โ โโโ futures-io 0.3.28
0/0 0/0 0/0 0/0 0/0 โ โโโ futures-lite 1.13.0
0/0 0/0 0/0 0/0 0/0 โ โโโ include_dir 0.7.3
0/0 0/0 0/0 0/0 0/0 โ โ โโโ include_dir_macros 0.7.3
0/0 0/15 0/0 0/0 0/3 โ โ โโโ proc-macro2 1.0.67
0/0 0/0 0/0 0/0 0/0 โ โ โโโ quote 1.0.33
0/0 0/121 0/9 0/0 0/4 โ โโโ once_cell 1.18.0
0/0 0/0 0/0 0/0 0/0 ๐ โโโ permit 0.2.1
0/0 0/32 0/0 0/0 0/0 โ โโโ rand 0.8.5
0/60 0/502 0/2 0/0 0/50 โ โ โโโ libc 0.2.148
0/2 0/20 0/1 0/0 0/0 โ โ โโโ log 0.4.20
0/0 0/0 0/0 0/0 0/0 โ โ โโโ rand_chacha 0.3.1
0/2 0/712 0/0 0/0 0/25 โ โ โ โโโ ppv-lite86 0.2.17
0/0 0/2 0/0 0/0 0/0 โ โ โ โโโ rand_core 0.6.4
0/7 0/228 0/1 0/0 0/3 โ โ โ โ โโโ getrandom 0.2.10
0/0 0/0 0/0 0/0 0/0 โ โ โ โ โ โโโ cfg-if 1.0.0
0/60 0/502 0/2 0/0 0/50 โ โ โ โ โ โโโ libc 0.2.148
0/0 0/5 0/0 0/0 0/0 โ โ โ โ โโโ serde 1.0.188
0/0 0/5 0/0 0/0 0/0 โ โ โ โโโ serde 1.0.188
0/0 0/2 0/0 0/0 0/0 โ โ โโโ rand_core 0.6.4
0/0 0/5 0/0 0/0 0/0 โ โ โโโ serde 1.0.188
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.67
0/0 0/4 0/0 0/0 0/0 โ โ โ โโโ unicode-ident 1.0.12
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.67
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.67
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
0/0 0/121 0/9 0/0 0/4 โ โ โโโ once_cell 1.18.0
0/0 0/5 0/0 0/0 0/0 โ โโโ serde 1.0.188
0/0 0/7 0/0 0/0 0/0 โ โโโ serde_json 1.0.107
0/0 0/7 0/0 0/0 0/0 โ โ โโโ itoa 1.0.9
0/9 0/715 0/0 0/0 0/2 โ โ โโโ ryu 1.0.15
0/0 0/5 0/0 0/0 0/0 โ โ โโโ serde 1.0.188
0/0 0/0 0/0 0/0 0/0 ๐ โโโ serde_urlencoded 0.7.1
0/0 0/2 0/0 0/0 0/0 โ โ โโโ form_urlencoded 1.2.0
0/0 0/8 0/0 0/0 0/0 โ โ โ โโโ percent-encoding 2.3.0
0/0 0/7 0/0 0/0 0/0 โ โ โโโ itoa 1.0.9
0/9 0/715 0/0 0/0 0/2 โ โ โโโ ryu 1.0.15
0/0 0/5 0/0 0/0 0/0 โ โ โโโ serde 1.0.188
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.4.1
0/0 0/2 0/0 0/0 0/0 โ โโโ form_urlencoded 1.2.0
0/0 0/0 0/0 0/0 0/0 โ โโโ idna 0.4.0
0/0 0/5 0/0 0/0 0/0 โ โ โโโ unicode-bidi 0.3.13
0/0 0/5 0/0 0/0 0/0 โ โ โ โโโ serde 1.0.188
0/0 0/20 0/0 0/0 0/0 โ โ โโโ unicode-normalization 0.1.22
0/0 0/0 0/0 0/0 0/0 ๐ โ โโโ tinyvec 1.6.0
0/0 0/5 0/0 0/0 0/0 โ โ โโโ serde 1.0.188
0/0 0/0 0/0 0/0 0/0 ๐ โ โโโ tinyvec_macros 0.1.1
0/0 0/8 0/0 0/0 0/0 โ โโโ percent-encoding 2.3.0
0/0 0/5 0/0 0/0 0/0 โ โโโ serde 1.0.188
0/509 0/15404 0/156 0/6 0/324
See rust-webserver-comparison.md.
- v0.4.3 - Implement
From<Cow<'_, str>>
andFrom<&Path>
forTagValue
. - v0.4.2 - Implement
Seek
forBodyReader
. - v0.4.1
- Add
Request::opt_json
. - Implement
From<LoggerStoppedError>
forError
.
- Add
- v0.4.0
- Changed
Response::json
to returnResult<Response, Error>
. - Changed
log_request_and_response
to returnResult
. - Added
Response::unprocessable_entity_422
.
- Changed
- v0.3.2 - Fix bug in
Response::include_dir
redirects. - v0.3.1
- Add
Response::redirect_301
Response::include_dir
to redirect from/somedir
to/somedir/
so relative URLs will work.
- Add
- v0.3.0 - Changed
Response::include_dir
to take&Request
and look forindex.html
in dirs. - v0.2.0
- Added:
log_request_and_response
and other logging toolingResponse::ok_200()
Response::unauthorized_401()
Response::forbidden_403()
Response::internal_server_errror_500()
Response::not_implemented_501()
Response::service_unavailable_503()
EventSender::is_connected()
PORT_env()
- Removed
print_log_response
andRequestBody::length_is_known
- Changed
RequestBody::len
andis_empty
to returnOption
. - Bugfixes
- Added:
- v0.1.1 - Add
EventSender::unconnected
. - v0.1.0 - Rename library to Servlin.
- Fix limitations above
- Support HEAD responses that have Content-Length set and no body.
- Add a server-wide limit on upload body size.
- Limit disk usage for caching uploads.
- 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