{"id":18421219,"url":"https://github.com/ibnz36/snowboard","last_synced_at":"2025-04-07T14:31:39.444Z","repository":{"id":202742295,"uuid":"708051396","full_name":"ibnz36/snowboard","owner":"ibnz36","description":"fast, simple \u0026 reliable http rust servers :snowboarder:","archived":false,"fork":false,"pushed_at":"2024-02-04T13:09:50.000Z","size":372,"stargazers_count":32,"open_issues_count":4,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-22T19:43:27.385Z","etag":null,"topics":["http","rust","server"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/snowboard","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ibnz36.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.YML","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null},"funding":{"ko_fi":"brian3647"}},"created_at":"2023-10-21T11:29:14.000Z","updated_at":"2024-10-18T06:56:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"f1079d57-602b-4571-a288-c90c01262799","html_url":"https://github.com/ibnz36/snowboard","commit_stats":null,"previous_names":["brian3647/snowboard","ibnz36/snowboard"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibnz36%2Fsnowboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibnz36%2Fsnowboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibnz36%2Fsnowboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibnz36%2Fsnowboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ibnz36","download_url":"https://codeload.github.com/ibnz36/snowboard/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247669887,"owners_count":20976467,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http","rust","server"],"created_at":"2024-11-06T04:24:47.416Z","updated_at":"2025-04-07T14:31:39.151Z","avatar_url":"https://github.com/ibnz36.png","language":"Rust","funding_links":["https://ko-fi.com/brian3647"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# **Snowboard 🏂**\n\n![License](https://img.shields.io/github/license/Brian3647/snowboard)\n![Build status](https://img.shields.io/github/actions/workflow/status/Brian3647/snowboard/rust.yml)\n[![DeepSource](https://app.deepsource.com/gh/Brian3647/snowboard.svg/?label=active+issues\u0026show_trend=false)](https://app.deepsource.com/gh/Brian3647/snowboard/)\n[![dependency status](https://deps.rs/repo/github/Brian3647/snowboard/status.svg)](https://deps.rs/repo/github/Brian3647/snowboard)\n\nAn extremely simple (\u0026 blazingly fast) library for HTTP \u0026 HTTPS servers in Rust\n\n[Request a feature/Report a bug](https://github.com/Brian3647/snowboard/issues)\n\n\u003c/div\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eTable of Contents\u003c/summary\u003e\n\n-   [**Snowboard 🏂**](#snowboard-)\n    -   [**Quick start**](#quick-start)\n    -   [**Async routes**](#async-routes)\n    -   [**TLS**](#tls)\n    -   [**Websockets**](#websockets)\n    -   [**Routing**](#routing)\n    -   [**Integration**](#integration)\n        -   [**JSON**](#json)\n        -   [**ResponseLike**](#responselike)\n    -   [**MSRV (Minimum Supported Rust Version)**](#msrv-minimum-supported-rust-version)\n    -   [**Contributing**](#contributing)\n    -   [**License**](#license)\n\n\u003c/details\u003e\n\n## **Quick start**\n\nTo get started with Snowboard, simply add it to your `Cargo.toml` file:\n\n```toml\n[dependencies]\nsnowboard = \"*\"\n```\n\nThen, create a new Rust file with the following code:\n\n```rust\nuse snowboard::{headers, response, Method, Result, Server};\n\nfn main() -\u003e Result {\n    let data = \"Hello, world!\";\n\n    let server = Server::new(\"localhost:8080\")?;\n\n    println!(\"Listening on {}\", server.pretty_addr()?);\n\n    server.run(move |mut req| {\n        if req.method == Method::DELETE {\n            return response!(method_not_allowed, \"Caught you trying to delete!\");\n        }\n\n        req.set_header(\"X-Server\", \"Snowboard\");\n\n        println!(\"{req:#?}\");\n\n        response!(ok, data, headers! { \"X-Hello\" =\u003e \"World!\" })\n    })\n}\n```\n\nAnd that's it! You got yourself a working server on :8080. Examples can be found in the `examples` folder.\n\n## **Async routes**\n\nYou can use the `async` feature and `Server::run_async` to run async routes:\n\n```toml\n# Cargo.toml\n\n[dependencies]\nsnowboard = { version = \"*\", features = [\"async\"] }\n```\n\n```rust\n// src/main.rs\nuse snowboard::{Request, ResponseLike, Server, Result};\nuse async_std::task;\nuse std::duration::Duration;\n\nasync fn index(_: Request) -\u003e impl ResponseLike {\n    task::sleep(Duration::from_secs(1)).await;\n\n    \"Async works\"\n}\n\nfn main() -\u003e Result {\n    Server::new(\"localhost:8080\")?.run_async(index)\n}\n```\n\n## **TLS**\n\nUse the `tls` feature (which will also install `native-tls`) to use TLS:\n\n```rust\nuse anyhow::Result;\nuse snowboard::{\n    Identity, TlsAcceptor,\n    response, Server,\n};\n\nuse std::fs;\n\nfn main() -\u003e Result\u003c()\u003e {\n    let der = fs::read(\"identity.pfx\")?;\n    let password = ..;\n    let tls_acceptor = TlsAcceptor::new(Identity::from_pkcs12(\u0026der, password)?)?;\n\n    Server::new_with_tls(\"localhost:3000\", tls_acceptor)?\n        .run(|request| format!(\"{request:#?}\"))\n}\n```\n\nYou can confirm it works by running `curl -k https://localhost:3000` _(the -k is needed to allow self-signed certificates)_\n\nMore info can be found in `examples/tls`.\n\n## **Websockets**\n\nWebSockets are easy to implement with the `websocket` feature. Example (echo server):\n\n```rust\nuse std::net::TcpStream;\n\nuse snowboard::Server;\nuse snowboard::WebSocket;\n\nfn handle_ws(mut ws: WebSocket) {\n    while let Ok(msg) = ws.read() {\n        ws.send(msg).unwrap();\n    }\n}\n\nfn main() -\u003e snowboard::Result {\n    Server::new(\"localhost:3000\")?\n        .on_websocket(\"/ws\", handle_ws)\n        .run(|_| \"Try `/ws`!\")\n}\n```\n\n## **Routing**\n\nRouting can be handled easily using the `Url` struct:\n\n```rust\nuse snowboard::{response, Request, ResponseLike, Result, Server};\n\nfn router(req: Request) -\u003e impl ResponseLike {\n    // /{x}\n    match req.parse_url().at(0) {\n        Some(\"ping\") =\u003e response!(ok, \"Pong!\"),\n        Some(\"api\") =\u003e response!(not_implemented, \"👀\"),\n        None =\u003e response!(ok, \"Hello, world!\"),\n        _ =\u003e response!(not_found, \"Route not found\"),\n    }\n}\n\nfn main() -\u003e Result {\n    Server::new(\"localhost:8080\")?.run(router);\n}\n```\n\n## **Integration**\n\n### **JSON**\n\nJSON is supported with the `json` feature (serializing \u0026 deserializing):\n\n```rust\nuse serde_json::Value;\nuse snowboard::{Response, Server};\n\n#[derive(serde::Deserialize)]\nstruct Example {\n    number: isize,\n}\n\nfn main() -\u003e snowboard::Result {\n    Server::new(\"localhost:8080\")?.run(|req| -\u003e Result\u003cValue, Response\u003e {\n        let example: Example = req.force_json()?;\n\n        Ok(serde_json::json!({\n            \"number_plus_one\": example.number + 1\n        }))\n    });\n}\n```\n\n```rust\nuse snowboard::Server;\n\nfn main() -\u003e snowboard::Result {\n    Server::new(\"localhost:3000\")?.run(|r| {\n        serde_json::json!({\n            \"ip\": r.ip(),\n            \"url\": r.parse_url(),\n            \"method\": r.method,\n            \"body\": r.text(),\n            \"headers\": r.headers,\n\t\t})\n\t})\n}\n```\n\n`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.\n\n### **ResponseLike**\n\nSnowboard'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:\n\n```rust\nuse snowboard::{Response, ResponseLike, Server};\n\nstruct Example {\n    num: usize,\n}\n\nimpl ResponseLike for Example {\n    fn to_response(self) -\u003e Response {\n        snowboard::response!(ok, self.num.to_string())\n    }\n}\n\nfn main() -\u003e snowboard::Result {\n    Server::new(\"localhost:8080\")?\n        .run(|_| Example { num: 5 });\n}\n```\n\n## **MSRV (Minimum Supported Rust Version)**\n\nThe MSRV is 1.60.0, but it might change (lower or higher) depending on which features are enabled.\n\n## **Contributing**\n\nCheck [CONTRIBUTING.md](CONTRIBUTING.md) for a simple guide on how to help the project.\n\n## **License**\n\nThis code is under the MIT license that can be found at [LICENSE](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibnz36%2Fsnowboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fibnz36%2Fsnowboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibnz36%2Fsnowboard/lists"}