Last active
November 20, 2024 03:46
-
-
Save 641i130/70bb89501c011e3646827db4cbf098d0 to your computer and use it in GitHub Desktop.
actix web static mapping with functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "mapactix" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
actix-web = "4.9.0" | |
futures = "0.3.31" | |
phf = {version = "0.11.2", features = ["macros"]} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer, Responder}; | |
use std::collections::HashMap; | |
use std::future::Future; | |
use std::pin::Pin; | |
use std::sync::LazyLock; | |
// Define the handler function signature | |
type HandlerFn = dyn Fn(HttpRequest) -> Pin<Box<dyn Future<Output = Result<HttpResponse, Error>>>> + Send + Sync; | |
// Define asynchronous handler functions | |
async fn handle_request_one(req: HttpRequest) -> Result<HttpResponse, Error> { | |
let query = req.query_string(); | |
Ok(HttpResponse::Ok().body(format!("Handled by async function 1. Query: {}", query))) | |
} | |
async fn handle_request_two(req: HttpRequest) -> Result<HttpResponse, Error> { | |
let path = req.path(); | |
Ok(HttpResponse::Ok().body(format!("Handled by async function 2. Path: {}", path))) | |
} | |
async fn handle_request_three(req: HttpRequest) -> Result<HttpResponse, Error> { | |
let headers = req.headers(); | |
if headers.is_empty() { | |
return Err(actix_web::error::ErrorBadRequest("No headers found")); | |
} | |
Ok(HttpResponse::Ok().body(format!( | |
"Handled by async function 3. Headers: {:?}", | |
headers | |
))) | |
} | |
// Wrap async functions to match the `HandlerFn` signature | |
fn wrap_async_handler<F, Fut>(func: F) -> Box<HandlerFn> | |
where | |
F: Fn(HttpRequest) -> Fut + Send + Sync + 'static, | |
Fut: Future<Output = Result<HttpResponse, Error>> + 'static, | |
{ | |
Box::new(move |req| Box::pin(func(req))) | |
} | |
// Use LazyLock to defer initialization of the runtime map | |
static ROUTE_MAP: LazyLock<HashMap<&'static str, Box<HandlerFn>>> = LazyLock::new(|| { | |
let mut map: HashMap<&'static str, Box<HandlerFn>> = HashMap::new(); | |
map.insert("1", wrap_async_handler(handle_request_one)); | |
map.insert("2", wrap_async_handler(handle_request_two)); | |
map.insert("3", wrap_async_handler(handle_request_three)); | |
map | |
}); | |
// Dynamic handler to route requests | |
async fn dynamic_handler(req: HttpRequest) -> impl Responder { | |
if let Some(number) = req.match_info().get("number") { | |
if let Some(handler) = ROUTE_MAP.get(number) { | |
return match handler(req).await { | |
Ok(response) => response, | |
Err(err) => HttpResponse::InternalServerError().body(err.to_string()), | |
}; | |
} | |
} | |
HttpResponse::NotFound().body("No matching handler for this number") | |
} | |
#[actix_web::main] | |
async fn main() -> std::io::Result<()> { | |
HttpServer::new(|| { | |
App::new() | |
.route("/{number}", web::get().to(dynamic_handler)) | |
}) | |
.bind("127.0.0.1:8080")? | |
.run() | |
.await | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment