🦀 🦀 #api - API Endpoint Directive - Rust Edition

Rust Documentation

🦀 #api - API Endpoint Directive - Rust Edition

"We don't bow to any king" - Rust Edition

The #api directive in Rust creates RESTful API endpoints with automatic JSON serialization, deserialization, and HTTP response formatting. Built with zero-copy performance and Rust's type safety guarantees.

Basic Syntax

use tusklang_rust::{parse, ApiDirective, JsonResponse};
use serde::{Deserialize, Serialize};

// Simple API endpoint with automatic JSON serialization let api_config = r#" #api /hello { handler: "HelloController::greet" response: { message: "Hello, World!" timestamp: @now() } } "#;

// With explicit return using Rust types let users_api = r#" #api /users { handler: "UserController::index" return: @User.all() } "#;

// Implicit JSON response with Rust structs let status_api = r#" #api /status { handler: "StatusController::health" return: { status: "online" timestamp: @now() version: "1.0.0" uptime: @uptime() } } "#;

Route Parameters with Rust Types

use tusklang_rust::{ApiDirective, RouteParams};
use uuid::Uuid;

// Single parameter with type validation let user_api = r#" #api /users/{id} { handler: "UserController::show" params: { id: "uuid" } validation: { id: "required|uuid" } } "#;

// Multiple parameters with Rust path extraction let posts_api = r#" #api /posts/{year}/{month}/{day} { handler: "PostController::by_date" params: { year: "u32" month: "u8" day: "u8" } validation: { year: "required|integer|min:2020|max:2030" month: "required|integer|min:1|max:12" day: "required|integer|min:1|max:31" } } "#;

// Optional parameters with Rust Option types let search_api = r#" #api /search/{query}/{page?} { handler: "SearchController::query" params: { query: "string" page: "Option<u32>" } defaults: { page: 1 } } "#;

HTTP Methods with Rust Enums

use tusklang_rust::{ApiDirective, HttpMethod};
use actix_web::{web, HttpResponse, Responder};

#[derive(Debug, Deserialize, Serialize)] enum ApiMethod { GET, POST, PUT, DELETE, PATCH, }

// GET request (default) let get_users = r#" #api /users { method: "GET" handler: "UserController::index" response_type: "json" cache: "5m" } "#;

// POST request with validation let create_user = r#" #api /users method: POST { handler: "UserController::create" validation: { name: "required|string|max:255" email: "required|email|unique:users" password: "required|min:8|confirmed" age: "integer|min:18|max:120" } response_status: 201 } "#;

// Multiple methods with Rust pattern matching let user_crud = r#" #api /users/{id} method: [GET, PUT, DELETE] { handler: "UserController::handle" params: { id: "uuid" } switch: { GET: { cache: "2m" response_type: "json" } PUT: { validation: { name: "string|max:255" email: "email|unique:users,id" } } DELETE: { response_status: 204 require_auth: true } } } "#;

Request Handling with Rust Types

use tusklang_rust::{ApiDirective, Request, RequestData};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Deserialize)] struct ApiRequest { query: HashMap<String, String>, headers: HashMap<String, String>, body: Option<serde_json::Value>, files: HashMap<String, UploadedFile>, }

#[derive(Debug, Deserialize)] struct UploadedFile { name: String, content_type: String, size: usize, path: String, }

// Access request data with Rust types let process_api = r#" #api /process { handler: "ProcessController::handle" # Query parameters with type conversion query_params: { sort: "string|default:created_at" order: "string|default:desc|in:asc,desc" limit: "u32|default:20|max:100" page: "u32|default:1" } # Headers with validation required_headers: { authorization: "string" content_type: "string|in:application/json,multipart/form-data" } # Body validation with Rust structs body_validation: { data: "required|json" metadata: "optional|json" } # File upload handling file_validation: { document: "optional|file|max:10MB|mimes:pdf,doc,docx" image: "optional|file|max:5MB|mimes:jpg,jpeg,png" } } "#;

Response Control with Rust HTTP Types

use tusklang_rust::{ApiDirective, Response, ResponseBuilder};
use actix_web::{HttpResponse, http::StatusCode};

// Set status codes with Rust HTTP types let resource_api = r#" #api /resource/{id} { handler: "ResourceController::show" params: { id: "uuid" } responses: { 200: { description: "Resource found" schema: "Resource" } 404: { description: "Resource not found" schema: "ErrorResponse" } 500: { description: "Internal server error" schema: "ErrorResponse" } } } "#;

// Set headers with Rust header types let download_api = r#" #api /download/{file} { handler: "FileController::download" params: { file: "string" } response_headers: { "Content-Type": "application/octet-stream" "Content-Disposition": "attachment; filename=\"{file}\"" "Cache-Control": "no-cache" "X-File-Size": "@file_size(@params.file)" } response_type: "file" file_path: "@storage_path(@params.file)" } "#;

// Custom response format with Rust serialization let custom_api = r#" #api /custom { handler: "CustomController::format" response_format: "xml" response_headers: { "Content-Type": "application/xml" } transform: { data: "@to_xml(@response.data)" encoding: "UTF-8" } } "#;

Authentication with Rust Security

use tusklang_rust::{ApiDirective, AuthMiddleware, SecurityContext};
use jsonwebtoken::{decode, encode, Header, Validation, DecodingKey, EncodingKey};

// API authentication middleware let protected_api = r#" #api /protected middleware: [authenticate] { handler: "ProtectedController::data" # @user is set by authenticate middleware auth_required: true roles: ["user", "admin"] return: { message: "Welcome, " + @user.name user: @user permissions: @user.permissions } } "#;

// Inline authentication with Rust JWT let admin_api = r#" #api /admin/users { handler: "AdminController::list_users" # Check authentication auth_check: { type: "jwt" secret: @env.JWT_SECRET required: true } # Check authorization authorization: { required: true permissions: ["manage-users"] roles: ["admin"] } return: @User.all() } "#;

// Token-based auth with Rust validation let data_api = r#" #api /data { handler: "DataController::sensitive" token_auth: { header: "Authorization" prefix: "Bearer " validation: { algorithm: "HS256" secret: @env.API_SECRET required_claims: ["user_id", "exp"] } } return: @get_sensitive_data(@user.id) } "#;

Validation with Rust Validators

use tusklang_rust::{ApiDirective, Validator, ValidationRule};
use validator::{Validate, ValidationError};
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Validate)] struct UserCreateRequest { #[validate(length(min = 3, max = 50))] username: String, #[validate(email)] email: String, #[validate(length(min = 8))] password: String, #[validate(range(min = 18, max = 120))] age: Option<u8>, }

// Input validation with Rust structs let register_api = r#" #api /register method: POST { handler: "AuthController::register" validation: { username: "required|string|min:3|max:50|unique:users" email: "required|email|unique:users" password: "required|min:8|confirmed" password_confirmation: "required|same:password" age: "integer|min:18|max:120" terms_accepted: "required|boolean|accepted" } custom_validation: { username: "@validate_username_availability(@request.username)" email: "@validate_email_domain(@request.email)" password: "@validate_password_strength(@request.password)" } response_status: 201 return: { message: "User registered successfully" user: @created_user token: @generate_jwt(@created_user) } } "#;

// Custom validation rules with Rust functions let custom_validation = r#" #api /custom-validation method: POST { handler: "CustomController::validate" validation_rules: { custom_field: { required: true custom: "@validate_custom_field" message: "Custom field validation failed" } conditional_field: { required_if: "other_field == 'value'" custom: "@validate_conditional" } } } "#;

Error Handling with Rust Result Types

use tusklang_rust::{ApiDirective, ApiError, ErrorHandler};
use thiserror::Error;

#[derive(Error, Debug)] pub enum ApiError { #[error("Validation failed: {0}")] ValidationError(String), #[error("Authentication failed: {0}")] AuthError(String), #[error("Resource not found: {0}")] NotFoundError(String), #[error("Internal server error: {0}")] InternalError(String), }

// Error handling with Rust Result types let error_handling_api = r#" #api /users/{id} { handler: "UserController::show" params: { id: "uuid" } error_handling: { validation_errors: { status: 422 format: "json" schema: "ValidationErrorResponse" } not_found: { status: 404 format: "json" schema: "ErrorResponse" } auth_errors: { status: 401 format: "json" schema: "AuthErrorResponse" } server_errors: { status: 500 format: "json" schema: "ErrorResponse" log: true } } return: @User.find_or_404(@params.id) } "#;

Caching with Rust Cache Implementations

use tusklang_rust::{ApiDirective, CacheManager, CacheStrategy};
use redis::AsyncCommands;
use std::time::Duration;

// Caching strategies with Rust cache implementations let cached_api = r#" #api /users { handler: "UserController::index" cache: { strategy: "redis" ttl: "5m" key: "users:list:{@request.query.sort}:{@request.query.page}" tags: ["users", "list"] } cache_headers: { "Cache-Control": "public, max-age=300" "ETag": "@generate_etag(@response.data)" } return: @User.all() } "#;

// Conditional caching with Rust logic let conditional_cache = r#" #api /posts/{id} { handler: "PostController::show" params: { id: "uuid" } cache: { strategy: "conditional" ttl: "10m" key: "post:{@params.id}" condition: "@user.is_authenticated == false" tags: ["posts", "public"] } return: @Post.find_or_404(@params.id) } "#;

Rate Limiting with Rust Rate Limiters

use tusklang_rust::{ApiDirective, RateLimiter, RateLimitConfig};
use std::collections::HashMap;
use tokio::time::{Duration, Instant};

// Rate limiting with Rust implementations let rate_limited_api = r#" #api /api/data { handler: "DataController::fetch" rate_limit: { strategy: "sliding_window" limit: 100 window: "1h" key: "@request.ip" headers: { "X-RateLimit-Limit": "100" "X-RateLimit-Remaining": "@rate_limit_remaining" "X-RateLimit-Reset": "@rate_limit_reset" } } return: @fetch_data() } "#;

// User-based rate limiting let user_rate_limit = r#" #api /api/user-data { handler: "UserController::data" rate_limit: { strategy: "token_bucket" limit: 1000 window: "1d" key: "@user.id" burst: 50 } return: @get_user_data(@user.id) } "#;

Integration with Rust Web Frameworks

use actix_web::{web, App, HttpServer, HttpResponse};
use tusklang_rust::{ApiDirective, ActixIntegration};

// Actix-web integration async fn create_actix_app() -> App<()> { let api_directives = parse(r#" #api /api/users { handler: "UserController::index" middleware: ["auth"] cache: "5m" }

#api /api/users/{id} { handler: "UserController::show" params: { id: "uuid" } } "#)?; App::new() .configure(|cfg| { ApiDirective::configure_actix(cfg, api_directives); }) }

// Axum integration use axum::{Router, routing::get, Json}; use tusklang_rust::AxumIntegration;

async fn create_axum_app() -> Router { let api_directives = parse(r#" #api /api/users { handler: "UserController::index" response_type: "json" } "#)?; ApiDirective::create_axum_router(api_directives) }

// Rocket integration use rocket::{Rocket, Build}; use tusklang_rust::RocketIntegration;

fn create_rocket_app() -> Rocket<Build> { let api_directives = parse(r#" #api /api/users { handler: "UserController::index" } "#)?; rocket::build() .attach(ApiDirective::fairing(api_directives)) }

Testing API Directives with Rust

use tusklang_rust::{ApiDirectiveTester, TestRequest, TestResponse};
use tokio::test;
use serde_json::json;

#[tokio::test] async fn test_api_directive() { let api_directive = r#" #api /api/test { handler: "TestController::json" return: { message: "Success" data: [1, 2, 3] } } "#; let tester = ApiDirectiveTester::new(); let response = tester .test_api_directive(api_directive, "/api/test") .method("GET") .execute() .await?; assert_eq!(response.status_code, 200); assert_eq!(response.content_type, "application/json"); let body: serde_json::Value = response.json().await?; assert_eq!(body["message"], "Success"); assert_eq!(body["data"], json!([1, 2, 3])); }

#[tokio::test] async fn test_api_with_validation() { let api_directive = r#" #api /api/register method: POST { handler: "AuthController::register" validation: { email: "required|email" password: "required|min:8" } } "#; let tester = ApiDirectiveTester::new(); // Test valid request let valid_response = tester .test_api_directive(api_directive, "/api/register") .method("POST") .json(json!({ "email": "test@example.com", "password": "password123" })) .execute() .await?; assert_eq!(valid_response.status_code, 200); // Test invalid request let invalid_response = tester .test_api_directive(api_directive, "/api/register") .method("POST") .json(json!({ "email": "invalid-email", "password": "123" })) .execute() .await?; assert_eq!(invalid_response.status_code, 422); }

Performance Optimization with Rust

use tusklang_rust::{ApiDirective, PerformanceOptimizer};
use std::sync::Arc;
use tokio::sync::RwLock;

// Zero-copy API processing fn process_api_zero_copy<'a>(directive: &'a str) -> ApiDirectiveResult<ApiContext<'a>> { let context = ApiContext::from_str(directive)?; Ok(context) }

// Async API processing with Rust futures async fn process_api_async(directive: &ApiDirective) -> ApiDirectiveResult<()> { let handler = find_handler_async(&directive.handler).await?; handler.execute_async().await?; Ok(()) }

// Connection pooling for database operations let db_api = r#" #api /api/users { handler: "UserController::index" database: { pool: "default" timeout: "5s" max_connections: 10 } return: @User.all() } "#;

Security Best Practices with Rust

use tusklang_rust::{ApiDirective, SecurityValidator};
use std::collections::HashSet;

// Security validation for API directives struct ApiSecurityValidator { allowed_handlers: HashSet<String>, allowed_methods: HashSet<String>, max_payload_size: usize, required_headers: HashSet<String>, }

impl ApiSecurityValidator { fn validate_api_directive(&self, directive: &ApiDirective) -> ApiDirectiveResult<()> { // Validate handler if !self.allowed_handlers.contains(&directive.handler) { return Err(ApiError::SecurityError( format!("Handler not allowed: {}", directive.handler) )); } // Validate method if let Some(method) = &directive.method { if !self.allowed_methods.contains(method) { return Err(ApiError::SecurityError( format!("Method not allowed: {}", method) )); } } // Validate payload size if let Some(max_size) = directive.max_payload_size { if max_size > self.max_payload_size { return Err(ApiError::SecurityError( format!("Payload size too large: {}", max_size) )); } } Ok(()) } }

Best Practices for Rust API Directives

// 1. Use strong typing for API configurations
#[derive(Debug, Deserialize, Serialize)]
struct ApiDirectiveConfig {
    route: String,
    method: HttpMethod,
    handler: String,
    validation: Option<ValidationRules>,
    cache: Option<CacheConfig>,
    rate_limit: Option<RateLimitConfig>,
}

// 2. Implement proper error handling fn process_api_directive_safe(directive: &str) -> Result<ApiDirective, Box<dyn std::error::Error>> { let parsed = parse(directive)?; // Validate directive let validator = ApiSecurityValidator::new(); validator.validate_api_directive(&parsed)?; Ok(parsed) }

// 3. Use async/await for I/O operations async fn execute_api_directive_async(directive: &ApiDirective) -> ApiDirectiveResult<()> { let handler = find_handler_async(&directive.handler).await?; handler.execute_async().await?; Ok(()) }

// 4. Implement proper logging and monitoring use tracing::{info, warn, error};

fn log_api_execution(directive: &ApiDirective, result: &ApiDirectiveResult<()>) { match result { Ok(_) => info!("API directive executed successfully: {}", directive.route), Err(e) => error!("API directive execution failed: {} - {}", directive.route, e), } }

Next Steps

Now that you understand the #api directive in Rust, explore other directive types:

- #web Directive - Web routes with full HTTP control - #cli Directive - Command-line interface integration - #cron Directive - Scheduled task execution - #middleware Directive - Request processing pipeline

Ready to build blazing-fast APIs with Rust and TuskLang? Let's continue with the next directive!