Last active
March 1, 2023 16:46
-
-
Save theoparis/39d1544c0fb6c63ca39b975d28d6fda8 to your computer and use it in GitHub Desktop.
rust + hyper http dynamic routing
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
#![feature(async_closure)] | |
use crate::handler::router::handle; | |
use anyhow::Result; | |
use futures::future::FutureExt; | |
use handler::router::DynamicRouter; | |
use hyper::{ | |
service::{make_service_fn, service_fn}, | |
Body, Response, Server, StatusCode, | |
}; | |
use matchit::Router; | |
use std::{ | |
convert::Infallible, | |
net::{IpAddr, Ipv6Addr, SocketAddr}, | |
sync::Arc, | |
}; | |
use tokio::sync::Mutex; | |
use tracing::{error, info}; | |
pub mod handler; | |
#[tokio::main] | |
async fn main() -> Result<()> { | |
tracing_subscriber::fmt::init(); | |
let addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 6969); | |
let router: Arc<Mutex<DynamicRouter>> = Arc::new(Mutex::new(Router::new())); | |
{ | |
let mut router = router.lock().await; | |
router.insert( | |
"/404", | |
Box::new(|(parts, bytes)| { | |
Box::pin(async move { | |
Response::builder() | |
.status(StatusCode::NOT_FOUND) | |
.body(Body::from("404 Not Found")) | |
}) | |
}), | |
)?; | |
router.insert( | |
"/", | |
Box::new(|(parts, bytes)| { | |
Box::pin(async move { | |
Response::builder() | |
.status(StatusCode::OK) | |
.body(Body::from("eeeeeee it works")) | |
}) | |
}), | |
)?; | |
} | |
info!("Starting server on {}", addr); | |
let server = Server::bind(&addr).serve(make_service_fn(move |_conn| { | |
let router = router.clone(); | |
async move { | |
Ok::<_, Infallible>(service_fn(move |req| { | |
handle(req, router.clone()) | |
})) | |
} | |
})); | |
if let Err(e) = server.await { | |
error!("server error: {}", e); | |
} | |
Ok(()) | |
} |
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 std::sync::Arc; | |
use anyhow::Result; | |
use futures::future::BoxFuture; | |
use hyper::{body::Bytes, http::request::Parts, Body, Request, Response}; | |
use matchit::Router; | |
use tokio::sync::Mutex; | |
pub type RouteFn<'a> = Box< | |
dyn Send | |
+ Sync | |
+ Fn( | |
(Parts, Bytes), | |
) -> BoxFuture<'a, Result<Response<Body>, hyper::http::Error>>, | |
>; | |
pub type DynamicRouter<'a> = Router<RouteFn<'a>>; | |
pub async fn handle( | |
request: Request<Body>, | |
router: Arc<Mutex<DynamicRouter<'_>>>, | |
) -> Result<Response<Body>> { | |
let parts = request.into_parts(); | |
let bytes = hyper::body::to_bytes(parts.1).await?; | |
let router = router.lock().await; | |
let handler = router.at(parts.0.uri.path()); | |
match handler { | |
Ok(handler) => { | |
let response = (handler.value)((parts.0, bytes)).await?; | |
Ok(response) | |
} | |
Err(_) => { | |
let not_found_handler = router.at("/404").unwrap(); | |
let response = (not_found_handler.value)((parts.0, bytes)).await?; | |
Ok(response) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment