{"id":28574786,"url":"https://github.com/BersisSe/feather","last_synced_at":"2025-06-10T22:02:50.969Z","repository":{"id":273581374,"uuid":"920177325","full_name":"BersisSe/feather","owner":"BersisSe","description":"Feather🪶: A Rust web framework that does not use async ","archived":false,"fork":false,"pushed_at":"2025-06-09T11:17:06.000Z","size":182,"stargazers_count":680,"open_issues_count":0,"forks_count":20,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-09T12:26:20.044Z","etag":null,"topics":["express","http","middleware","rust","server","web","web-framework"],"latest_commit_sha":null,"homepage":"","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/BersisSe.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2025-01-21T17:40:06.000Z","updated_at":"2025-06-09T11:17:09.000Z","dependencies_parsed_at":"2025-01-21T19:26:43.865Z","dependency_job_id":"baa7bbda-2ac9-4430-85a2-ff8195946f97","html_url":"https://github.com/BersisSe/feather","commit_stats":null,"previous_names":["bersisse/feather"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BersisSe%2Ffeather","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BersisSe%2Ffeather/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BersisSe%2Ffeather/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BersisSe%2Ffeather/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BersisSe","download_url":"https://codeload.github.com/BersisSe/feather/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BersisSe%2Ffeather/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258892407,"owners_count":22773835,"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":["express","http","middleware","rust","server","web","web-framework"],"created_at":"2025-06-10T22:01:46.493Z","updated_at":"2025-06-10T22:02:50.939Z","avatar_url":"https://github.com/BersisSe.png","language":"Rust","readme":"# 🪶 Feather\n\n## **Feather** is a lightweight, DX-first web framework for Rust — inspired by the simplicity of Express.js, but designed for Rust’s performance and safety.\n\n## Why Feather?\n\n- **Middleware-First Architecture**  \n  Everything is a middleware even if they are not a middleware they produce a middleware in the end.  \n\n- **Easy State Management Using Context**  \n  Recently implemented the Context API that makes it very easy to manage state without the use of Extractors/Macros.  \n\n- **Feel of Async Without Async**  \n  Feather is Multithreaded by default running on **Feather-Runtime**.\n  \n- **Great Tooling Out Of the Box**  \n  With the use of the [Feather-CLI](https://github.com/BersisSe/feather-cli/tree/main) creating API's and Web Servers becomes a _Breeze_.\n\n## How it works behind the scenes:  \nEvery Request given a thread from the Server's threadpool and that thread is responsible for returning the a response to that request.  \nSo you can Run long running task's on another thread in the middlewares but the response can only be returned from the middleware the request is accepted on.  \nIf you want to go deeper take look at [Feather-Runtime](./crates/feather-runtime)  \n\n---\n\n## Getting Started\n\nAdd Feather to your `Cargo.toml`:\n\n```toml\n[dependencies]\nfeather = \"~0.5\"\n```\n\n---\n\n## Quick Example\n\n```rust\nuse feather::middleware::builtins;\nuse feather::{App, AppContext, next};\nuse feather::{Request, Response};\nfn main() {\n    let mut app = App::new();\n    app.get(\"/\", |_request: \u0026mut Request, response: \u0026mut Response, _ctx: \u0026mut AppContext| {\n        response.send_text(\"Hello, world!\");\n        next!()\n    });\n    \n    app.use_middleware(builtins::Logger);\n    app.listen(\"127.0.0.1:5050\");\n}\n```\n\nThat’s all — no async.\n\n---\n\n## Middleware in Feather\n\nMiddleware is intented to be the heart of Feather. You may write it as a closure, a struct, or chain them together:\n\n```rust,no_run\nuse feather::{App, AppContext, Request, Response,next,Outcome};\nuse feather::middleware::builtins;\nuse feather::middleware::{Middleware, MiddlewareResult};\n\n// Implementors of the Middleware trait are middleware that can be used in a Feather app.\nstruct Custom;\n\nimpl Middleware for Custom {\n    fn handle(\u0026self, request: \u0026mut Request, _response: \u0026mut Response, _ctx: \u0026mut AppContext) -\u003e Outcome {\n      println!(\"Now running some custom middleware (struct Custom)!\");\n      println!(\"And there's a request with path: {:?}\", request.uri);\n      next!()\n    }\n}\n\nfn main() {\n    let mut app = App::new();\n    app.use_middleware(builtins::Logger);\n    app.use_middleware(Custom);\n    app.use_middleware(|_req: \u0026mut Request, _res: \u0026mut Response, _ctx: \u0026mut AppContext| {\n        println!(\"Now running some custom middleware (closure)!\");\n        next!()\n    });\n\n    app.get(\"/\",|_req: \u0026mut Request, res: \u0026mut Response, _ctx: \u0026mut AppContext| {\n        res.send_text(\"Hello, world!\");\n        next!()\n    });\n\n    app.listen(\"127.0.0.1:5050\");\n}\n```\n---\n\n## State Management using the Context API\n\nFeather's new Context API allows you to manage application-wide state without extractors or macros.\n\nAs an example:\n\n```rust,no_run\nuse feather::{next, App, AppContext, Request, Response};\n// Create a couter struct to hold the state\n#[derive(Debug)]\nstruct Counter {\n    pub count: i32,\n}\nfn main() {\n    let mut app = App::new();\n    let counter = Counter { count: 0 };\n    app.context().set_state(counter);\n\n    app.get(\"/\",move |_req: \u0026mut Request, res: \u0026mut Response, ctx: \u0026mut AppContext| {\n      let counter: \u0026mut Counter = ctx.get_mut_state::\u003cCounter\u003e().unwrap();\n      counter.count += 1;\n      res.send_text(format!(\"Counted! {}\", counter.count));\n      next!()\n    });\n    // Lastly add a route to get the current count\n    app.get(\"/count\",move |_req: \u0026mut Request, res: \u0026mut Response, ctx: \u0026mut AppContext| {\n      let counter = ctx.get_state::\u003cCounter\u003e().unwrap();\n      res.send_text(counter.count.to_string());\n      next!()\n    });\n    app.listen(\"127.0.0.1:5050\");\n}\n\n```\n\nContext is especially useful when needing to access databases and files.\n\n## Built-in JWT Authentication\n\nFeather has a native JWT module activated using a cargo feature `jwt`:\n\n```toml\n[dependencies]\nfeather = { version = \"0.3.1\", features = [\"jwt\"] }\n```\n\n```rust,no_run\nuse feather::jwt::{generate_jwt, with_jwt_auth};\nuse feather::{App, AppContext,next};\n\nfn main() {\n    let mut app = App::new();\n    app.get(\"/auth\",with_jwt_auth(\"secretcode\", |_req, res,_ctx, claim| {\n        println!(\"Claim: {:?}\", claim);\n        res.send_text(\"Hello, JWT!\");\n        next!()\n      }),\n    );\n    // Check the JWT Example for a more complete version!\n    app.listen(\"127.0.0.1:8080\")\n}\n```\n\n---\n\n## Goals\n\n- Being the simplest Rust web framework to get started with\n- Being modular and easy to extend\n- Focusing on DX without sacrificing Rust's safety and performance\n\n---\n\n## Contributing\n\nPRs are welcome!  \nIf you have ideas or bugs, please [open an issue]([https://github.com/BersisSe/feather/issues) or submit a pull request.\n\n```bash\n# Getting started with dev\ngit clone https://github.com/BersisSe/feather.git\ncd feather\ncargo run --example app\n```\n\n---\n\n## License\n\nFeather is MIT licensed. See [LICENSE](./LICENSE).\n\n---\n\n## Acknowledgments\n\nFeather is inspired by [Express.js](https://expressjs.com) and exists to bring that same productivity to Rust.\n\n---\n\n## Spread the Word\n\nIf you like Feather:\n\n- ⭐ Star it on [GitHub](https://github.com/BersisSe/feather),\n- If you can Maybe buy me a Coffee [Here](https://buymeacoffee.com/bersisse)!\n- Share it on Reddit, HN, or Discord\n- Build something and show up!\n\n---\n","funding_links":["https://buymeacoffee.com/bersisse)!"],"categories":["Rust","\u003ca name=\"Rust\"\u003e\u003c/a\u003eRust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBersisSe%2Ffeather","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FBersisSe%2Ffeather","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBersisSe%2Ffeather/lists"}