Skip to main content
Version: 0.5.x

Routing

Routing is a fundamental concept in web applications. In Ngyn, routing allows you to define how your application responds to client requests to specific endpoints. This guide covers everything you need to know about routing in Ngyn.

Basic Routing

In Ngyn, you can define routes using HTTP method functions on your application instance:

use ngyn::prelude::*;

#[handler]
fn hello() -> &'static str {
"Hello, World!"
}

#[tokio::main]
async fn main() {
let mut app = HyperApplication::default();

// Register a route for GET requests to "/hello"
app.get("/hello", hello);

let _ = app.listen("127.0.0.1:3000").await;
}

Ngyn supports all standard HTTP methods:

// GET request
app.get("/users", get_users);

// POST request
app.post("/users", create_user);

// PUT request
app.put("/users/{id}", update_user);

// DELETE request
app.delete("/users/{id}", delete_user);

// PATCH request
app.patch("/users/{id}", partial_update_user);

// HEAD request
app.head("/status", check_status);

// OPTIONS request
app.options("/users", get_options);

Route Parameters

You can define dynamic route parameters using curly braces {} in your route patterns:

use ngyn::prelude::*;

#[handler]
fn get_user(param: Param) -> String {
let user_id = param.get("id").unwrap_or("unknown");
format!("User ID: {}", user_id)
}

#[tokio::main]
async fn main() {
let mut app = HyperApplication::default();

// Register a route with a parameter
app.get("/users/{id}", get_user);

let _ = app.listen("127.0.0.1:3000").await;
}

When a request is made to /users/123, the id parameter will be set to 123.

Query Parameters

You can access query parameters using the Query struct:

use ngyn::prelude::*;

#[handler]
fn search(query: Query) -> String {
let term = query.get("term").unwrap_or("empty");
format!("Search term: {}", term)
}

#[tokio::main]
async fn main() {
let mut app = HyperApplication::default();

app.get("/search", search);

let _ = app.listen("127.0.0.1:3000").await;
}

When a request is made to /search?term=ngyn, the term query parameter will be set to ngyn.

Route Groups

You can group routes with a common prefix using the group method:

use ngyn::prelude::*;

#[handler]
fn list_users() -> &'static str {
"List of users"
}

#[handler]
fn get_user(param: Param) -> String {
let user_id = param.get("id").unwrap_or("unknown");
format!("User ID: {}", user_id)
}

#[handler]
fn create_user() -> &'static str {
"User created"
}

#[tokio::main]
async fn main() {
let mut app = HyperApplication::default();

// Group routes under "/api/users"
app.group("/api/users", |group| {
group.get("", list_users); // Matches "/api/users"
group.get("/{id}", get_user); // Matches "/api/users/123"
group.post("", create_user); // Matches "/api/users"
});

let _ = app.listen("127.0.0.1:3000").await;
}

Wildcard Routes

You can use wildcards in your routes to match multiple paths:

use ngyn::prelude::*;

#[handler]
fn handle_any() -> &'static str {
"Matched any route"
}

#[tokio::main]
async fn main() {
let mut app = HyperApplication::default();

// Match any route
app.any("*", handle_any);

// Match any route under /api
app.any("/api/*", handle_any);

let _ = app.listen("127.0.0.1:3000").await;
}

Route Handlers

Route handlers in Ngyn can be defined in several ways:

Function Handlers

The simplest way is to define a function and mark it with the #[handler] attribute:

#[handler]
fn hello() -> &'static str {
"Hello, World!"
}

Async Handlers

You can also define async handlers for operations that need to be asynchronous:

#[handler]
async fn fetch_data() -> String {
// Simulate an async operation
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
"Data fetched".to_string()
}

Handlers with Context

For more complex scenarios, you can access the request context:

#[handler]
fn with_context(ctx: NgynContext) -> String {
let path = ctx.request().uri().path();
format!("Request path: {}", path)
}

Error Handling

Handlers can return Result types to handle errors gracefully:

#[handler]
fn might_fail() -> Result<String, String> {
// Simulate a condition that might fail
if rand::random::<bool>() {
Ok("Success!".to_string())
} else {
Err("Something went wrong".to_string())
}
}

For more advanced routing scenarios, check out the examples in the Ngyn repository.