Skip to content

Commit cc5af85

Browse files
authored
feat: parse request params into QueryParams (#187)
1 parent 87e63a8 commit cc5af85

File tree

2 files changed

+83
-7
lines changed

2 files changed

+83
-7
lines changed

src/addon/file_server/mod.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod directory_entry;
22
mod file;
33
mod http_utils;
4+
mod query_params;
45
mod scoped_file_system;
56

67
pub use file::{File, FILE_BUFFER_SIZE};
@@ -59,13 +60,17 @@ impl<'a> FileServer {
5960
Arc::new(handlebars)
6061
}
6162

62-
/// Retrieves the path from the URI and removes the query params
63-
fn sanitize_path(req_uri: &str) -> Result<PathBuf> {
63+
fn parse_path(req_uri: &str) -> Result<PathBuf> {
6464
let uri = Uri::from_str(req_uri)?;
6565
let uri_parts = uri.into_parts();
6666

6767
if let Some(path_and_query) = uri_parts.path_and_query {
6868
let path = path_and_query.path();
69+
let _queries = if let Some(query_str) = path_and_query.query() {
70+
Some(query_params::QueryParams::from_str(query_str)?)
71+
} else {
72+
None
73+
};
6974

7075
return Ok(decode_uri(path));
7176
}
@@ -83,8 +88,8 @@ impl<'a> FileServer {
8388
///
8489
/// If the HTTP Request URI points to `/` (root), the default behavior
8590
/// would be to respond with `Not Found` but in order to provide `root_dir`
86-
/// indexing, the request is handled and renders `root_dir` directory listing
87-
/// instead.
91+
/// indexing, the request is handled and renders `root_dir` directory
92+
/// listing instead.
8893
///
8994
/// If the HTTP Request doesn't match any file relative to `root_dir` then
9095
/// responds with 'Not Found'
@@ -100,7 +105,7 @@ impl<'a> FileServer {
100105
pub async fn resolve(&self, req_path: String) -> Result<Response<Body>> {
101106
use std::io::ErrorKind;
102107

103-
let path = FileServer::sanitize_path(req_path.as_str())?;
108+
let path = FileServer::parse_path(req_path.as_str())?;
104109

105110
match self.scoped_file_system.resolve(path).await {
106111
Ok(entry) => match entry {
@@ -280,7 +285,7 @@ mod tests {
280285
}
281286

282287
#[test]
283-
fn sanitize_req_uri_path() {
288+
fn parse_req_uri_path() {
284289
let have = vec![
285290
"/index.html",
286291
"/index.html?foo=1234",
@@ -296,7 +301,7 @@ mod tests {
296301
];
297302

298303
for (idx, req_uri) in have.iter().enumerate() {
299-
let sanitized_path = FileServer::sanitize_path(req_uri).unwrap();
304+
let sanitized_path = FileServer::parse_path(req_uri).unwrap();
300305
let wanted_path = PathBuf::from_str(want[idx]).unwrap();
301306

302307
assert_eq!(sanitized_path, wanted_path);

src/addon/file_server/query_params.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use anyhow::Error;
2+
use std::str::FromStr;
3+
4+
#[derive(Debug, PartialEq, Eq)]
5+
enum SortBy {
6+
Name,
7+
}
8+
9+
impl FromStr for SortBy {
10+
type Err = Error;
11+
12+
fn from_str(s: &str) -> Result<Self, Self::Err> {
13+
let lower = s.to_ascii_lowercase();
14+
let lower = lower.as_str();
15+
16+
match lower {
17+
"name" => Ok(SortBy::Name),
18+
_ => Err(Error::msg("Value doesnt correspond")),
19+
}
20+
}
21+
}
22+
23+
#[derive(Debug, Default, PartialEq, Eq)]
24+
pub struct QueryParams {
25+
sort_by: Option<SortBy>,
26+
}
27+
28+
impl FromStr for QueryParams {
29+
type Err = Error;
30+
31+
fn from_str(s: &str) -> Result<Self, Self::Err> {
32+
let mut query_params = QueryParams::default();
33+
34+
for set in s.split('&') {
35+
let mut it = set.split('=').take(2);
36+
37+
if let (Some(key), Some(value)) = (it.next(), it.next()) {
38+
match key {
39+
"sort_by" => {
40+
if let Ok(sort_value) = SortBy::from_str(value) {
41+
query_params.sort_by = Some(sort_value);
42+
}
43+
}
44+
_ => continue,
45+
}
46+
}
47+
48+
continue;
49+
}
50+
51+
Ok(query_params)
52+
}
53+
}
54+
55+
#[cfg(test)]
56+
mod tests {
57+
use std::str::FromStr;
58+
59+
use super::{QueryParams, SortBy};
60+
61+
#[test]
62+
fn builds_query_params_from_str() {
63+
let uri_string = "sort_by=name";
64+
let have = QueryParams::from_str(uri_string).unwrap();
65+
let expect = QueryParams {
66+
sort_by: Some(SortBy::Name),
67+
};
68+
69+
assert_eq!(have, expect);
70+
}
71+
}

0 commit comments

Comments
 (0)