# Routing in Feather
Feather provides a simple, Express.js-like routing system. This guide covers everything you need to know about routing.
## Basic Routing
Define routes using HTTP method functions on the `App` struct:
```rust,ignore
use feather::App;
let mut app = App::new();
// GET request
app.post("/users", middleware!(|_req, res, _ctx| {
res.send_text("POST /users");
next!()
}));
// PUT request
app.put("/users/:id", middleware!(|_req, res, _ctx| {
res.send_text("PUT /users/:id");
next!()
}));
// DELETE request
app.delete("/users/:id", middleware!(|_req, res, _ctx| {
res.send_text("DELETE /users/:id");
next!()
}));
// PATCH request
app.patch("/items/:id", middleware!(|_req, res, _ctx| {
res.send_text("PATCH /items/:id");
next!()
}));
// HEAD request
app.head("/status", middleware!(|_req, res, _ctx| {
res.set_status(200);
next!()
}));
// OPTIONS request
app.options("/api/*", middleware!(|_req, res, _ctx| {
res.send_text("OPTIONS allowed");
next!()
}));
```
## Route Grouping via Routers
While you can define all routes on the App struct, as of Feather 0.8.0, we recommend using the Router for better organization.
This allows you to group related routes and apply middleware that only affects that specific group.
```rust,ignore
use feather::Router;
pub fn api_v1() -> Router {
let mut router = Router::new();
// This middleware only runs for routes in this router
router.use_middleware(|_req, _res, _ctx| {
println!("API v1 access");
next!()
});
router.get("/status", |_req, res, _ctx| {
res.finish_json(feather::json!({ "status": "ok" }))
});
router
}
// In your main.rs
app.mount("/api/v1", api_v1());
```
## Supported HTTP Methods
Feather supports all standard HTTP methods:
- **GET** - `app.get(path, middleware)`
- **POST** - `app.post(path, middleware)`
- **PUT** - `app.put(path, middleware)`
- **DELETE** - `app.delete(path, middleware)`
- **PATCH** - `app.patch(path, middleware)`
- **HEAD** - `app.head(path, middleware)`
- **OPTIONS** - `app.options(path, middleware)`
## Path Parameters
Extract parameters from the URL using the `:paramName` syntax:
```rust,ignore
next!()
}));
Use wildcards (`*`) to match any path structure:
```rust,ignore
// Match any path starting with /api/
app.get("/api/*", middleware!(|_req, res, _ctx| {
res.send_text("API route");
next!()
}));
// Catch-all route
app.get("/*", middleware!(|_req, res, _ctx| {
res.set_status(404);
res.send_text("Not found");
next!()
}));
```
## Accessing Request Information
Inside your middleware, use `req` to access request data:
```rust,ignore
println!("Path: {}", req.uri);
// Headers
if let Some(content_type) = req.headers.get("Content-Type") {
println!("Content-Type: {:?}", content_type);
}
// Request body
let body_bytes = &req.body;
println!("Body length: {}", body_bytes.len());
next!()
}));
```
## Status Codes and Responses
Set custom HTTP status codes:
```rust,ignore
res.set_status(403); // Forbidden
.send_text("Access denied");
next!()
}));