22 unstable releases (3 breaking)
Uses new Rust 2024
new 0.4.7 | Apr 17, 2025 |
---|---|
0.4.6 | Apr 11, 2025 |
0.3.3 | Apr 2, 2025 |
0.3.2 | Mar 26, 2025 |
0.1.3 | Feb 26, 2025 |
#197 in HTTP server
1,901 downloads per month
155KB
3K
SLoC
Starberry Web Framework
Small, sweet, easy framework for full-stack Rust web applications
📋 Overview
Starberry is a lightweight, intuitive web framework focused on simplicity and productivity. It supports regex-based routing, tree-structured URLs, and integrates seamlessly with the Akari templating system.
✨ Key Features
- Simple API: Intuitive request/response handling with minimal boilerplate
- Full-Stack: Built-in template rendering with Akari templates
- Flexible Routing: Support for regex patterns, literal URLs, and nested routes
- Asynchronous: Built with Tokio for efficient async handling
- Form Handling: Easy processing of form data and file uploads
- Middleware Support: Create reusable request processing chains
🚀 Getting Started
Installation
Install starberry bu using
cargo install starberry
After installing starberry, use
starberry new <Proj_name>
To create a new project
Quick Start
use starberry::prelude::*;
#[tokio::main]
async fn main() {
APP.clone().run().await;
}
pub static APP: SApp = Lazy::new(|| {
App::new().build()
});
#[lit_url(APP, "/")]
async fn home_route() -> HttpResponse {
text_response("Hello, world!")
}
Visit your server at http://localhost:3003
Project Structure
project/
├── src/
│ ├── main.rs
│ ├── lib.rs
│ └── ...
└── templates/
├── base.html
├── index.html
└── ...
Templates are automatically copied to the dist
directory when you run starberry build
.
📝 Usage Guide
URL Registration
Method 1: Using Macros (Recommended)
// Absolute URL
#[url(APP.lit_url("/random/split/something"))]
async fn random_route() -> HttpResponse {
text_response("A random page")
}
// Relative URL with parent
#[url(reg![&APP, LitUrl("hello")])]
async fn hello() -> HttpResponse {
text_response("Hello, world!")
}
Method 2: Dynamic Registration
let furl = APP.clone().reg_from(&[LitUrl("flexible"), LitUrl("url")]);
furl.set_method(Arc::new(flexible_access));
URL Pattern Types
Type | Description | Example |
---|---|---|
LitUrl(&str) |
Matches literal path segment | LitUrl("users") |
RegUrl(&str) |
Matches regex pattern | RegUrl("[0-9]+") |
AnyUrl |
Matches any single path segment | AnyUrl |
AnyDir |
Matches any number of path segments | AnyDir |
Request Handling
#[url(APP.lit_url("/submit"))]
async fn handle_form() -> HttpResponse {
if request.method() == POST {
// Form data (application/x-www-form-urlencoded)
let form = req.form_or_default().await;
// Access form fields
let name = form.get_or_default("name");
let age = form.get_or_default("age");
// File uploads
if let Some(files) = request.files().await {
if let Some(file) = files.get("file") {
// Process file
let file_data = file.data().unwrap();
// ...
}
}
return akari_json!({
name: form.get_or_default("name"),
age: form.get_or_default("age")
});
}
text_response("Method not allowed").with_status(405)
}
Templating
#[url(APP.lit_url("/template"))]
async fn template() -> HttpResponse {
akari_template!(
"template.html",
title="My Website - Home",
page_title="Welcome to My Website",
show_message=true,
message="Hello, world!",
items=[1, 2, 3, 4, 5]
)
}
Template Example:
-[ template "base.html" ]-
-[ block head ]-
<link rel="stylesheet" href="style.css">
<meta name="description" content="My awesome page">
-[ endblock ]-
-[ block content ]-
<div class="container">
<h2>-[ page_title ]-</h2>
-[ if show_message ]-
<div class="message">-[ message ]-</div>
-[ endif ]-
<ul class="items">
-[ for item items ]-
<li class="item">-[ item ]-</li>
-[ endfor ]-
</ul>
</div>
-[ endblock ]-
Working with Cookies
#[url(APP.lit_url("/cookie"))]
async fn set_cookie() -> HttpResponse {
text_response("Cookie Set").add_cookie(
Cookie::new("global_cookie", "something").path("/")
)
}
JSON Responses
#[url(APP.lit_url("/api/data"))]
async fn api_data() -> HttpResponse {
akari_json!({
success: true,
data: {
id: 1,
name: "Example",
values: [10, 20, 30]
}
})
}
Redirects
#[url(APP.lit_url("/redirect"))]
async fn redirect() -> HttpResponse {
redirect_response("/new-location")
}
📋 Changelog
0.4.7 (Latest stable)
0.4.5
- Updates with tokio, enable m:n scaling
- Graceful shutdown enabled
- Better URL reg macro
- Debugging in Build mode
- Important Syntax Change: You now must use
.await
afterRc.form
,Rc.json
orRc.file
0.4.4
- Enable early return if request doesn't match allowed method
- Bug fix: The blank project will no longer use old syntax
starberry version
implemented
0.4.3
- Enable passing arguments and locals into Rc
0.4.2
- Rc is used to send the response
- Request body will not be automatically parsed
- Important Syntax Update: Middleware chain passes request context
0.4.1
- Updated middleware syntax
0.4.0
- Wrap the Request with Request context struct
- Change the name preload into prelude
- Important syntax update: Accept Rc as argument instead of HttpRequest
0.3.x and earlier
- Added Akari templating support
- Added cookie manipulation
- File upload handling
- Form data processing improvements
🔮 Planned Updates
- Standard middleware library (OAuth)
- Better URL configuration
- URL registering macros
- m:n thread scale
- Early abort
📚 Learn More
Learn more about Akari template: https://crates.io/crates/akari
📄 License
MIT License
Dependencies
~7–14MB
~176K SLoC