Skip to main content

Crate snowboard

Crate snowboard 

Source
Expand description

§Snowboard 🏂

License Build status DeepSource dependency status

An extremely simple (& blazingly fast) library for HTTP & HTTPS servers in Rust

Request a feature/Report a bug

Table of Contents

§Quick start

To get started with Snowboard, simply add it and smol-potat (or your preferred async runtime) to your Cargo.toml file:

[dependencies]
snowboard = "*"
smol-potat = { version = "*", features = "auto" }

Then, create a new Rust file with the following code:

use snowboard::{headers, response, Server};

#[smol_potat::main]
async fn main() -> snowboard::Result {
    let server = Server::new("localhost:8080")?;

    println!("Listening on {}", server.pretty_addr()?);

    server
        .run(async move |mut req| {
            println!("{req:#?}");
            response!(ok, "hello from snowboard!", headers! { "X-Hello" => "World!" })
        })
        .await
}

And that’s it! You got yourself a working server on :8080. Examples can be found in the examples folder.

§TLS

Use the tls feature to create secure-connection servers:

use anyhow::Result;
use snowboard::TlsAcceptor;

use snowboard::Server;

use snowboard::smol::fs::File;

#[smol_potat::main]
async fn main() -> Result<()> {
    let password = "1234";
    let idx = File::open("identity.pfx").await?;
    let tls_acceptor = TlsAcceptor::new(idx, password).await?;

    Server::new("localhost:3000", tls_acceptor)?
        .run(async move |request| format!("{request:#?}"))
        .await
}

More info can be found in examples/tls.

§Websockets

WebSockets are easy to implement with the websocket feature. Example (echo server):

use snowboard::Server;
use snowboard::{StreamExt, WebSocket};

async fn handle_ws(ws: WebSocket) {
    let (mut sender, mut reciever) = ws.split();
    while let Some(Ok(msg)) = reciever.next().await {
        let _ = sender.send(msg).await;
    }
}

#[smol_potat::main]
async fn main() -> snowboard::Result {
    Server::new("localhost:8080")?
        .on_websocket("/ws", handle_ws)
        .run(async |_| "Try `/ws`!")
        .await
}

§Routing

Routing can be handled easily using the Url struct:

use snowboard::{response, Request, ResponseLike, Result, Server};

async fn router(req: Request) -> impl ResponseLike {
    // /{x}
    match req.parse_url().at(0) {
        Some("ping") => response!(ok, "Pong!"),
        Some("api") => response!(continue),
        None => response!(ok, "Hello, world!"),
        _ => response!(not_found, "Route not found"),
    }
}

#[smol_potat::main]
async fn main() -> Result {
    Server::new("localhost:8080")?.run(router).await
}

§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,
}

#[smol_potat::main]
async fn main() -> snowboard::Result {
    Server::new("localhost:8080")?
        .run(async |req| -> Result<Value, Response> {
            let parsed: Example = req.expect_json()?;

            Ok(serde_json::json!({
                "number_plus_one": parsed.number + 1
            }))
        })
        .await
}

expect_json returns a result of either the parsed JSON or a bad request response. If you want to handle the error yourself, use the json function 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, you can 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, format!("My favorite number is {}!", self.num))
    }
}

#[smol_potat::main]
async fn main() -> snowboard::Result {
    Server::new("localhost:8080")?
        .run(async |_| Example { num: 5 })
        .await
}

§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

Re-exports§

pub use smol;

Macros§

headers
A quick way to create a header HashMap.
response
A quick way to create responses.

Structs§

Request
A server request. Parses the raw request string into a more usable format.
Response
Response struct. Contains the response data and converts it to text if needed.
Server
Single threaded listener made for simpler servers.
TcpListener
A TCP server, listening for connections.
Url
A parsed URL.

Enums§

Method
Any valid HTTP method.

Constants§

DEFAULT_BUFFER_SIZE
The size of the buffer used to read incoming requests. It’s set to 8KiB by default.
_DEFAULT_HTTP_VERSION
The default HTTP version used by the server.

Traits§

ResponseLike
A trait for everything that can be converted into a Response.
StreamExt
Extension trait for Stream.

Type Aliases§

Headers
Equivalent to HashMap<&'static str, String>.
Result
A type alias for std::io::Result<()> used in Server::new()?.run(...).
Stream
A TCP stream