update to router 0.5.0 beta

This commit is contained in:
Rob Ede 2021-07-20 08:21:05 +01:00
parent 293c52c3ef
commit 3ddf355241
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
12 changed files with 75 additions and 57 deletions

View File

@ -67,7 +67,8 @@ __compress = []
[dependencies] [dependencies]
actix-codec = "0.4.0" actix-codec = "0.4.0"
actix-macros = "0.2.1" actix-macros = "0.2.1"
actix-router = "0.2.7" # actix-router = "0.5.0"
actix-router = { git = "https://github.com/actix/actix-net.git", branch = "master" }
actix-rt = "2.2" actix-rt = "2.2"
actix-server = "2.0.0-beta.3" actix-server = "2.0.0-beta.3"
actix-service = "2.0.0" actix-service = "2.0.0"

View File

@ -334,7 +334,7 @@ where
U: AsRef<str>, U: AsRef<str>,
{ {
let mut rdef = ResourceDef::new(url.as_ref()); let mut rdef = ResourceDef::new(url.as_ref());
*rdef.name_mut() = name.as_ref().to_string(); rdef.set_name(name.as_ref());
self.external.push(rdef); self.external.push(rdef);
self self
} }

View File

@ -291,7 +291,7 @@ impl Service<ServiceRequest> for AppRouting {
actix_service::always_ready!(); actix_service::always_ready!();
fn call(&self, mut req: ServiceRequest) -> Self::Future { fn call(&self, mut req: ServiceRequest) -> Self::Future {
let res = self.router.recognize_checked(&mut req, |req, guards| { let res = self.router.recognize_fn(&mut req, |req, guards| {
if let Some(ref guards) = guards { if let Some(ref guards) = guards {
for f in guards { for f in guards {
if !f.check(req.head()) { if !f.check(req.head()) {

View File

@ -249,7 +249,7 @@ impl ServiceConfig {
U: AsRef<str>, U: AsRef<str>,
{ {
let mut rdef = ResourceDef::new(url.as_ref()); let mut rdef = ResourceDef::new(url.as_ref());
*rdef.name_mut() = name.as_ref().to_string(); rdef.set_name(name.as_ref());
self.external.push(rdef); self.external.push(rdef);
self self
} }

View File

@ -28,11 +28,22 @@ pub use actix_service::{
use crate::http::header::ContentEncoding; use crate::http::header::ContentEncoding;
use actix_http::{Response, ResponseBuilder}; use actix_http::{Response, ResponseBuilder};
pub(crate) fn insert_leading_slash(mut patterns: Vec<String>) -> Vec<String> { use actix_router::Patterns;
for path in &mut patterns {
if !path.is_empty() && !path.starts_with('/') { pub(crate) fn ensure_leading_slash(mut patterns: Patterns) -> Patterns {
path.insert(0, '/'); match &mut patterns {
}; Patterns::Single(pat) => {
if !pat.is_empty() && !pat.starts_with('/') {
pat.insert(0, '/');
};
}
Patterns::List(pats) => {
for pat in pats {
if !pat.is_empty() && !pat.starts_with('/') {
pat.insert(0, '/');
};
}
}
} }
patterns patterns

View File

@ -509,7 +509,7 @@ mod tests {
#[test] #[test]
fn test_url_for() { fn test_url_for() {
let mut res = ResourceDef::new("/user/{name}.{ext}"); let mut res = ResourceDef::new("/user/{name}.{ext}");
*res.name_mut() = "index".to_string(); res.set_name("index");
let mut rmap = ResourceMap::new(ResourceDef::new("")); let mut rmap = ResourceMap::new(ResourceDef::new(""));
rmap.add(&mut res, None); rmap.add(&mut res, None);
@ -539,7 +539,7 @@ mod tests {
#[test] #[test]
fn test_url_for_static() { fn test_url_for_static() {
let mut rdef = ResourceDef::new("/index.html"); let mut rdef = ResourceDef::new("/index.html");
*rdef.name_mut() = "index".to_string(); rdef.set_name("index");
let mut rmap = ResourceMap::new(ResourceDef::new("")); let mut rmap = ResourceMap::new(ResourceDef::new(""));
rmap.add(&mut rdef, None); rmap.add(&mut rdef, None);
@ -560,7 +560,7 @@ mod tests {
#[test] #[test]
fn test_match_name() { fn test_match_name() {
let mut rdef = ResourceDef::new("/index.html"); let mut rdef = ResourceDef::new("/index.html");
*rdef.name_mut() = "index".to_string(); rdef.set_name("index");
let mut rmap = ResourceMap::new(ResourceDef::new("")); let mut rmap = ResourceMap::new(ResourceDef::new(""));
rmap.add(&mut rdef, None); rmap.add(&mut rdef, None);
@ -579,7 +579,7 @@ mod tests {
fn test_url_for_external() { fn test_url_for_external() {
let mut rdef = ResourceDef::new("https://youtube.com/watch/{video_id}"); let mut rdef = ResourceDef::new("https://youtube.com/watch/{video_id}");
*rdef.name_mut() = "youtube".to_string(); rdef.set_name("youtube");
let mut rmap = ResourceMap::new(ResourceDef::new("")); let mut rmap = ResourceMap::new(ResourceDef::new(""));
rmap.add(&mut rdef, None); rmap.add(&mut rdef, None);

View File

@ -4,7 +4,7 @@ use std::future::Future;
use std::rc::Rc; use std::rc::Rc;
use actix_http::Extensions; use actix_http::Extensions;
use actix_router::IntoPattern; use actix_router::{IntoPatterns, Patterns};
use actix_service::boxed::{self, BoxService, BoxServiceFactory}; use actix_service::boxed::{self, BoxService, BoxServiceFactory};
use actix_service::{ use actix_service::{
apply, apply_fn_factory, fn_service, IntoServiceFactory, Service, ServiceFactory, apply, apply_fn_factory, fn_service, IntoServiceFactory, Service, ServiceFactory,
@ -15,7 +15,7 @@ use futures_util::future::join_all;
use crate::{ use crate::{
data::Data, data::Data,
dev::{insert_leading_slash, AppService, HttpServiceFactory, ResourceDef}, dev::{ensure_leading_slash, AppService, HttpServiceFactory, ResourceDef},
guard::Guard, guard::Guard,
handler::Handler, handler::Handler,
responder::Responder, responder::Responder,
@ -51,7 +51,7 @@ type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, Err
/// Default behavior could be overridden with `default_resource()` method. /// Default behavior could be overridden with `default_resource()` method.
pub struct Resource<T = ResourceEndpoint> { pub struct Resource<T = ResourceEndpoint> {
endpoint: T, endpoint: T,
rdef: Vec<String>, rdef: Patterns,
name: Option<String>, name: Option<String>,
routes: Vec<Route>, routes: Vec<Route>,
app_data: Option<Extensions>, app_data: Option<Extensions>,
@ -61,7 +61,7 @@ pub struct Resource<T = ResourceEndpoint> {
} }
impl Resource { impl Resource {
pub fn new<T: IntoPattern>(path: T) -> Resource { pub fn new<T: IntoPatterns>(path: T) -> Resource {
let fref = Rc::new(RefCell::new(None)); let fref = Rc::new(RefCell::new(None));
Resource { Resource {
@ -391,13 +391,13 @@ where
}; };
let mut rdef = if config.is_root() || !self.rdef.is_empty() { let mut rdef = if config.is_root() || !self.rdef.is_empty() {
ResourceDef::new(insert_leading_slash(self.rdef.clone())) ResourceDef::new(ensure_leading_slash(self.rdef.clone()))
} else { } else {
ResourceDef::new(self.rdef.clone()) ResourceDef::new(self.rdef.clone())
}; };
if let Some(ref name) = self.name { if let Some(ref name) = self.name {
*rdef.name_mut() = name.clone(); rdef.set_name(name);
} }
*self.factory_ref.borrow_mut() = Some(ResourceFactory { *self.factory_ref.borrow_mut() = Some(ResourceFactory {

View File

@ -29,9 +29,8 @@ impl ResourceMap {
pub fn add(&mut self, pattern: &mut ResourceDef, nested: Option<Rc<ResourceMap>>) { pub fn add(&mut self, pattern: &mut ResourceDef, nested: Option<Rc<ResourceMap>>) {
pattern.set_id(self.patterns.len() as u16); pattern.set_id(self.patterns.len() as u16);
self.patterns.push((pattern.clone(), nested)); self.patterns.push((pattern.clone(), nested));
if !pattern.name().is_empty() { if let Some(name) = pattern.name() {
self.named self.named.insert(name.to_owned(), pattern.clone());
.insert(pattern.name().to_string(), pattern.clone());
} }
} }
@ -83,10 +82,10 @@ impl ResourceMap {
for (pattern, rmap) in &self.patterns { for (pattern, rmap) in &self.patterns {
if let Some(ref rmap) = rmap { if let Some(ref rmap) = rmap {
if let Some(plen) = pattern.is_prefix_match(path) { if let Some(pat_len) = pattern.find_match(path) {
return rmap.has_resource(&path[plen..]); return rmap.has_resource(&path[pat_len..]);
} }
} else if pattern.is_match(path) || pattern.pattern() == "" && path == "/" { } else if pattern.is_match(path) || pattern.pattern() == Some("") && path == "/" {
return true; return true;
} }
} }
@ -100,14 +99,11 @@ impl ResourceMap {
for (pattern, rmap) in &self.patterns { for (pattern, rmap) in &self.patterns {
if let Some(ref rmap) = rmap { if let Some(ref rmap) = rmap {
if let Some(plen) = pattern.is_prefix_match(path) { if let Some(plen) = pattern.find_match(path) {
return rmap.match_name(&path[plen..]); return rmap.match_name(&path[plen..]);
} }
} else if pattern.is_match(path) { } else if pattern.is_match(path) {
return match pattern.name() { return pattern.name();
"" => None,
s => Some(s),
};
} }
} }
@ -136,8 +132,9 @@ impl ResourceMap {
fn traverse_resource_pattern(&self, remaining: &str) -> String { fn traverse_resource_pattern(&self, remaining: &str) -> String {
for (pattern, rmap) in &self.patterns { for (pattern, rmap) in &self.patterns {
if let Some(ref rmap) = rmap { if let Some(ref rmap) = rmap {
if let Some(prefix_len) = pattern.is_prefix_match(remaining) { if let Some(prefix_len) = pattern.find_match(remaining) {
let prefix = pattern.pattern().to_owned(); // TODO: think about unwrap_or
let prefix = pattern.pattern().unwrap_or("").to_owned();
return [ return [
prefix, prefix,
@ -146,7 +143,8 @@ impl ResourceMap {
.concat(); .concat();
} }
} else if pattern.is_match(remaining) { } else if pattern.is_match(remaining) {
return pattern.pattern().to_owned(); // TODO: think about unwrap_or
return pattern.pattern().unwrap_or("").to_owned();
} }
} }
@ -181,10 +179,15 @@ impl ResourceMap {
I: AsRef<str>, I: AsRef<str>,
{ {
if let Some(pattern) = self.named.get(name) { if let Some(pattern) = self.named.get(name) {
if pattern.pattern().starts_with('/') { if pattern
.pattern()
.map(|pat| pat.starts_with('/'))
.unwrap_or(false)
{
self.fill_root(path, elements)?; self.fill_root(path, elements)?;
} }
if pattern.resource_path(path, elements) {
if pattern.resource_path_from_iter(path, elements) {
Ok(Some(())) Ok(Some(()))
} else { } else {
Err(UrlGenerationError::NotEnoughElements) Err(UrlGenerationError::NotEnoughElements)
@ -213,7 +216,8 @@ impl ResourceMap {
if let Some(ref parent) = self.parent.borrow().upgrade() { if let Some(ref parent) = self.parent.borrow().upgrade() {
parent.fill_root(path, elements)?; parent.fill_root(path, elements)?;
} }
if self.root.resource_path(path, elements) {
if self.root.resource_path_from_iter(path, elements) {
Ok(()) Ok(())
} else { } else {
Err(UrlGenerationError::NotEnoughElements) Err(UrlGenerationError::NotEnoughElements)
@ -233,7 +237,7 @@ impl ResourceMap {
if let Some(ref parent) = self.parent.borrow().upgrade() { if let Some(ref parent) = self.parent.borrow().upgrade() {
if let Some(pattern) = parent.named.get(name) { if let Some(pattern) = parent.named.get(name) {
self.fill_root(path, elements)?; self.fill_root(path, elements)?;
if pattern.resource_path(path, elements) { if pattern.resource_path_from_iter(path, elements) {
Ok(Some(())) Ok(Some(()))
} else { } else {
Err(UrlGenerationError::NotEnoughElements) Err(UrlGenerationError::NotEnoughElements)
@ -329,7 +333,7 @@ mod tests {
let mut root = ResourceMap::new(ResourceDef::root_prefix("")); let mut root = ResourceMap::new(ResourceDef::root_prefix(""));
let mut rdef = ResourceDef::new("/info"); let mut rdef = ResourceDef::new("/info");
*rdef.name_mut() = "root_info".to_owned(); rdef.set_name("root_info");
root.add(&mut rdef, None); root.add(&mut rdef, None);
let mut user_map = ResourceMap::new(ResourceDef::root_prefix("")); let mut user_map = ResourceMap::new(ResourceDef::root_prefix(""));
@ -337,7 +341,7 @@ mod tests {
user_map.add(&mut rdef, None); user_map.add(&mut rdef, None);
let mut rdef = ResourceDef::new("/post/{post_id}"); let mut rdef = ResourceDef::new("/post/{post_id}");
*rdef.name_mut() = "user_post".to_owned(); rdef.set_name("user_post");
user_map.add(&mut rdef, None); user_map.add(&mut rdef, None);
root.add( root.add(

View File

@ -530,7 +530,7 @@ impl Service<ServiceRequest> for ScopeService {
actix_service::always_ready!(); actix_service::always_ready!();
fn call(&self, mut req: ServiceRequest) -> Self::Future { fn call(&self, mut req: ServiceRequest) -> Self::Future {
let res = self.router.recognize_checked(&mut req, |req, guards| { let res = self.router.recognize_fn(&mut req, |req, guards| {
if let Some(ref guards) = guards { if let Some(ref guards) = guards {
for f in guards { for f in guards {
if !f.check(req.head()) { if !f.check(req.head()) {

View File

@ -7,14 +7,14 @@ use actix_http::{
http::{HeaderMap, Method, StatusCode, Uri, Version}, http::{HeaderMap, Method, StatusCode, Uri, Version},
Extensions, HttpMessage, Payload, PayloadStream, RequestHead, Response, ResponseHead, Extensions, HttpMessage, Payload, PayloadStream, RequestHead, Response, ResponseHead,
}; };
use actix_router::{IntoPattern, Path, Resource, ResourceDef, Url}; use actix_router::{IntoPatterns, Path, Patterns, Resource, ResourceDef, Url};
use actix_service::{IntoServiceFactory, ServiceFactory}; use actix_service::{IntoServiceFactory, ServiceFactory};
#[cfg(feature = "cookies")] #[cfg(feature = "cookies")]
use cookie::{Cookie, ParseError as CookieParseError}; use cookie::{Cookie, ParseError as CookieParseError};
use crate::{ use crate::{
config::{AppConfig, AppService}, config::{AppConfig, AppService},
dev::insert_leading_slash, dev::ensure_leading_slash,
guard::Guard, guard::Guard,
info::ConnectionInfo, info::ConnectionInfo,
rmap::ResourceMap, rmap::ResourceMap,
@ -212,14 +212,14 @@ impl ServiceRequest {
self.req.match_pattern() self.req.match_pattern()
} }
#[inline]
/// Get a mutable reference to the Path parameters. /// Get a mutable reference to the Path parameters.
#[inline]
pub fn match_info_mut(&mut self) -> &mut Path<Url> { pub fn match_info_mut(&mut self) -> &mut Path<Url> {
self.req.match_info_mut() self.req.match_info_mut()
} }
#[inline]
/// Get a reference to a `ResourceMap` of current application. /// Get a reference to a `ResourceMap` of current application.
#[inline]
pub fn resource_map(&self) -> &ResourceMap { pub fn resource_map(&self) -> &ResourceMap {
self.req.resource_map() self.req.resource_map()
} }
@ -459,14 +459,14 @@ where
} }
pub struct WebService { pub struct WebService {
rdef: Vec<String>, rdef: Patterns,
name: Option<String>, name: Option<String>,
guards: Vec<Box<dyn Guard>>, guards: Vec<Box<dyn Guard>>,
} }
impl WebService { impl WebService {
/// Create new `WebService` instance. /// Create new `WebService` instance.
pub fn new<T: IntoPattern>(path: T) -> Self { pub fn new<T: IntoPatterns>(path: T) -> Self {
WebService { WebService {
rdef: path.patterns(), rdef: path.patterns(),
name: None, name: None,
@ -528,7 +528,7 @@ impl WebService {
struct WebServiceImpl<T> { struct WebServiceImpl<T> {
srv: T, srv: T,
rdef: Vec<String>, rdef: Patterns,
name: Option<String>, name: Option<String>,
guards: Vec<Box<dyn Guard>>, guards: Vec<Box<dyn Guard>>,
} }
@ -551,13 +551,15 @@ where
}; };
let mut rdef = if config.is_root() || !self.rdef.is_empty() { let mut rdef = if config.is_root() || !self.rdef.is_empty() {
ResourceDef::new(insert_leading_slash(self.rdef)) ResourceDef::new(ensure_leading_slash(self.rdef))
} else { } else {
ResourceDef::new(self.rdef) ResourceDef::new(self.rdef)
}; };
if let Some(ref name) = self.name { if let Some(ref name) = self.name {
*rdef.name_mut() = name.clone(); rdef.set_name(name);
} }
config.register_service(rdef, guards, self.srv, None) config.register_service(rdef, guards, self.srv, None)
} }
} }

View File

@ -209,7 +209,7 @@ mod tests {
let resource = ResourceDef::new("/{value}/"); let resource = ResourceDef::new("/{value}/");
let mut req = TestRequest::with_uri("/32/").to_srv_request(); let mut req = TestRequest::with_uri("/32/").to_srv_request();
resource.match_path(req.match_info_mut()); resource.capture_match_info(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
assert_eq!(*Path::<i8>::from_request(&req, &mut pl).await.unwrap(), 32); assert_eq!(*Path::<i8>::from_request(&req, &mut pl).await.unwrap(), 32);
@ -221,7 +221,7 @@ mod tests {
let resource = ResourceDef::new("/{key}/{value}/"); let resource = ResourceDef::new("/{key}/{value}/");
let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request(); let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
resource.match_path(req.match_info_mut()); resource.capture_match_info(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let (Path(res),) = <(Path<(String, String)>,)>::from_request(&req, &mut pl) let (Path(res),) = <(Path<(String, String)>,)>::from_request(&req, &mut pl)
@ -247,7 +247,7 @@ mod tests {
let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request(); let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
let resource = ResourceDef::new("/{key}/{value}/"); let resource = ResourceDef::new("/{key}/{value}/");
resource.match_path(req.match_info_mut()); resource.capture_match_info(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let mut s = Path::<MyStruct>::from_request(&req, &mut pl).await.unwrap(); let mut s = Path::<MyStruct>::from_request(&req, &mut pl).await.unwrap();
@ -270,7 +270,7 @@ mod tests {
let mut req = TestRequest::with_uri("/name/32/").to_srv_request(); let mut req = TestRequest::with_uri("/name/32/").to_srv_request();
let resource = ResourceDef::new("/{key}/{value}/"); let resource = ResourceDef::new("/{key}/{value}/");
resource.match_path(req.match_info_mut()); resource.capture_match_info(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let s = Path::<Test2>::from_request(&req, &mut pl).await.unwrap(); let s = Path::<Test2>::from_request(&req, &mut pl).await.unwrap();

View File

@ -1,10 +1,10 @@
//! Essentials helper functions and types for application registration. //! Essentials helper functions and types for application registration.
use actix_http::http::Method;
use actix_router::IntoPattern;
use std::future::Future; use std::future::Future;
use actix_http::http::Method;
pub use actix_http::Response as HttpResponse; pub use actix_http::Response as HttpResponse;
use actix_router::IntoPatterns;
pub use bytes::{Buf, BufMut, Bytes, BytesMut}; pub use bytes::{Buf, BufMut, Bytes, BytesMut};
use crate::error::BlockingError; use crate::error::BlockingError;
@ -51,7 +51,7 @@ pub use crate::types::*;
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed())) /// .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
/// ); /// );
/// ``` /// ```
pub fn resource<T: IntoPattern>(path: T) -> Resource { pub fn resource<T: IntoPatterns>(path: T) -> Resource {
Resource::new(path) Resource::new(path)
} }
@ -268,7 +268,7 @@ where
/// .finish(my_service) /// .finish(my_service)
/// ); /// );
/// ``` /// ```
pub fn service<T: IntoPattern>(path: T) -> WebService { pub fn service<T: IntoPatterns>(path: T) -> WebService {
WebService::new(path) WebService::new(path)
} }