sword-macros 0.1.7

Axum based web framework prototype macros (sword crate)
Documentation
<div align="center">
<img src="https://pillan.inf.uct.cl/~lrevillod/images/sword-logo.png" alt="Sword Logo" width="200">

<h1>⚔️ Sword ⚔️</h1>
<p><em>Rust web framework</em></p>
</div>

## ✨ Features

- 🛣️ **Macro-based routing** - Clean and intuitive route definitions
- 📄 **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 `Context` object with utility methods for request handling
- �💉 **Dependency Injection** - Built-in DI support using `shaku` crate
- 🧩 **Middleware support** - Easily add middleware to routes or controllers
- 🚀 **Asynchronous by default** - Built on top of `axum` and `tokio`

## 🛠️ Usage

### Add to your `Cargo.toml`

```toml
[dependencies]
sword = "0.1.7"
tokio = { version = "1.47.1", features = ["full"] }

# validation features:
validator = { version = "0.20.0", features = ["derive"] }

# JSON handling features:
serde = { version = "*", features = ["derive"] }
serde_json = "*"

# OPTIONAL: If you want to use dependency injection features
shaku = { version = "0.6.2", features = ["derive"] }
async-trait = "0.1.88"
```

### Basic web server 

```rust
use sword::prelude::*;
use sword::web::HttpResult;

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

#[routes]
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(ctx: Context) -> HttpResult<HttpResponse> {
        let body = ctx.body::<serde_json::Value>()?;

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

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    Application::builder()?
        .controller::<AppController>()
        .run("0.0.0.0:8080")
        .await?;

    Ok(())
}
```
### With Middleware

```rust
use serde_json::json;
use sword::prelude::*;
use sword::web::HttpResult;

struct LoggingMiddleware;

impl Middleware for LoggingMiddleware {
    async fn handle(mut ctx: Context, next: Next) -> MiddlewareResult {
        println!("Request: {} {}", ctx.method(), ctx.uri());
        
        ctx.extensions.insert::<String>("middleware_data".to_string());

        next!(ctx, next)
    }
}

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

#[routes]
impl AppController {
    #[get("/hello")]
    #[middleware(LoggingMiddleware)]
    async fn hello(ctx: Context) -> HttpResult<HttpResponse> {
        let middleware_data = ctx.extensions
            .get::<String>()
            .cloned()
            .unwrap_or_default();

        Ok(HttpResponse::Ok().data(json!({
            "message": "Hello from middleware!",
            "middleware_data": middleware_data
        })))
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    Application::builder()?
        .controller::<AppController>()
        .run("0.0.0.0:8080")
        .await?;

    Ok(())
}
```

## Known Issues
- Body size limit errors return a `400 Bad Request` instead of `413 Payload Too Large. It will be fixed in future releases.

## More Examples
See the [examples directory]./examples for more advanced usage.

## Hot reloading

In the case of use hot reloading, you need to install `dioxus-cli`:

```bash
cargo install --git https://github.com/DioxusLabs/dioxus.git dioxus-cli
```

Then run the server with:

```bash
dx serve --hot-patch --example hot_reloading
```