32 releases (4 stable)
1.0.3 | Dec 24, 2023 |
---|---|
1.0.0 | Nov 22, 2023 |
0.7.3 | Nov 20, 2023 |
#402 in HTTP server
374 downloads per month
43KB
833 lines
Snowboard 🏂
An extremely simple (& blazingly fast) library for HTTP & HTTPS servers in Rust
Table of Contents
Quick start
To get started with Snowboard, simply add it to your Cargo.toml
file:
[dependencies]
snowboard = "*"
Then, create a new Rust file with the following code:
use snowboard::{headers, response, Method, Result, Server};
fn main() -> Result {
let data = "Hello, world!";
let server = Server::new("localhost:8080")?;
println!("Listening on {}", server.pretty_addr()?);
server.run(move |mut req| {
if req.method == Method::DELETE {
return response!(method_not_allowed, "Caught you trying to delete!");
}
req.set_header("X-Server", "Snowboard");
println!("{req:#?}");
response!(ok, data, headers! { "X-Hello" => "World!" })
})
}
And that's it! You got yourself a working server on :8080. Examples can be found in the examples
folder.
Async routes
You can use the async
feature and Server::run_async
to run async routes:
# Cargo.toml
[dependencies]
snowboard = { version = "*", features = ["async"] }
// src/main.rs
use snowboard::{Request, ResponseLike, Server, Result};
use async_std::task;
use std::duration::Duration;
async fn index(_: Request) -> impl ResponseLike {
task::sleep(Duration::from_secs(1)).await;
"Async works"
}
fn main() -> Result {
Server::new("localhost:8080")?.run_async(index)
}
TLS
Use the tls
feature (which will also install native-tls
) to use TLS:
use anyhow::Result;
use snowboard::{
Identity, TlsAcceptor,
response, Server,
};
use std::fs;
fn main() -> Result<()> {
let der = fs::read("identity.pfx")?;
let password = ..;
let tls_acceptor = TlsAcceptor::new(Identity::from_pkcs12(&der, password)?)?;
Server::new_with_tls("localhost:3000", tls_acceptor)?
.run(|request| format!("{request:#?}"))
}
You can confirm it works by running curl -k https://localhost:3000
(the -k is needed to allow self-signed certificates)
More info can be found in examples/tls
.
Websockets
WebSockets are easy to implement with the websocket
feature. Example (echo server):
use std::net::TcpStream;
use snowboard::Server;
use snowboard::WebSocket;
fn handle_ws(mut ws: WebSocket) {
while let Ok(msg) = ws.read() {
ws.send(msg).unwrap();
}
}
fn main() -> snowboard::Result {
Server::new("localhost:3000")?
.on_websocket("/ws", handle_ws)
.run(|_| "Try `/ws`!")
}
Routing
Routing can be handled easily using the Url
struct:
use snowboard::{response, Request, ResponseLike, Result, Server};
fn router(req: Request) -> impl ResponseLike {
// /{x}
match req.parse_url().at(0) {
Some("ping") => response!(ok, "Pong!"),
Some("api") => response!(not_implemented, "👀"),
None => response!(ok, "Hello, world!"),
_ => response!(not_found, "Route not found"),
}
}
fn main() -> Result {
Server::new("localhost:8080")?.run(router);
}
Integration
JSON
JSON is supported with the json
feature (serializing & deserializing):
use serde_json::Value;
use snowboard::{Response, Server};
#[derive(serde::Deserialize)]
struct Example {
number: isize,
}
fn main() -> snowboard::Result {
Server::new("localhost:8080")?.run(|req| -> Result<Value, Response> {
let example: Example = req.force_json()?;
Ok(serde_json::json!({
"number_plus_one": example.number + 1
}))
});
}
use snowboard::Server;
fn main() -> snowboard::Result {
Server::new("localhost:3000")?.run(|r| {
serde_json::json!({
"ip": r.ip(),
"url": r.parse_url(),
"method": r.method,
"body": r.text(),
"headers": r.headers,
})
})
}
force_json
returns a result of either the parsed JSON or a bad request response. If you want to handle the error yourself, use json
instead.
ResponseLike
Snowboard's ResponseLike
is designed to work with pretty much anything, but it wont by default with certain cases like maud
's html!
macro. If you happen to use a lot a crate that doesn't work with Snowboard, please open an issue, pr or implement ResponseLike
for it:
use snowboard::{Response, ResponseLike, Server};
struct Example {
num: usize,
}
impl ResponseLike for Example {
fn to_response(self) -> Response {
snowboard::response!(ok, self.num.to_string())
}
}
fn main() -> snowboard::Result {
Server::new("localhost:8080")?
.run(|_| Example { num: 5 });
}
MSRV (Minimum Supported Rust Version)
The MSRV is 1.60.0, but it might change (lower or higher) depending on which features are enabled.
Contributing
Check CONTRIBUTING.md for a simple guide on how to help the project.
License
This code is under the MIT license that can be found at LICENSE
Dependencies
~1–11MB
~128K SLoC