sword 0.1.1

Axum based web framework prototype
Documentation

๐Ÿšง Prototype Status

This is a prototype and not production-ready. It is intended for:

  • ๐Ÿ“š Educational purposes
  • ๐Ÿ”ฌ Exploring web framework design
  • ๐Ÿ› ๏ธ Axum wrapper experimentation

While it may scale well in the future, it is not recommended for production use at this stage.


โœจ Features

  • ๐Ÿ›ฃ๏ธ Macro-based routing - Clean and intuitive route definitions
  • ๐Ÿ” Complex query parameters - Ready for advanced parameter handling
  • ๐Ÿ“„ JSON-first design - Built with JSON formats as priority
  • โœ… Built-in validation - Support with serde and validator crates
  • ๐ŸŒ RFC-compliant HTTP responses - Using axum_responses crate
  • ๐Ÿ’ก Express-Like - It provides a req from request with some utility methods.

๐Ÿ› ๏ธ Usage

Basic web server

use sword::prelude::*;

#[controller("/")]
struct AppController {}

#[controller_impl]
impl AppController {
    #[get("/")]
    async fn get_data() -> HttpResponse {
        let data = vec![
            "This is a basic web server",
            "It serves static data",
            "You can extend it with more routes",
        ];

        HttpResponse::Ok().data(data)
    }

    #[get("/hello")]
    async fn hello() -> HttpResponse {
        HttpResponse::Ok().data("Hello, World!")
    }

    #[post("/submit")]
    async fn submit_data(req: Request) -> Result<HttpResponse> {
        let body = req.body::<serde_json::Value>()?;

        Ok(HttpResponse::Ok()
            .data(body)
            .message("Data submitted successfully"))
    }
}

#[tokio::main]
async fn main() {
    Application::builder()
        .controller::<AppController>()
        .run("0.0.0.0:8080")
        .await;
}

With Middleware

use serde_json::json;
use std::sync::{Arc, OnceLock};
use sword::prelude::*;
use tokio::sync::RwLock;

type InMemoryDb = Arc<RwLock<Vec<String>>>;
const IN_MEMORY_DB: OnceLock<InMemoryDb> = OnceLock::new();

fn db() -> Arc<RwLock<Vec<String>>> {
    IN_MEMORY_DB
        .get_or_init(|| Arc::new(RwLock::new(Vec::new())))
        .clone()
}

#[derive(Clone)]
struct AppState {
    db: InMemoryDb,
}

struct MyMiddleware;

impl MiddlewareWithState<AppState> for MyMiddleware {
    async fn handle(ctx: State<AppState>, mut req: Request, next: Next) -> MiddlewareResult {
        let count = ctx.db.read().await.len();
        req.extensions.insert(count);

        Ok(next.run(req.into()).await)
    }
}

#[controller("/api")]
struct AppController {}

#[controller_impl]
impl AppController {
    #[get("/data")]
    #[middleware(MyMiddleware)]
    async fn submit_data(state: State<AppState>, req: Request) -> HttpResponse {
        let db = &state.db;
        let count = req.extensions.get::<usize>().cloned().unwrap_or(0);
        let message = format!("Current data count: {}", count);

        db.write().await.push(message);

        HttpResponse::Ok().data(json!({
            "count": count,
            "current_data": db.read().await.clone(),
        }))
    }
}

#[tokio::main]
async fn main() {
    let app_state = AppState { db: db() };

    Application::builder()
        .state(app_state)
        .controller::<AppController>()
        .run("0.0.0.0:8080")
        .await;
}

Currently working on

  • โœ…๐Ÿ“ฑ Add Application struct
  • โœ… ๐Ÿ—๏ธ Add Application Context
  • โœ… ๐Ÿ”’ Add Middleware support
  • ๐Ÿ’‰ Add Dependency Injection support based on shaku crate

๐Ÿ“‹ Roadmap

  • โš™๏ธ Add config file support
  • ๐Ÿ“ Add File - FormData support
  • ๐Ÿงช Add more tests
  • ๐Ÿ“š Add more documentation
  • ๐Ÿ› ๏ธ CLI Command line interface for code-generation (templates)