1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-24 00:01:11 +01:00

rework resourcedef (#373)

This commit is contained in:
Rob Ede 2021-07-19 22:37:54 +01:00 committed by GitHub
parent a83dfaa162
commit c65e8524b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 956 additions and 372 deletions

View File

@ -1,3 +1,3 @@
[alias] [alias]
chk = "hack check --workspace --all-features --tests --examples" chk = "check --workspace --all-features --tests --examples --bins"
lint = "hack --clean-per-run clippy --workspace --tests --examples" lint = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo"

View File

@ -39,4 +39,4 @@ jobs:
uses: actions-rs/clippy-check@v1 uses: actions-rs/clippy-check@v1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --tests --all-features args: --workspace --all-features --tests --examples --bins -- -Dclippy::todo

View File

@ -1,15 +1,23 @@
# Changes # Changes
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
* Resource definitions with unnamed tail segments now correctly interpolate the tail when constructed from an iterator. [#371] * Fix a bug in multi-patterns where static patterns are interpreted as regex. [#366]
* Introduce `ResourceDef::resource_path_from_map_with_tail` method to allow building paths in the presence of unnamed tail segments. [#371] * Introduce `ResourceDef::pattern_iter` to get an iterator over all patterns in a multi-pattern resource. [#373]
* Fix segment interpolation leaving `Path` in unintended state after matching. [#368] * Fix segment interpolation leaving `Path` in unintended state after matching. [#368]
* Path tail pattern now works as expected after a dynamic segment (e.g. `/user/{uid}/*`). [#366] * Fix `ResourceDef` `PartialEq` implementation.
* Fixed a bug where, in multi-patterns, static patterns are interpreted as regex. [#366] * Re-work `IntoPatterns` trait, adding a `Patterns` enum. [#372]
* Re-work `IntoPatterns` trait. [#372] * Implement `IntoPatterns` for `bytestring::ByteString`. [#372]
* Rename `Path::{len => segment_count}` to be more descriptive of it's purpose. [#370] * Rename `Path::{len => segment_count}` to be more descriptive of it's purpose. [#370]
* Alias `ResourceDef::{resource_path => resource_path_from_iter}` pending eventual deprecation. [#371] * Rename `ResourceDef::{resource_path => resource_path_from_iter}`. [#371]
* Alias `ResourceDef::{resource_path_named => resource_path_from_map}` pending eventual deprecation. [#371] * `ResourceDef::resource_path_from_iter` now takes an `IntoIterator`. [#373]
* Rename `ResourceDef::{resource_path_named => resource_path_from_map}`. [#371]
* Rename `ResourceDef::{is_prefix_match => find_match}`. [#373]
* Rename `ResourceDef::{match_path => capture_match_info}`. [#373]
* Rename `ResourceDef::{match_path_checked => capture_match_info_fn}`. [#373]
* Remove `ResourceDef::name_mut` and introduce `ResourceDef::set_name`. [#373]
* Rename `Router::{*_checked => *_fn}`. [#373]
* Return type of `ResourceDef::name` is now `Option<&str>`. [#373]
* Return type of `ResourceDef::pattern` is now `Option<&str>`. [#373]
[#368]: https://github.com/actix/actix-net/pull/368 [#368]: https://github.com/actix/actix-net/pull/368
[#366]: https://github.com/actix/actix-net/pull/366 [#366]: https://github.com/actix/actix-net/pull/366
@ -17,6 +25,7 @@
[#370]: https://github.com/actix/actix-net/pull/370 [#370]: https://github.com/actix/actix-net/pull/370
[#371]: https://github.com/actix/actix-net/pull/371 [#371]: https://github.com/actix/actix-net/pull/371
[#372]: https://github.com/actix/actix-net/pull/372 [#372]: https://github.com/actix/actix-net/pull/372
[#373]: https://github.com/actix/actix-net/pull/373
## 0.4.0 - 2021-06-06 ## 0.4.0 - 2021-06-06

View File

@ -140,7 +140,7 @@ macro_rules! register {
}}; }};
} }
static PATHS: [&'static str; 5] = [ static PATHS: [&str; 5] = [
"/authorizations", "/authorizations",
"/user/repos", "/user/repos",
"/repos/rust-lang/rust/stargazers", "/repos/rust-lang/rust/stargazers",

View File

@ -14,6 +14,8 @@ pub use self::path::Path;
pub use self::resource::ResourceDef; pub use self::resource::ResourceDef;
pub use self::router::{ResourceInfo, Router, RouterBuilder}; pub use self::router::{ResourceInfo, Router, RouterBuilder};
// TODO: this trait is necessary, document it
// see impl Resource for ServiceRequest
pub trait Resource<T: ResourcePath> { pub trait Resource<T: ResourcePath> {
fn resource_path(&mut self) -> &mut Path<T>; fn resource_path(&mut self) -> &mut Path<T>;
} }
@ -41,7 +43,7 @@ impl ResourcePath for bytestring::ByteString {
} }
/// One or many patterns. /// One or many patterns.
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Patterns { pub enum Patterns {
Single(String), Single(String),
List(Vec<String>), List(Vec<String>),
@ -70,6 +72,12 @@ impl<'a> IntoPatterns for &'a str {
} }
} }
impl IntoPatterns for bytestring::ByteString {
fn patterns(&self) -> Patterns {
Patterns::Single(self.to_string())
}
}
impl<T: AsRef<str>> IntoPatterns for Vec<T> { impl<T: AsRef<str>> IntoPatterns for Vec<T> {
fn patterns(&self) -> Patterns { fn patterns(&self) -> Patterns {
let mut patterns = self.iter().map(|v| v.as_ref().to_owned()); let mut patterns = self.iter().map(|v| v.as_ref().to_owned());

View File

@ -4,8 +4,7 @@ use std::ops::Index;
use firestorm::profile_method; use firestorm::profile_method;
use serde::de; use serde::de;
use crate::de::PathDeserializer; use crate::{de::PathDeserializer, Resource, ResourcePath};
use crate::{Resource, ResourcePath};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) enum PathItem { pub(crate) enum PathItem {
@ -120,24 +119,21 @@ impl<T: ResourcePath> Path<T> {
} }
/// Get matched parameter by name without type conversion /// Get matched parameter by name without type conversion
pub fn get(&self, key: &str) -> Option<&str> { pub fn get(&self, name: &str) -> Option<&str> {
profile_method!(get); profile_method!(get);
for item in self.segments.iter() { for (seg_name, val) in self.segments.iter() {
if key == item.0 { if name == seg_name {
return match item.1 { return match val {
PathItem::Static(ref s) => Some(&s), PathItem::Static(ref s) => Some(&s),
PathItem::Segment(s, e) => { PathItem::Segment(s, e) => {
Some(&self.path.path()[(s as usize)..(e as usize)]) Some(&self.path.path()[(*s as usize)..(*e as usize)])
} }
}; };
} }
} }
if key == "tail" {
Some(&self.path.path()[(self.skip as usize)..]) None
} else {
None
}
} }
/// Get unprocessed part of the path /// Get unprocessed part of the path
@ -150,7 +146,7 @@ impl<T: ResourcePath> Path<T> {
/// If keyed parameter is not available empty string is used as default value. /// If keyed parameter is not available empty string is used as default value.
pub fn query(&self, key: &str) -> &str { pub fn query(&self, key: &str) -> &str {
profile_method!(query); profile_method!(query);
if let Some(s) = self.get(key) { if let Some(s) = self.get(key) {
s s
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@ -29,10 +29,11 @@ impl<T, U> Router<T, U> {
profile_method!(recognize); profile_method!(recognize);
for item in self.0.iter() { for item in self.0.iter() {
if item.0.match_path(resource.resource_path()) { if item.0.capture_match_info(resource.resource_path()) {
return Some((&item.1, ResourceId(item.0.id()))); return Some((&item.1, ResourceId(item.0.id())));
} }
} }
None None
} }
@ -44,18 +45,15 @@ impl<T, U> Router<T, U> {
profile_method!(recognize_mut); profile_method!(recognize_mut);
for item in self.0.iter_mut() { for item in self.0.iter_mut() {
if item.0.match_path(resource.resource_path()) { if item.0.capture_match_info(resource.resource_path()) {
return Some((&mut item.1, ResourceId(item.0.id()))); return Some((&mut item.1, ResourceId(item.0.id())));
} }
} }
None None
} }
pub fn recognize_checked<R, P, F>( pub fn recognize_fn<R, P, F>(&self, resource: &mut R, check: F) -> Option<(&T, ResourceId)>
&self,
resource: &mut R,
check: F,
) -> Option<(&T, ResourceId)>
where where
F: Fn(&R, &Option<U>) -> bool, F: Fn(&R, &Option<U>) -> bool,
R: Resource<P>, R: Resource<P>,
@ -64,14 +62,15 @@ impl<T, U> Router<T, U> {
profile_method!(recognize_checked); profile_method!(recognize_checked);
for item in self.0.iter() { for item in self.0.iter() {
if item.0.match_path_checked(resource, &check, &item.2) { if item.0.capture_match_info_fn(resource, &check, &item.2) {
return Some((&item.1, ResourceId(item.0.id()))); return Some((&item.1, ResourceId(item.0.id())));
} }
} }
None None
} }
pub fn recognize_mut_checked<R, P, F>( pub fn recognize_mut_fn<R, P, F>(
&mut self, &mut self,
resource: &mut R, resource: &mut R,
check: F, check: F,
@ -84,10 +83,11 @@ impl<T, U> Router<T, U> {
profile_method!(recognize_mut_checked); profile_method!(recognize_mut_checked);
for item in self.0.iter_mut() { for item in self.0.iter_mut() {
if item.0.match_path_checked(resource, &check, &item.2) { if item.0.capture_match_info_fn(resource, &check, &item.2) {
return Some((&mut item.1, ResourceId(item.0.id()))); return Some((&mut item.1, ResourceId(item.0.id())));
} }
} }
None None
} }
} }

View File

@ -206,7 +206,7 @@ mod tests {
let re = ResourceDef::new(pattern); let re = ResourceDef::new(pattern);
let uri = Uri::try_from(url.as_ref()).unwrap(); let uri = Uri::try_from(url.as_ref()).unwrap();
let mut path = Path::new(Url::new(uri)); let mut path = Path::new(Url::new(uri));
assert!(re.match_path(&mut path)); assert!(re.capture_match_info(&mut path));
path path
} }
@ -221,7 +221,7 @@ mod tests {
let path = match_url(re, "/user/2345/test"); let path = match_url(re, "/user/2345/test");
assert_eq!(path.get("id").unwrap(), "2345"); assert_eq!(path.get("id").unwrap(), "2345");
// "%25" should never be decoded into '%' to gurantee the output is a valid // "%25" should never be decoded into '%' to guarantee the output is a valid
// percent-encoded format // percent-encoded format
let path = match_url(re, "/user/qwe%25/test"); let path = match_url(re, "/user/qwe%25/test");
assert_eq!(path.get("id").unwrap(), "qwe%25"); assert_eq!(path.get("id").unwrap(), "qwe%25");