# Http Actix Axum

> >

- **Type:** Skill
- **Install:** `agentstack add skill-pedromneto97-custom-skills-http-actix-axum`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [pedromneto97](https://agentstack.voostack.com/s/pedromneto97)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [pedromneto97](https://github.com/pedromneto97)
- **Source:** https://github.com/pedromneto97/custom-skills/tree/main/skills/http-actix-axum

## Install

```sh
agentstack add skill-pedromneto97-custom-skills-http-actix-axum
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# HTTP Best Practices — actix-web / axum

## 1. Resource Naming

| Rule | Good | Bad |
|------|------|-----|
| Plural nouns | `/orders`, `/users` | `/order`, `/getOrders` |
| Lowercase + hyphens | `/order-items` | `/orderItems`, `/Order_Items` |
| Hierarchical nesting | `/orders/{id}/items` | `/order-items?orderId={id}` |
| No verbs in path | `POST /orders` | `POST /createOrder` |
| Filter / sort in query | `/orders?status=pending&sort=created_at` | `/pending-orders` |

Max nesting depth: **2 levels** (`/resource/{id}/sub-resource`). Avoid deeper hierarchies.

---

## 2. API Versioning

Prefix at the router level. Handlers are version-agnostic.

**actix-web**
```rust
// inbound/src/http/router.rs
pub fn configure(cfg: &mut web::ServiceConfig) {
    cfg.service(
        web::scope("/api/v1")
            .service(web::scope("/orders")
                .route("",      web::get().to(list))
                .route("",      web::post().to(create))
                .route("/{id}", web::get().to(get_one))
                .route("/{id}", web::put().to(update))
                .route("/{id}", web::delete().to(delete)),
            ),
    );
}
```

**axum**
```rust
// inbound/src/http/router.rs
pub fn build_router() -> Router {
    Router::new()
        .nest("/api/v1", Router::new()
            .nest("/orders", Router::new()
                .route("/",    get(list).post(create))
                .route("/:id", get(get_one).put(update).delete(delete)),
            ),
        )
}
```

---

## 3. HTTP Status Codes

| Operation | Method | Success | Error cases |
|-----------|--------|---------|-------------|
| Fetch one | GET | 200 | 404 if not found |
| Fetch list | GET | 200 | Empty list → 200 `[]`, never 404 |
| Create | POST | 201 + `Location` header | 400, 422 |
| Full replace | PUT | 200 | 404, 422 |
| Partial update | PATCH | 200 | 404, 422 |
| Delete | DELETE | 204 No Content | 404 |
| Async action | POST | 202 Accepted | — |
| Bad input | — | 400 Bad Request | — |
| Unauthenticated | — | 401 Unauthorized | — |
| Forbidden | — | 403 Forbidden | — |
| Conflict (duplicate) | — | 409 Conflict | — |
| Business rule violated | — | 422 Unprocessable Entity | — |
| Server fault | — | 500 Internal Server Error | Never leak stack traces |

```rust
// 201 + Location (actix-web)
HttpResponse::Created()
    .insert_header(("Location", format!("/api/v1/orders/{}", order.id)))
    .json(OrderResponse::from(order))

// 201 + Location (axum)
(StatusCode::CREATED, [("Location", format!("/api/v1/orders/{}", order.id))], Json(body))
```

---

## 4. Error Responses — Problem Details (RFC 9457)

→ Read [`references/problem-details.md`](./references/problem-details.md) for the full struct,
`ResponseError` / `IntoResponse` impl, `From`, and validation error mapping.

Quick rules:
- `Content-Type: application/problem+json`
- `type` is a URI; use `"about:blank"` when no dedicated error page exists
- Never expose stack traces, internal IDs, or DB details in `detail`
- Convert framework extractor errors (JSON/query/path) into sanitized Problem Details

---

## 5. Security Headers (OWASP)

→ Read [`references/security-headers.md`](./references/security-headers.md) for middleware
implementation (actix-web `Transform` + axum `tower-http` layer).

Mandatory headers on every response:

| Header | Value |
|--------|-------|
| `X-Content-Type-Options` | `nosniff` |
| `X-Frame-Options` | `DENY` |
| `Referrer-Policy` | `strict-origin-when-cross-origin` |
| `Content-Security-Policy` | `default-src 'self'` *(tune per app)* |
| `Permissions-Policy` | `geolocation=(), microphone=(), camera=()` |
| `Strict-Transport-Security` | `max-age=31536000; includeSubDomains` *(HTTPS only)* |

Remove `Server` and `X-Powered-By` response headers.

---

## 6. CORS

→ Read [`references/cors.md`](./references/cors.md) for full configuration.

Decision guide:

| Scenario | Strategy |
|----------|----------|
| Public API, no cookies | `allow_any_origin()` |
| Cookie-auth / credentialed | Explicit origin allowlist + `allow_credentials(true)` |

> **Never** combine `allow_any_origin()` with `allow_credentials(true)` — browsers reject it.

For cookie/session auth, combine CORS policy with cookie security (`Secure`, `HttpOnly`,
`SameSite`) and an explicit origin allowlist.

---

## 7. Response Compression

→ Read [`references/compression.md`](./references/compression.md) for middleware setup.

- Priority order: **Brotli → gzip → deflate** (auto-negotiated from `Accept-Encoding`)
- Skip already-compressed content: images (jpeg/png/gif/webp), video, `application/zip`, `application/pdf`
- Skip small responses:  for ApiError`.

→ Read [`references/problem-details.md`](./references/problem-details.md) for the `From` impl and the domain-validation bridge pattern.

**actix-web**
```rust
#[derive(Deserialize, Validate)]
#[serde(rename_all = "camelCase")]
pub struct CreateOrderRequest {
    #[validate(length(min = 1, max = 100))]
    pub customer_name: String,
    #[validate(email)]
    pub email: String,
}

pub async fn create_order(
    state: web::Data>,
    body: web::Json,
) -> Result {
    body.validate()?; // ValidationErrors → ApiError via From impl → 400 Problem Detail
    let order = orders::create_order(&state.repo, body.into_inner().into()).await?;
    Ok(HttpResponse::Created()
        .insert_header(("Location", format!("/api/v1/orders/{}", order.id)))
        .json(OrderResponse::from(order)))
}
```

---

## 9. Custom Extractors

Use typed request extractors (`FromRequest` in actix-web, `FromRequestParts` in axum) for
cross-cutting concerns like auth claims, tenant context, and request-scoped metadata.

→ Read [`references/extractors.md`](./references/extractors.md).

---

## 10. OpenAPI / Swagger

Keep handlers transport-focused and annotate route contracts where possible.
Expose docs routes conditionally (often only in non-production/debug builds).

→ Read [`references/openapi.md`](./references/openapi.md).

**Domain-validation bridge** (when domain owns the rules):
```rust
use validator::ValidationError;
use domain::use_cases::validate_customer_name; // pure domain fn → Vec

fn customer_name_valid(val: &str) -> Result {
    match validate_customer_name(val) {
        Ok(_) => Ok(()),
        Err(errors) => {
            let mut e = ValidationError::new("customer_name")
                .with_message("Invalid customer name".into());
            e.add_param("errors".into(), &errors);
            Err(e)
        }
    }
}

#[derive(Deserialize, Validate)]
pub struct CreateOrderRequest {
    #[validate(custom(function = "customer_name_valid"))]
    pub customer_name: String,
}
```

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [pedromneto97](https://github.com/pedromneto97)
- **Source:** [pedromneto97/custom-skills](https://github.com/pedromneto97/custom-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-pedromneto97-custom-skills-http-actix-axum
- Seller: https://agentstack.voostack.com/s/pedromneto97
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
