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 url::Url;
|
||||||
use urlpattern::{UrlPattern, UrlPatternInit, UrlPatternMatchInput};
|
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 {
|
struct UrlPatternWithInput {
|
||||||
pathname: String,
|
pathname: String,
|
||||||
|
|
@ -65,13 +75,13 @@ impl<T> Router<T> {
|
||||||
for (upwi, methods) in self.patterns.iter() {
|
for (upwi, methods) in self.patterns.iter() {
|
||||||
let pattern = &upwi.pattern;
|
let pattern = &upwi.pattern;
|
||||||
let result = pattern.exec(UrlPatternMatchInput::Url(url.clone()));
|
let result = pattern.exec(UrlPatternMatchInput::Url(url.clone()));
|
||||||
let pathGroups = match result {
|
let path_groups = match result {
|
||||||
Ok(Some(res)) => res.pathname.groups,
|
Ok(Some(res)) => res.pathname.groups,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(t) = methods.get(method) {
|
if let Some(t) = methods.get(method) {
|
||||||
return Ok((t, pathGroups));
|
return Ok((t, PathParams(path_groups)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(405);
|
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 Result<T> = core::result::Result<T, AnyError>;
|
||||||
|
|
||||||
pub type Dbs = atelier::rusqlite_thread_pool::PoolSender;
|
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<()> {
|
fn migrate(connection: &mut rusqlite::Connection) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -23,7 +27,10 @@ fn init(connection: &mut rusqlite::Connection) -> rusqlite::Result<()> {
|
||||||
type Request = axum::extract::Request;
|
type Request = axum::extract::Request;
|
||||||
type Response = axum::response::Response;
|
type Response = axum::response::Response;
|
||||||
type Handler = Box<
|
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
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
|
|
@ -33,18 +40,22 @@ type Router = atelier::router::Router<Handler>;
|
||||||
fn make_handler<Fut, F>(f: F) -> Handler
|
fn make_handler<Fut, F>(f: F) -> Handler
|
||||||
where
|
where
|
||||||
Fut: Future<Output = Response> + Send + 'static,
|
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();
|
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()
|
"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 {
|
fn make_router() -> Router {
|
||||||
let mut router = atelier::router::Router::new();
|
let mut router = atelier::router::Router::new();
|
||||||
|
|
||||||
|
|
@ -55,6 +66,7 @@ fn make_router() -> Router {
|
||||||
}
|
}
|
||||||
|
|
||||||
r!("GET", "/hello", get_hello);
|
r!("GET", "/hello", get_hello);
|
||||||
|
r!("GET", "/hello/:name", get_hello_name);
|
||||||
|
|
||||||
router
|
router
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +79,7 @@ async fn serve(
|
||||||
let method = req.method().as_str();
|
let method = req.method().as_str();
|
||||||
let uri = format!("{}", req.uri());
|
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,
|
Ok(h) => h,
|
||||||
Err(sc) => {
|
Err(sc) => {
|
||||||
return (http::status::StatusCode::from_u16(sc).unwrap(), "")
|
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<()> {
|
async fn go() -> Result<()> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue