Bit of a better path param interface
This commit is contained in:
parent
fd9322923b
commit
8bede90019
|
|
@ -3,7 +3,17 @@ use std::collections::HashMap;
|
|||
use url::Url;
|
||||
use urlpattern::{UrlPattern, UrlPatternInit, UrlPatternMatchInput};
|
||||
|
||||
pub type PathParams = HashMap<String, Option<String>>;
|
||||
pub struct PathParams(HashMap<String, Option<String>>);
|
||||
impl PathParams {
|
||||
pub fn get(&self, name: &str) -> &str {
|
||||
let s = match self.0.get(name) {
|
||||
None => return "",
|
||||
Some(s) => s,
|
||||
};
|
||||
|
||||
s.as_ref().map(|s| s.as_str()).unwrap_or("")
|
||||
}
|
||||
}
|
||||
|
||||
struct UrlPatternWithInput {
|
||||
pathname: String,
|
||||
|
|
@ -65,13 +75,13 @@ impl<T> Router<T> {
|
|||
for (upwi, methods) in self.patterns.iter() {
|
||||
let pattern = &upwi.pattern;
|
||||
let result = pattern.exec(UrlPatternMatchInput::Url(url.clone()));
|
||||
let pathGroups = match result {
|
||||
let path_groups = match result {
|
||||
Ok(Some(res)) => res.pathname.groups,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if let Some(t) = methods.get(method) {
|
||||
return Ok((t, pathGroups));
|
||||
return Ok((t, PathParams(path_groups)));
|
||||
}
|
||||
|
||||
return Err(405);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ pub type AnyError = Box<dyn Error + Send + Sync + 'static>;
|
|||
pub type Result<T> = core::result::Result<T, AnyError>;
|
||||
|
||||
pub type Dbs = atelier::rusqlite_thread_pool::PoolSender;
|
||||
pub struct RequestCtx {
|
||||
dbs: Dbs,
|
||||
path_params: atelier::router::PathParams,
|
||||
}
|
||||
|
||||
fn migrate(connection: &mut rusqlite::Connection) -> Result<()> {
|
||||
Ok(())
|
||||
|
|
@ -23,7 +27,10 @@ fn init(connection: &mut rusqlite::Connection) -> rusqlite::Result<()> {
|
|||
type Request = axum::extract::Request;
|
||||
type Response = axum::response::Response;
|
||||
type Handler = Box<
|
||||
dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'static>>
|
||||
dyn Fn(
|
||||
Request,
|
||||
RequestCtx,
|
||||
) -> Pin<Box<dyn Future<Output = Response> + Send + 'static>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
|
|
@ -33,18 +40,22 @@ type Router = atelier::router::Router<Handler>;
|
|||
fn make_handler<Fut, F>(f: F) -> Handler
|
||||
where
|
||||
Fut: Future<Output = Response> + Send + 'static,
|
||||
F: FnMut(Request) -> Fut + Clone + Send + Sync + 'static,
|
||||
F: FnMut(Request, RequestCtx) -> Fut + Clone + Send + Sync + 'static,
|
||||
{
|
||||
Box::new(move |req| {
|
||||
Box::new(move |req, ctx| {
|
||||
let mut f = f.clone();
|
||||
Box::pin(async move { f(req).await })
|
||||
Box::pin(async move { f(req, ctx).await })
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_hello(req: Request) -> Response {
|
||||
async fn get_hello(req: Request, ctx: RequestCtx) -> Response {
|
||||
"hello".into_response()
|
||||
}
|
||||
|
||||
async fn get_hello_name(req: Request, ctx: RequestCtx) -> Response {
|
||||
format!("Hello, {}", ctx.path_params.get("name")).into_response()
|
||||
}
|
||||
|
||||
fn make_router() -> Router {
|
||||
let mut router = atelier::router::Router::new();
|
||||
|
||||
|
|
@ -55,6 +66,7 @@ fn make_router() -> Router {
|
|||
}
|
||||
|
||||
r!("GET", "/hello", get_hello);
|
||||
r!("GET", "/hello/:name", get_hello_name);
|
||||
|
||||
router
|
||||
}
|
||||
|
|
@ -67,7 +79,7 @@ async fn serve(
|
|||
let method = req.method().as_str();
|
||||
let uri = format!("{}", req.uri());
|
||||
|
||||
let (handler, pathParams) = match router.get(method, &uri) {
|
||||
let (handler, path_params) = match router.get(method, &uri) {
|
||||
Ok(h) => h,
|
||||
Err(sc) => {
|
||||
return (http::status::StatusCode::from_u16(sc).unwrap(), "")
|
||||
|
|
@ -75,7 +87,7 @@ async fn serve(
|
|||
},
|
||||
};
|
||||
|
||||
handler(req).await
|
||||
handler(req, RequestCtx { dbs, path_params }).await
|
||||
}
|
||||
|
||||
async fn go() -> Result<()> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue