elif_http/routing/
mod.rs

1//! HTTP routing system for elif.rs
2//!
3//! This module provides flexible HTTP routing with:
4//! - Framework-independent route pattern matching
5//! - Advanced parameter extraction with type conversion
6//! - Route compilation and optimization
7//! - Efficient route resolution
8//! - Route groups and prefixes
9//! - Route naming and URL generation
10//! - Parameter validation and constraints
11
12// Legacy modules (will be refactored to use new engine)
13pub mod group;
14pub mod params;
15pub mod router;
16pub mod versioned;
17
18// New framework-independent routing engine
19pub mod compiler;
20pub mod diagnostics;
21pub mod extraction;
22pub mod matcher;
23pub mod pattern;
24
25// Legacy exports (for backward compatibility)
26pub use group::{GroupBuilder, RouteGroup};
27pub use params::{ParamError, ParamType, PathParams, RouteParam};
28pub use router::{RouteBuilder, Router as ElifRouter, Router};
29pub use versioned::{
30    header_versioned_router, path_versioned_router, versioned_router, VersionedRouteBuilder,
31    VersionedRouter,
32};
33
34// New engine exports
35pub use compiler::{
36    CompilableRoute, CompilationResult, CompilationStats, RouteCompiler, RouteCompilerBuilder,
37};
38pub use diagnostics::{CliDiagnosticsFormatter, RouteDiagnostics};
39pub use extraction::{ExtractedParams, ExtractionError, ParameterExtractor, TypedExtractorBuilder};
40pub use matcher::{MatcherStats, RouteDefinition, RouteMatcher, RouteMatcherBuilder, RouteMatchError};
41pub use pattern::{CompiledRoute, ParamConstraint, PathSegment, RouteMatch, RoutePattern};
42
43use axum::http::Method;
44use serde::{Deserialize, Serialize};
45use std::collections::HashMap;
46
47/// HTTP methods supported by the router
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub enum HttpMethod {
50    GET,
51    POST,
52    PUT,
53    DELETE,
54    PATCH,
55    HEAD,
56    OPTIONS,
57    TRACE,
58}
59
60impl HttpMethod {
61    /// Get the string representation of the HTTP method
62    pub fn as_str(&self) -> &'static str {
63        match self {
64            HttpMethod::GET => "GET",
65            HttpMethod::POST => "POST", 
66            HttpMethod::PUT => "PUT",
67            HttpMethod::DELETE => "DELETE",
68            HttpMethod::PATCH => "PATCH",
69            HttpMethod::HEAD => "HEAD",
70            HttpMethod::OPTIONS => "OPTIONS",
71            HttpMethod::TRACE => "TRACE",
72        }
73    }
74}
75
76impl std::fmt::Display for HttpMethod {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        write!(f, "{}", self.as_str())
79    }
80}
81
82impl From<Method> for HttpMethod {
83    fn from(method: Method) -> Self {
84        match method {
85            Method::GET => HttpMethod::GET,
86            Method::POST => HttpMethod::POST,
87            Method::PUT => HttpMethod::PUT,
88            Method::DELETE => HttpMethod::DELETE,
89            Method::PATCH => HttpMethod::PATCH,
90            Method::HEAD => HttpMethod::HEAD,
91            Method::OPTIONS => HttpMethod::OPTIONS,
92            Method::TRACE => HttpMethod::TRACE,
93            _ => HttpMethod::GET, // Default fallback
94        }
95    }
96}
97
98impl From<HttpMethod> for Method {
99    fn from(method: HttpMethod) -> Self {
100        match method {
101            HttpMethod::GET => Method::GET,
102            HttpMethod::POST => Method::POST,
103            HttpMethod::PUT => Method::PUT,
104            HttpMethod::DELETE => Method::DELETE,
105            HttpMethod::PATCH => Method::PATCH,
106            HttpMethod::HEAD => Method::HEAD,
107            HttpMethod::OPTIONS => Method::OPTIONS,
108            HttpMethod::TRACE => Method::TRACE,
109        }
110    }
111}
112
113/// Route metadata for introspection and URL generation
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct RouteInfo {
116    pub name: Option<String>,
117    pub path: String,
118    pub method: HttpMethod,
119    pub params: Vec<String>,
120    pub group: Option<String>,
121}
122
123/// Route registry for managing all registered routes
124#[derive(Debug, Default)]
125pub struct RouteRegistry {
126    routes: HashMap<String, RouteInfo>,
127    named_routes: HashMap<String, String>, // name -> route_id
128}
129
130impl RouteRegistry {
131    pub fn new() -> Self {
132        Self {
133            routes: HashMap::new(),
134            named_routes: HashMap::new(),
135        }
136    }
137
138    pub fn register(&mut self, route_id: String, info: RouteInfo) {
139        if let Some(ref name) = info.name {
140            self.named_routes.insert(name.clone(), route_id.clone());
141        }
142        self.routes.insert(route_id, info);
143    }
144
145    pub fn get(&self, route_id: &str) -> Option<&RouteInfo> {
146        self.routes.get(route_id)
147    }
148
149    pub fn get_by_name(&self, name: &str) -> Option<&RouteInfo> {
150        self.named_routes
151            .get(name)
152            .and_then(|id| self.routes.get(id))
153    }
154
155    pub fn all_routes(&self) -> &HashMap<String, RouteInfo> {
156        &self.routes
157    }
158}