🦀 🦀 #web - Web Route Directive - Rust Edition
🦀 #web - Web Route Directive - Rust Edition
"We don't bow to any king" - Rust Edition
The #web
directive in Rust creates web routes with full HTTP control, enabling you to build high-performance web applications with zero-copy routing and Rust's memory safety guarantees.
Basic Syntax
use tusklang_rust::{parse, WebDirective, RouteHandler};
use actix_web::{web, HttpResponse, Responder};// Simple web route with Rust handler
let web_config = r#"
#web /hello {
handler: "HelloController::greet"
method: "GET"
response: "Hello, World!"
}
"#;
// Route with parameters
let user_route = r#"
#web /users/{id} {
handler: "UserController::show"
method: "GET"
params: {
id: "uuid"
}
}
"#;
// Route with middleware
let protected_route = r#"
#web /admin {
handler: "AdminController::dashboard"
method: "GET"
middleware: ["auth", "admin"]
require_auth: true
}
"#;
Route Parameters with Rust Types
use tusklang_rust::{WebDirective, RouteParams};
use uuid::Uuid;
use serde::{Deserialize, Serialize};#[derive(Debug, Deserialize, Serialize)]
struct RouteParams {
id: Uuid,
slug: String,
page: Option<u32>,
}
// Single parameter with type validation
let single_param = r#"
#web /users/{id} {
handler: "UserController::show"
params: {
id: "uuid"
}
validation: {
id: "required|uuid"
}
}
"#;
// Multiple parameters with Rust path extraction
let multi_params = r#"
#web /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 optional_params = r#"
#web /search/{query}/{page?} {
handler: "SearchController::query"
params: {
query: "string"
page: "Option<u32>"
}
defaults: {
page: 1
}
}
"#;
HTTP Methods with Rust Enums
use tusklang_rust::{WebDirective, HttpMethod};
use actix_web::{web, HttpResponse, Responder};#[derive(Debug, Deserialize, Serialize, Clone)]
enum HttpMethod {
GET,
POST,
PUT,
DELETE,
PATCH,
HEAD,
OPTIONS,
}
// GET request (default)
let get_route = r#"
#web /users {
method: "GET"
handler: "UserController::index"
response_type: "html"
template: "users/index.html"
}
"#;
// POST request with form handling
let post_route = r#"
#web /users method: POST {
handler: "UserController::create"
content_type: "application/x-www-form-urlencoded"
validation: {
name: "required|string|max:255"
email: "required|email|unique:users"
password: "required|min:8"
}
redirect: "/users"
}
"#;
// Multiple methods with Rust pattern matching
let crud_route = r#"
#web /users/{id} method: [GET, PUT, DELETE] {
handler: "UserController::handle"
params: {
id: "uuid"
}
switch: {
GET: {
response_type: "html"
template: "users/show.html"
}
PUT: {
content_type: "application/json"
validation: {
name: "string|max:255"
email: "email|unique:users,id"
}
}
DELETE: {
redirect: "/users"
flash_message: "User deleted successfully"
}
}
}
"#;
Request Handling with Rust Types
use tusklang_rust::{WebDirective, Request, RequestData};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;#[derive(Debug, Deserialize)]
struct WebRequest {
query: HashMap<String, String>,
headers: HashMap<String, String>,
body: Option<String>,
files: HashMap<String, UploadedFile>,
session: HashMap<String, String>,
cookies: HashMap<String, String>,
}
#[derive(Debug, Deserialize)]
struct UploadedFile {
name: String,
content_type: String,
size: usize,
path: String,
}
// Access request data with Rust types
let request_handling = r#"
#web /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: {
user_agent: "string"
accept: "string|in:text/html,application/json"
}
# Form data handling
form_validation: {
name: "required|string|max:255"
email: "required|email"
message: "string|max:1000"
}
# File upload handling
file_validation: {
avatar: "optional|file|max:5MB|mimes:jpg,jpeg,png"
document: "optional|file|max:10MB|mimes:pdf,doc,docx"
}
# Session data
session_required: ["user_id"]
# Cookie handling
cookies: {
theme: "string|default:light"
language: "string|default:en"
}
}
"#;
Response Control with Rust HTTP Types
use tusklang_rust::{WebDirective, Response, ResponseBuilder};
use actix_web::{HttpResponse, http::StatusCode};// HTML responses with templates
let html_route = r#"
#web /dashboard {
handler: "DashboardController::index"
response_type: "html"
template: "dashboard/index.html"
layout: "layouts/app.html"
template_data: {
user: @user
stats: @get_user_stats(@user.id)
notifications: @get_notifications(@user.id)
}
response_headers: {
"Cache-Control": "private, max-age=300"
"X-Frame-Options": "DENY"
}
}
"#;
// JSON responses with Rust serialization
let json_route = r#"
#web /api/data {
handler: "DataController::fetch"
response_type: "json"
response_data: {
status: "success"
data: @fetch_data()
timestamp: @now()
}
response_headers: {
"Content-Type": "application/json"
"Cache-Control": "public, max-age=60"
}
}
"#;
// File downloads with Rust file handling
let download_route = r#"
#web /download/{file} {
handler: "FileController::download"
params: {
file: "string"
}
response_type: "file"
file_path: "@storage_path(@params.file)"
response_headers: {
"Content-Type": "application/octet-stream"
"Content-Disposition": "attachment; filename=\"{file}\""
"Cache-Control": "no-cache"
}
validation: {
file: "required|string|exists:storage"
}
}
"#;
// Redirects with flash messages
let redirect_route = r#"
#web /login method: POST {
handler: "AuthController::login"
validation: {
email: "required|email"
password: "required|string"
}
on_success: {
redirect: "/dashboard"
flash_message: "Welcome back!"
flash_type: "success"
}
on_error: {
redirect: "/login"
flash_message: "Invalid credentials"
flash_type: "error"
preserve_input: true
}
}
"#;
Middleware Integration with Rust
use tusklang_rust::{WebDirective, Middleware, MiddlewareChain};
use actix_web::{web, HttpRequest, HttpResponse, Error};// Middleware with Rust trait system
trait WebMiddleware {
async fn process(&self, req: &HttpRequest) -> Result<HttpResponse, Error>;
fn priority(&self) -> u32;
fn name(&self) -> &str;
}
// Authentication middleware
let auth_middleware = r#"
#middleware auth {
handler: "AuthMiddleware::authenticate"
priority: 100
async: true
config: {
session_key: "user_id"
redirect_url: "/login"
exclude_paths: ["/login", "/register", "/public"]
}
}
"#;
// Logging middleware
let logging_middleware = r#"
#middleware logging {
handler: "LoggingMiddleware::log_request"
priority: 50
async: true
config: {
log_level: "info"
include_headers: ["user-agent", "x-forwarded-for"]
exclude_paths: ["/health", "/metrics"]
}
}
"#;
// CSRF protection middleware
let csrf_middleware = r#"
#middleware csrf {
handler: "CsrfMiddleware::protect"
priority: 75
async: true
config: {
token_name: "_token"
token_length: 32
exclude_methods: ["GET", "HEAD", "OPTIONS"]
}
}
"#;
// Apply middleware to routes
let protected_routes = r#"
#web /admin {
handler: "AdminController::dashboard"
middleware: ["auth", "logging", "csrf"]
require_auth: true
roles: ["admin"]
}
#web /profile {
handler: "UserController::profile"
middleware: ["auth", "logging"]
require_auth: true
}
#web /public {
handler: "PublicController::index"
middleware: ["logging"]
public: true
}
"#;
Template Integration with Rust
use tusklang_rust::{WebDirective, TemplateEngine, TemplateContext};
use tera::{Tera, Context};// Template rendering with Rust template engines
let template_route = r#"
#web /users {
handler: "UserController::index"
response_type: "html"
template: "users/index.html"
layout: "layouts/app.html"
template_data: {
users: @User.all()
pagination: @get_pagination(@request.query.page)
search: @request.query.search
}
template_functions: {
format_date: "@format_date"
user_avatar: "@get_user_avatar"
user_status: "@get_user_status"
}
cache: {
enabled: true
ttl: "5m"
key: "users:list:{@request.query.page}:{@request.query.search}"
}
}
"#;
// Dynamic template selection
let dynamic_template = r#"
#web /content/{slug} {
handler: "ContentController::show"
params: {
slug: "string"
}
template: "@get_template_for_content(@params.slug)"
layout: "@get_layout_for_user(@user)"
template_data: {
content: @get_content(@params.slug)
related: @get_related_content(@params.slug)
comments: @get_comments(@params.slug)
}
cache: {
enabled: true
ttl: "10m"
key: "content:{@params.slug}"
}
}
"#;
Session Management with Rust
use tusklang_rust::{WebDirective, SessionManager, SessionData};
use std::collections::HashMap;// Session handling with Rust types
let session_route = r#"
#web /login method: POST {
handler: "AuthController::login"
validation: {
email: "required|email"
password: "required|string"
}
session: {
user_id: "@user.id"
user_email: "@user.email"
user_role: "@user.role"
login_time: "@now()"
}
session_config: {
secure: true
http_only: true
same_site: "strict"
max_age: "24h"
}
on_success: {
redirect: "/dashboard"
flash_message: "Welcome back!"
}
}
"#;
// Session validation
let session_validation = r#"
#web /dashboard {
handler: "DashboardController::index"
session_required: ["user_id"]
session_validation: {
user_id: "required|uuid"
user_role: "required|string|in:user,admin,moderator"
}
on_session_invalid: {
redirect: "/login"
flash_message: "Please log in to continue"
}
}
"#;
Error Handling with Rust Result Types
use tusklang_rust::{WebDirective, WebError, ErrorHandler};
use thiserror::Error;#[derive(Error, Debug)]
pub enum WebError {
#[error("Route not found: {0}")]
NotFoundError(String),
#[error("Authentication required")]
AuthRequiredError,
#[error("Permission denied: {0}")]
PermissionError(String),
#[error("Validation failed: {0}")]
ValidationError(String),
#[error("Internal server error: {0}")]
InternalError(String),
}
// Error handling with Rust Result types
let error_handling = r#"
#web /users/{id} {
handler: "UserController::show"
params: {
id: "uuid"
}
error_handling: {
not_found: {
status: 404
template: "errors/404.html"
log: true
}
auth_required: {
status: 401
redirect: "/login"
flash_message: "Please log in to view this page"
}
permission_denied: {
status: 403
template: "errors/403.html"
log: true
}
validation_errors: {
status: 422
template: "errors/validation.html"
preserve_input: true
}
server_errors: {
status: 500
template: "errors/500.html"
log: true
notify_admin: true
}
}
return: @User.find_or_404(@params.id)
}
"#;
Integration with Rust Web Frameworks
use actix_web::{web, App, HttpServer, HttpResponse};
use tusklang_rust::{WebDirective, ActixIntegration};// Actix-web integration
async fn create_actix_app() -> App<()> {
let web_directives = parse(r#"
#web /users {
handler: "UserController::index"
middleware: ["auth"]
template: "users/index.html"
}
#web /users/{id} {
handler: "UserController::show"
params: {
id: "uuid"
}
template: "users/show.html"
}
"#)?;
App::new()
.configure(|cfg| {
WebDirective::configure_actix(cfg, web_directives);
})
}
// Axum integration
use axum::{Router, routing::get, extract::Path};
use tusklang_rust::AxumIntegration;
async fn create_axum_app() -> Router {
let web_directives = parse(r#"
#web /users {
handler: "UserController::index"
response_type: "html"
}
"#)?;
WebDirective::create_axum_router(web_directives)
}
// Rocket integration
use rocket::{Rocket, Build, get, post};
use tusklang_rust::RocketIntegration;
fn create_rocket_app() -> Rocket<Build> {
let web_directives = parse(r#"
#web /users {
handler: "UserController::index"
}
"#)?;
rocket::build()
.attach(WebDirective::fairing(web_directives))
}
Testing Web Directives with Rust
use tusklang_rust::{WebDirectiveTester, TestRequest, TestResponse};
use tokio::test;#[tokio::test]
async fn test_web_directive() {
let web_directive = r#"
#web /test {
handler: "TestController::index"
response_type: "html"
template: "test/index.html"
template_data: {
message: "Hello, Test!"
}
}
"#;
let tester = WebDirectiveTester::new();
let response = tester
.test_web_directive(web_directive, "/test")
.method("GET")
.execute()
.await?;
assert_eq!(response.status_code, 200);
assert_eq!(response.content_type, "text/html");
assert!(response.body.contains("Hello, Test!"));
}
#[tokio::test]
async fn test_web_directive_with_params() {
let web_directive = r#"
#web /users/{id} {
handler: "UserController::show"
params: {
id: "uuid"
}
template: "users/show.html"
}
"#;
let tester = WebDirectiveTester::new();
let user_id = uuid::Uuid::new_v4();
let response = tester
.test_web_directive(web_directive, &format!("/users/{}", user_id))
.method("GET")
.execute()
.await?;
assert_eq!(response.status_code, 200);
}
Performance Optimization with Rust
use tusklang_rust::{WebDirective, PerformanceOptimizer};
use std::sync::Arc;
use tokio::sync::RwLock;// Zero-copy web processing
fn process_web_zero_copy<'a>(directive: &'a str) -> WebDirectiveResult<WebContext<'a>> {
let context = WebContext::from_str(directive)?;
Ok(context)
}
// Async web processing with Rust futures
async fn process_web_async(directive: &WebDirective) -> WebDirectiveResult<()> {
let handler = find_handler_async(&directive.handler).await?;
handler.execute_async().await?;
Ok(())
}
// Template caching with Rust
let template_cache = r#"
#web /cached {
handler: "CachedController::index"
template: "cached/index.html"
cache: {
strategy: "template"
ttl: "10m"
key: "template:cached:index"
}
template_data: {
data: @get_cached_data()
}
}
"#;
Security Best Practices with Rust
use tusklang_rust::{WebDirective, SecurityValidator};
use std::collections::HashSet;// Security validation for web directives
struct WebSecurityValidator {
allowed_handlers: HashSet<String>,
allowed_methods: HashSet<String>,
max_payload_size: usize,
required_headers: HashSet<String>,
secure_paths: HashSet<String>,
}
impl WebSecurityValidator {
fn validate_web_directive(&self, directive: &WebDirective) -> WebDirectiveResult<()> {
// Validate handler
if !self.allowed_handlers.contains(&directive.handler) {
return Err(WebError::SecurityError(
format!("Handler not allowed: {}", directive.handler)
));
}
// Validate method
if let Some(method) = &directive.method {
if !self.allowed_methods.contains(method) {
return Err(WebError::SecurityError(
format!("Method not allowed: {}", method)
));
}
}
// Validate secure paths
if directive.require_auth && !self.secure_paths.contains(&directive.route) {
return Err(WebError::SecurityError(
format!("Route not in secure paths: {}", directive.route)
));
}
Ok(())
}
}
Best Practices for Rust Web Directives
// 1. Use strong typing for web configurations
#[derive(Debug, Deserialize, Serialize)]
struct WebDirectiveConfig {
route: String,
method: HttpMethod,
handler: String,
template: Option<String>,
middleware: Vec<String>,
require_auth: bool,
cache: Option<CacheConfig>,
}// 2. Implement proper error handling
fn process_web_directive_safe(directive: &str) -> Result<WebDirective, Box<dyn std::error::Error>> {
let parsed = parse(directive)?;
// Validate directive
let validator = WebSecurityValidator::new();
validator.validate_web_directive(&parsed)?;
Ok(parsed)
}
// 3. Use async/await for I/O operations
async fn execute_web_directive_async(directive: &WebDirective) -> WebDirectiveResult<()> {
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_web_execution(directive: &WebDirective, result: &WebDirectiveResult<()>) {
match result {
Ok(_) => info!("Web directive executed successfully: {}", directive.route),
Err(e) => error!("Web directive execution failed: {} - {}", directive.route, e),
}
}
Next Steps
Now that you understand the #web
directive in Rust, explore other directive types:
- #cli Directive - Command-line interface integration - #cron Directive - Scheduled task execution - #middleware Directive - Request processing pipeline - #auth Directive - Authentication and authorization
Ready to build lightning-fast web applications with Rust and TuskLang? Let's continue with the next directive!