Crates.io | cargo-swim |
lib.rs | cargo-swim |
version | 0.2.1 |
source | src |
created_at | 2023-02-03 16:24:54.645129 |
updated_at | 2023-02-03 22:22:45.314622 |
description | Cargo subcommand for interacting with the swim web framework |
homepage | https://github.com/SyedAhkam/swim |
repository | https://github.com/SyedAhkam/swim |
max_upload_size | |
id | 775716 |
size | 6,273 |
An opinionated batteries-included approach to a rust web framework.
The idea is to take the best parts of the rust ecosystem and combine them into a framework that is easy to use and provides a good developer experience.
Add the following to your Cargo.toml
file.
[dependencies]
swim = "0.2"
You define a project by defining a struct that implements the Project
trait. It is the highest-level abstraction in the framework. It is responsible for defining the settings, apps, and middleware for your project.
use swim::prelude::*;
struct MyProject;
impl Project for MyProject {
fn settings(&self) -> Settings {
Settings::builder()
.extend_ron(relative! ("settings.ron"))
.build()
}
fn apps(&self) -> Vec<Box<dyn App>> {
vec! [
MyApp.into()
]
}
fn middleware(&self) -> Vec<Box<dyn Middleware>> {
vec! [
MyMiddleware.into()
]
}
}
You define an app by defining a struct that implements the App
trait. It is responsible for defining the routes and views for your app.
use swim::prelude::*;
struct MyApp;
impl App for MyApp {
fn mount(&self) -> &'static str {
"/"
}
fn config(&self) -> AppConfig {
AppConfig::with_name("MyApp")
}
fn models(&self) -> Vec<Box<dyn Model>> {
vec! []
}
fn routes(&self) -> Vec<Route> {
vec! [
Route::new("/", IndexView),
Route::new("/hello", HelloView),
Route::new("/greeting/:name", GreetingView),
]
}
}
You define a view by defining a struct that implements the View
trait. It is responsible for handling the request and returning a response. You can implement the specific HTTP methods you want to handle.
#[derive(Debug)]
pub struct HelloView;
#[async_trait::async_trait]
impl View for HelloView {
async fn get(&self, request: Request<Body>) -> Result<Response<Body>> {
Ok(Response::builder()
.status(StatusCode::OK)
.body(Body::from("Say hello to Swim! "))
.unwrap())
}
async fn post(&self, request: Request<Body>) -> Result<Response<Body>> {
Ok(Response::builder()
.status(StatusCode::OK)
.body(Body::from("It's a post request! "))
.unwrap())
}
}
You define a middleware by defining a struct that implements the Middleware
trait. It is responsible for handling the request and returning a response. You can implement the specific HTTP methods you want to handle.
#[derive(Debug)]
pub struct Logger;
#[async_trait::async_trait]
impl Middleware for Logger {
async fn pre(&self, request: Request<Body>) -> Result<Request<Body>> {
println! ("New request: {:?}", request.uri());
Ok(request)
}
async fn post(&self, response: Response<Body>) -> Result<Response<Body>> {
println! ("Response: {:?}", response.status());
Ok(response)
}
}
You may use the elegant swim macro to run your project.
#[tokio::main(flavor = "multi_thread")]
async fn main() {
swim! (MyProject, host = "localhost", port = 8000);
}
The device has been built, but the batteries are not yet included.
Feel free to open an issue or a PR if you have any ideas or suggestions. This project is all about new ideas and making the developer experience better.