From 7682a97a3314060715492a3050e9bb7ed26406de Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Tue, 17 Jan 2023 14:10:21 +0000 Subject: [PATCH] Decode urlencoded path parameters automatically Closes #1396 --- Cargo.lock | 1 + Cargo.toml | 1 + src/net/key.rs | 44 ++++++++++++++++++++++---------------------- src/net/params.rs | 30 ++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 013b7ffd..8ff91e91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3465,6 +3465,7 @@ dependencies = [ "surrealdb", "thiserror", "tokio", + "urlencoding", "warp", ] diff --git a/Cargo.toml b/Cargo.toml index 8a8a3a26..facfca62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ serde_pack = { version = "1.1.1", package = "rmp-serde" } surrealdb = { path = "lib", features = ["protocol-http", "protocol-ws", "rustls"] } thiserror = "1.0.38" tokio = { version = "1.24.1", features = ["macros", "signal"] } +urlencoding = "2.1.2" warp = { version = "0.3.3", features = ["compression", "tls", "websocket"] } [package.metadata.deb] diff --git a/src/net/key.rs b/src/net/key.rs index b4157231..3b7e47ee 100644 --- a/src/net/key.rs +++ b/src/net/key.rs @@ -3,7 +3,7 @@ use crate::dbs::DB; use crate::err::Error; use crate::net::input::bytes_to_utf8; use crate::net::output; -use crate::net::params::Params; +use crate::net::params::{Param, Params}; use crate::net::session; use bytes::Bytes; use serde::Deserialize; @@ -39,7 +39,7 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) - .and(path!("key" / String).and(warp::path::end())) + .and(path!("key" / Param).and(warp::path::end())) .and(warp::query()) .and(session::build()) .and_then(select_all); @@ -47,7 +47,7 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) - .and(path!("key" / String).and(warp::path::end())) + .and(path!("key" / Param).and(warp::path::end())) .and(warp::body::content_length_limit(MAX)) .and(warp::body::bytes()) .and(warp::query()) @@ -57,7 +57,7 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) - .and(path!("key" / String).and(warp::path::end())) + .and(path!("key" / Param).and(warp::path::end())) .and(warp::query()) .and(session::build()) .and_then(delete_all); @@ -72,14 +72,14 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) - .and(path!("key" / String / String).and(warp::path::end())) + .and(path!("key" / Param / Param).and(warp::path::end())) .and(session::build()) .and_then(select_one); // Set create method let create = warp::any() .and(warp::post()) .and(warp::header::(http::header::ACCEPT.as_str())) - .and(path!("key" / String / String).and(warp::path::end())) + .and(path!("key" / Param / Param).and(warp::path::end())) .and(warp::body::content_length_limit(MAX)) .and(warp::body::bytes()) .and(warp::query()) @@ -89,7 +89,7 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) - .and(path!("key" / String / String).and(warp::path::end())) + .and(path!("key" / Param / Param).and(warp::path::end())) .and(warp::body::content_length_limit(MAX)) .and(warp::body::bytes()) .and(warp::query()) @@ -99,7 +99,7 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) - .and(path!("key" / String / String).and(warp::path::end())) + .and(path!("key" / Param / Param).and(warp::path::end())) .and(warp::body::content_length_limit(MAX)) .and(warp::body::bytes()) .and(warp::query()) @@ -109,7 +109,7 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) - .and(path!("key" / String / String).and(warp::path::end())) + .and(path!("key" / Param / Param).and(warp::path::end())) .and(warp::query()) .and(session::build()) .and_then(delete_one); @@ -130,7 +130,7 @@ pub fn config() -> impl Filter Result { @@ -164,7 +164,7 @@ async fn select_all( async fn create_all( output: String, - table: String, + table: Param, body: Bytes, params: Params, session: Session, @@ -205,7 +205,7 @@ async fn create_all( async fn delete_all( output: String, - table: String, + table: Param, params: Params, session: Session, ) -> Result { @@ -240,8 +240,8 @@ async fn delete_all( async fn select_one( output: String, - table: String, - id: String, + table: Param, + id: Param, session: Session, ) -> Result { // Get the datastore reference @@ -276,8 +276,8 @@ async fn select_one( async fn create_one( output: String, - table: String, - id: String, + table: Param, + id: Param, body: Bytes, params: Params, session: Session, @@ -324,8 +324,8 @@ async fn create_one( async fn update_one( output: String, - table: String, - id: String, + table: Param, + id: Param, body: Bytes, params: Params, session: Session, @@ -372,8 +372,8 @@ async fn update_one( async fn modify_one( output: String, - table: String, - id: String, + table: Param, + id: Param, body: Bytes, params: Params, session: Session, @@ -420,8 +420,8 @@ async fn modify_one( async fn delete_one( output: String, - table: String, - id: String, + table: Param, + id: Param, params: Params, session: Session, ) -> Result { diff --git a/src/net/params.rs b/src/net/params.rs index 9b5b2979..02d9a8e2 100644 --- a/src/net/params.rs +++ b/src/net/params.rs @@ -1,7 +1,37 @@ +use crate::err::Error; use serde::Deserialize; use std::collections::BTreeMap; +use std::ops::Deref; +use std::str::FromStr; use surrealdb::sql::Value; +#[derive(Debug, Clone)] +pub struct Param(pub String); + +impl Deref for Param { + type Target = str; + #[inline] + fn deref(&self) -> &Self::Target { + self.0.as_str() + } +} + +impl FromStr for Param { + type Err = Error; + #[inline] + fn from_str(s: &str) -> Result { + let s = urlencoding::decode(s)?.into_owned(); + Ok(Param(s)) + } +} + +impl From for Value { + #[inline] + fn from(v: Param) -> Self { + Value::from(v.0) + } +} + #[derive(Default, Deserialize, Debug, Clone)] pub struct Params { #[serde(flatten)]