Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Your First Handler

This guide explains the structure of a handler and how to work with requests and responses.

Handler Structure

Every handler follows the same pattern:

#![allow(unused)]
fn main() {
use rust_edge_gateway_sdk::prelude::*;

fn handle(req: Request) -> Response {
    // Your logic here
    Response::ok(json!({"status": "success"}))
}

handler_loop!(handle);
}

The Prelude

The prelude module imports everything you typically need:

#![allow(unused)]
fn main() {
use rust_edge_gateway_sdk::prelude::*;

// This imports:
// - Request, Response types
// - serde::{Deserialize, Serialize}
// - serde_json::{json, Value as JsonValue}
// - read_request, send_response IPC functions
// - HandlerError for error handling
}

The Handler Function

Your handler function receives a Request and returns a Response:

#![allow(unused)]
fn main() {
fn handle(req: Request) -> Response {
    // Access request data
    let method = &req.method;  // "GET", "POST", etc.
    let path = &req.path;      // "/users/123"
    
    // Return a response
    Response::ok(json!({"received": path}))
}
}

The Handler Loop Macro

The handler_loop! macro sets up the main function and IPC loop:

handler_loop!(handle);

// This expands to:
fn main() {
    loop {
        match read_request() {
            Ok(req) => {
                let response = handle(req);
                send_response(response).unwrap();
            }
            Err(_) => break,
        }
    }
}

Working with Requests

Accessing the Body

For POST/PUT requests, parse the JSON body:

#![allow(unused)]
fn main() {
#[derive(Deserialize)]
struct CreateUser {
    name: String,
    email: String,
}

fn handle(req: Request) -> Response {
    // Parse JSON body
    let user: CreateUser = match req.json() {
        Ok(u) => u,
        Err(e) => return Response::bad_request(format!("Invalid JSON: {}", e)),
    };
    
    Response::created(json!({
        "id": "new-user-id",
        "name": user.name,
        "email": user.email,
    }))
}
}

Path Parameters

Extract dynamic path segments (e.g., /users/{id}):

#![allow(unused)]
fn main() {
fn handle(req: Request) -> Response {
    let user_id = req.path_param("id")
        .ok_or_else(|| "Missing user ID")?;
    
    Response::ok(json!({"user_id": user_id}))
}
}

Query Parameters

Access query string values (e.g., ?page=1&limit=10):

#![allow(unused)]
fn main() {
fn handle(req: Request) -> Response {
    let page = req.query_param("page")
        .map(|s| s.parse::<u32>().unwrap_or(1))
        .unwrap_or(1);
    
    let limit = req.query_param("limit")
        .map(|s| s.parse::<u32>().unwrap_or(10))
        .unwrap_or(10);
    
    Response::ok(json!({
        "page": page,
        "limit": limit,
    }))
}
}

Headers

Access HTTP headers (case-insensitive):

#![allow(unused)]
fn main() {
fn handle(req: Request) -> Response {
    let auth = req.header("Authorization");
    let content_type = req.header("Content-Type");
    
    if auth.is_none() {
        return Response::json(401, json!({"error": "Unauthorized"}));
    }
    
    Response::ok(json!({"authenticated": true}))
}
}

Working with Responses

JSON Responses

The most common response type:

#![allow(unused)]
fn main() {
// 200 OK with JSON
Response::ok(json!({"status": "success"}))

// 201 Created
Response::created(json!({"id": "123"}))

// Custom status with JSON
Response::json(418, json!({"error": "I'm a teapot"}))
}

Error Responses

Built-in error response helpers:

#![allow(unused)]
fn main() {
Response::bad_request("Invalid input")      // 400
Response::not_found()                        // 404
Response::internal_error("Something broke")  // 500
}

Custom Headers

Add headers to any response:

#![allow(unused)]
fn main() {
Response::ok(json!({"data": "value"}))
    .with_header("X-Custom-Header", "custom-value")
    .with_header("Cache-Control", "max-age=3600")
}

Text Responses

For non-JSON responses:

#![allow(unused)]
fn main() {
Response::text(200, "Hello, World!")
Response::text(200, "<html><body>Hello</body></html>")
    .with_header("Content-Type", "text/html")
}

Next Steps