1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-08-13 02:47:08 +02:00

Compare commits

...

15 Commits

Author SHA1 Message Date
Nikolay Kim
ae27b87641 IoStream trait and impls for TcpStream, SslStream and TlsStream 2019-04-16 08:32:12 -07:00
Nikolay Kim
fc2dcadc7a use stable version of trust-dns-resolver 2019-04-14 20:46:36 -07:00
Nikolay Kim
54f62b5035 prep release 2019-04-12 12:30:55 -07:00
Nikolay Kim
d3208bf7a8 Do not start default resolver immediately for default connector. 2019-04-12 12:28:18 -07:00
Nikolay Kim
21507d3da1 add TestServerRuntime::run_on() method 2019-04-12 12:26:47 -07:00
Nikolay Kim
b9d8a215b4 Start trust-dns default resolver on first use 2019-04-11 09:57:21 -07:00
Nikolay Kim
51c4dfe5cb Allow to reset Path instance; export Quoter type 2019-04-07 22:48:18 -07:00
Nikolay Kim
a60112c71e Poll boxed service call result immediately 2019-04-07 20:48:40 -07:00
Nikolay Kim
bd814d6f80 re-export trust-dns types 2019-04-05 10:36:57 -07:00
Nikolay Kim
a4e0c71baa Merge branch 'master' of github.com:actix/actix-net 2019-04-04 15:41:50 -07:00
Nikolay Kim
b9ea445e70 Log error if dns system config could not be loaded 2019-04-04 15:41:05 -07:00
Nikolay Kim
ba2901269d Merge pull request #11 from Dowwie/master
added docs for trait Service, trait Transform
2019-04-04 11:06:02 -07:00
dowwie
5cbc29306a updated as per comments 2019-04-04 14:02:53 -04:00
Nikolay Kim
810fa869ae remove unneeded static 2019-04-04 10:04:19 -07:00
dowwie
33cd51aabf added docs for trait Service, trait Transform 2019-04-04 11:40:28 -04:00
26 changed files with 324 additions and 71 deletions

View File

@@ -1,6 +1,29 @@
# Changes
## [0.1.2] - 2019-04-xx
### Changed
* Use trust-dns-resolver 0.11.0
## [0.1.4] - 2019-04-12
### Changed
* Do not start default resolver immediately for default connector.
## [0.1.3] - 2019-04-11
### Changed
* Start trust-dns default resolver on first use
## [0.1.2] - 2019-04-04
### Added
* Log error if dns system config could not be loaded.
### Changed

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-connect"
version = "0.1.2"
version = "0.1.4"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix Connector - tcp connector service"
keywords = ["network", "framework", "async", "futures"]
@@ -30,9 +30,9 @@ ssl = ["openssl", "tokio-openssl"]
uri = ["http"]
[dependencies]
actix-service = "0.3.4"
actix-codec = "0.1.1"
actix-utils = "0.3.4"
actix-service = "0.3.6"
actix-codec = "0.1.2"
actix-utils = "0.3.5"
derive_more = "0.14.0"
either = "1.5.1"
futures = "0.1.25"
@@ -40,7 +40,7 @@ http = { version = "0.1.16", optional = true }
log = "0.4"
tokio-tcp = "0.1.3"
tokio-current-thread = "0.1.5"
trust-dns-resolver = { version="0.11.0-alpha.2", default-features = false }
trust-dns-resolver = { version="0.11.0", default-features = false }
# openssl
openssl = { version="0.10", optional = true }
@@ -48,8 +48,7 @@ tokio-openssl = { version="0.3", optional = true }
[dev-dependencies]
bytes = "0.4"
actix-connect = { path=".", features=["ssl"] }
actix-test-server = { version="0.2.0", features=["ssl"] }
actix-test-server = { version="0.2.1", features=["ssl"] }
actix-server-config = "0.1.0"
actix-utils = "0.3.4"
tokio-tcp = "0.1"

View File

@@ -8,6 +8,8 @@
#[macro_use]
extern crate log;
use std::cell::RefCell;
mod connect;
mod connector;
mod error;
@@ -17,6 +19,8 @@ pub mod ssl;
#[cfg(feature = "uri")]
mod uri;
pub use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
pub use trust_dns_resolver::system_conf::read_system_conf;
pub use trust_dns_resolver::{error::ResolveError, AsyncResolver};
pub use self::connect::{Address, Connect, Connection};
@@ -26,8 +30,6 @@ pub use self::resolver::{Resolver, ResolverFactory};
use actix_service::{NewService, Service, ServiceExt};
use tokio_tcp::TcpStream;
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
use trust_dns_resolver::system_conf::read_system_conf;
#[doc(hidden)]
#[deprecated(since = "0.1.2", note = "please use `actix_connect::TcpConnector`")]
@@ -46,16 +48,34 @@ pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> AsyncResolver
resolver
}
pub fn start_default_resolver() -> AsyncResolver {
let (cfg, opts) = if let Ok((cfg, opts)) = read_system_conf() {
(cfg, opts)
} else {
(ResolverConfig::default(), ResolverOpts::default())
};
thread_local! {
static DEFAULT_RESOLVER: RefCell<Option<AsyncResolver>> = RefCell::new(None);
}
let (resolver, bg) = AsyncResolver::new(cfg, opts);
tokio_current_thread::spawn(bg);
resolver
pub(crate) fn get_default_resolver() -> AsyncResolver {
DEFAULT_RESOLVER.with(|cell| {
if let Some(ref resolver) = *cell.borrow() {
return resolver.clone();
}
let (cfg, opts) = match read_system_conf() {
Ok((cfg, opts)) => (cfg, opts),
Err(e) => {
log::error!("TRust-DNS can not load system config: {}", e);
(ResolverConfig::default(), ResolverOpts::default())
}
};
let (resolver, bg) = AsyncResolver::new(cfg, opts);
tokio_current_thread::spawn(bg);
*cell.borrow_mut() = Some(resolver.clone());
resolver
})
}
pub fn start_default_resolver() -> AsyncResolver {
get_default_resolver()
}
/// Create tcp connector service
@@ -82,7 +102,7 @@ pub fn new_connector_factory<T: Address>(
pub fn default_connector<T: Address>(
) -> impl Service<Request = Connect<T>, Response = Connection<T, TcpStream>, Error = ConnectError>
+ Clone {
Resolver::new(start_default_resolver()).and_then(TcpConnector::new())
Resolver::default().and_then(TcpConnector::new())
}
/// Create connector service factory with default parameters
@@ -92,5 +112,5 @@ pub fn default_connector_factory<T: Address>() -> impl NewService<
Error = ConnectError,
InitError = (),
> + Clone {
ResolverFactory::new(start_default_resolver()).and_then(TcpConnectorFactory::new())
ResolverFactory::default().and_then(TcpConnectorFactory::new())
}

View File

@@ -10,10 +10,11 @@ use trust_dns_resolver::{AsyncResolver, Background};
use crate::connect::{Address, Connect};
use crate::error::ConnectError;
use crate::get_default_resolver;
/// DNS Resolver Service factory
pub struct ResolverFactory<T> {
resolver: AsyncResolver,
resolver: Option<AsyncResolver>,
_t: PhantomData<T>,
}
@@ -21,13 +22,18 @@ impl<T> ResolverFactory<T> {
/// Create new resolver instance with custom configuration and options.
pub fn new(resolver: AsyncResolver) -> Self {
ResolverFactory {
resolver,
resolver: Some(resolver),
_t: PhantomData,
}
}
}
pub fn resolver(&self) -> &AsyncResolver {
&self.resolver
impl<T> Default for ResolverFactory<T> {
fn default() -> Self {
ResolverFactory {
resolver: None,
_t: PhantomData,
}
}
}
@@ -58,7 +64,7 @@ impl<T: Address> NewService for ResolverFactory<T> {
/// DNS Resolver Service
pub struct Resolver<T> {
resolver: AsyncResolver,
resolver: Option<AsyncResolver>,
_t: PhantomData<T>,
}
@@ -66,7 +72,16 @@ impl<T> Resolver<T> {
/// Create new resolver instance with custom configuration and options.
pub fn new(resolver: AsyncResolver) -> Self {
Resolver {
resolver,
resolver: Some(resolver),
_t: PhantomData,
}
}
}
impl<T> Default for Resolver<T> {
fn default() -> Self {
Resolver {
resolver: None,
_t: PhantomData,
}
}
@@ -100,7 +115,10 @@ impl<T: Address> Service for Resolver<T> {
Either::B(ok(req))
} else {
trace!("DNS resolver: resolving host {:?}", req.host());
Either::A(ResolverFuture::new(req, &self.resolver))
if self.resolver.is_none() {
self.resolver = Some(get_default_resolver());
}
Either::A(ResolverFuture::new(req, self.resolver.as_ref().unwrap()))
}
}
}

View File

@@ -9,6 +9,7 @@ use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
use actix_connect::{default_connector, Connect};
#[cfg(feature = "ssl")]
#[test]
fn test_string() {
let mut srv = TestServer::with(|| {
@@ -19,11 +20,9 @@ fn test_string() {
})
});
let mut conn = srv
.block_on(lazy(|| Ok::<_, ()>(default_connector())))
.unwrap();
let mut conn = default_connector();
let addr = format!("localhost:{}", srv.port());
let con = srv.block_on(conn.call(addr.into())).unwrap();
let con = srv.run_on(move || conn.call(addr.into())).unwrap();
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
@@ -92,6 +91,7 @@ fn test_new_service() {
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
#[cfg(feature = "ssl")]
#[test]
fn test_uri() {
let mut srv = TestServer::with(|| {
@@ -102,10 +102,8 @@ fn test_uri() {
})
});
let mut conn = srv
.block_on(lazy(|| Ok::<_, ()>(default_connector())))
.unwrap();
let mut conn = default_connector();
let addr = Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
let con = srv.block_on(conn.call(addr.into())).unwrap();
let con = srv.run_on(move || conn.call(addr.into())).unwrap();
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-server-config"
version = "0.1.0"
version = "0.1.1"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix server config utils"
homepage = "https://actix.rs"
@@ -13,5 +13,22 @@ workspace = ".."
name = "actix_server_config"
path = "src/lib.rs"
[package.metadata.docs.rs]
features = ["ssl", "rust-tls"]
[features]
default = []
# openssl
ssl = ["tokio-openssl"]
# rustls
rust-tls = ["rustls", "tokio-rustls"]
[dependencies]
futures = "0.1.25"
tokio-io = "0.1.12"
tokio-tcp = "0.1"
tokio-openssl = { version="0.3.0", optional = true }
rustls = { version = "0.15.2", optional = true }
tokio-rustls = { version = "0.9.1", optional = true }

View File

@@ -0,0 +1,7 @@
# Changes
## [0.1.1] - 2019-04-16
### Added
* `IoStream` trait and impls for TcpStream, SslStream and TlsStream

View File

@@ -1,7 +1,10 @@
use std::cell::Cell;
use std::fmt;
use std::net::SocketAddr;
use std::rc::Rc;
use std::{fmt, io, net, time};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_tcp::TcpStream;
#[derive(Debug, Clone)]
pub struct ServerConfig {
@@ -130,3 +133,86 @@ impl<T: fmt::Debug, P> fmt::Debug for Io<T, P> {
write!(f, "Io {{{:?}}}", self.io)
}
}
/// Low-level io stream operations
pub trait IoStream: AsyncRead + AsyncWrite {
/// Returns the socket address of the remote peer of this TCP connection.
fn peer_addr(&self) -> Option<SocketAddr> {
None
}
/// Sets the value of the TCP_NODELAY option on this socket.
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()>;
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()>;
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()>;
}
impl IoStream for TcpStream {
#[inline]
fn peer_addr(&self) -> Option<net::SocketAddr> {
TcpStream::peer_addr(self).ok()
}
#[inline]
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
TcpStream::set_nodelay(self, nodelay)
}
#[inline]
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
TcpStream::set_linger(self, dur)
}
#[inline]
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
TcpStream::set_keepalive(self, dur)
}
}
#[cfg(any(feature = "ssl"))]
impl<T: IoStream> IoStream for tokio_openssl::SslStream<T> {
#[inline]
fn peer_addr(&self) -> Option<net::SocketAddr> {
self.get_ref().get_ref().peer_addr()
}
#[inline]
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
self.get_mut().get_mut().set_nodelay(nodelay)
}
#[inline]
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
self.get_mut().get_mut().set_linger(dur)
}
#[inline]
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
self.get_mut().get_mut().set_keepalive(dur)
}
}
#[cfg(any(feature = "rust-tls"))]
impl<T: IoStream> IoStream for tokio_rustls::TlsStream<T, rustls::ServerSession> {
#[inline]
fn peer_addr(&self) -> Option<net::SocketAddr> {
self.get_ref().0.peer_addr()
}
#[inline]
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
self.get_mut().0.set_nodelay(nodelay)
}
#[inline]
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
self.get_mut().0.set_linger(dur)
}
#[inline]
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
self.get_mut().0.set_keepalive(dur)
}
}

View File

@@ -1,5 +1,16 @@
# Changes
## [0.4.3] - 2019-04-16
### Added
* Re-export `IoStream` trait
### Changed
* Deppend on `ssl` and `rust-tls` features from actix-server-config
## [0.4.2] - 2019-03-30
### Fixed

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-server"
version = "0.4.2"
version = "0.4.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix server - General purpose tcp server"
keywords = ["network", "framework", "async", "futures"]
@@ -27,20 +27,20 @@ default = []
tls = ["native-tls"]
# openssl
ssl = ["openssl", "tokio-openssl"]
ssl = ["openssl", "tokio-openssl", "actix-server-config/ssl"]
# rustls
rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots"]
rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots", "actix-server-config/rust-tls"]
[dependencies]
actix-rt = "0.2.1"
actix-service = "0.3.4"
actix-server-config = "0.1.0"
actix-server-config = "0.1.1"
log = "0.4"
num_cpus = "1.0"
mio = "^0.6.13"
mio = "0.6.13"
net2 = "0.2"
futures = "0.1"
slab = "0.4"
@@ -58,12 +58,12 @@ openssl = { version="0.10", optional = true }
tokio-openssl = { version="0.3", optional = true }
#rustls
rustls = { version = "^0.15", optional = true }
tokio-rustls = { version = "^0.9", optional = true }
rustls = { version = "0.15.2", optional = true }
tokio-rustls = { version = "0.9.1", optional = true }
webpki = { version = "0.19", optional = true }
webpki-roots = { version = "0.16", optional = true }
[dev-dependencies]
bytes = "0.4"
actix-codec = "0.1.0"
actix-codec = "0.1.2"
env_logger = "0.6"

View File

@@ -10,7 +10,7 @@ mod signals;
pub mod ssl;
mod worker;
pub use actix_server_config::{Io, Protocol, ServerConfig};
pub use actix_server_config::{Io, IoStream, Protocol, ServerConfig};
pub use self::builder::ServerBuilder;
pub use self::config::{ServiceConfig, ServiceRuntime};

View File

@@ -1,5 +1,12 @@
# Changes
## [0.3.6] - 2019-04-07
### Changed
* Poll boxed service call result immediately
## [0.3.5] - 2019-03-29
### Added

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-service"
version = "0.3.5"
version = "0.3.6"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix Service"
keywords = ["network", "framework", "async", "futures"]

View File

@@ -1,12 +1,14 @@
use futures::future::{err, ok, Either, FutureResult};
use futures::{Async, Future, IntoFuture, Poll};
use crate::{NewService, Service};
use futures::{Future, IntoFuture, Poll};
pub type BoxedService<Req, Res, Err> = Box<
Service<
Request = Req,
Response = Res,
Error = Err,
Future = Box<Future<Item = Res, Error = Err>>,
Future = Either<FutureResult<Res, Err>, Box<Future<Item = Res, Error = Err>>>,
>,
>;
@@ -125,13 +127,21 @@ where
type Request = Req;
type Response = Res;
type Error = Err;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
type Future = Either<
FutureResult<Self::Response, Self::Error>,
Box<Future<Item = Self::Response, Error = Self::Error>>,
>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.0.poll_ready()
}
fn call(&mut self, req: Self::Request) -> Self::Future {
Box::new(self.0.call(req))
let mut fut = self.0.call(req);
match fut.poll() {
Ok(Async::Ready(res)) => Either::A(ok(res)),
Err(e) => Either::A(err(e)),
Ok(Async::NotReady) => Either::B(Box::new(fut)),
}
}
}

View File

@@ -6,9 +6,16 @@ use futures::{Async, Future, IntoFuture, Poll};
use crate::transform_err::{TransformFromErr, TransformMapInitErr};
use crate::{IntoNewService, NewService, Service};
/// `Transform` service factory.
/// The `Transform` trait defines the interface of a Service factory. `Transform`
/// is often implemented for middleware, defining how to manufacture a
/// middleware Service. A Service that is manufactured by the factory takes
/// the Service that follows it during execution as a parameter, assuming
/// ownership of the next Service. A Service can be a variety of types, such
/// as (but not limited to) another middleware Service, an extractor Service,
/// other helper Services, or the request handler endpoint Service.
///
/// A Service is created by the factory during server initialization.
///
/// Transform factory creates service that wraps other services.
/// `Config` is a service factory configuration type.
pub trait Transform<S> {
/// Requests handled by the service.
@@ -33,7 +40,7 @@ pub trait Transform<S> {
/// The future response value.
type Future: Future<Item = Self::Transform, Error = Self::InitError>;
/// Create and return a new service value asynchronously.
/// Creates and returns a new Service component, asynchronously
fn new_transform(&self, service: S) -> Self::Future;
/// Map this service's factory error to a different error,

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-test-server"
version = "0.2.0"
version = "0.2.1"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix test server"
keywords = ["network", "framework", "async", "futures"]

View File

@@ -6,7 +6,7 @@ use actix_rt::{Runtime, System};
use actix_server::{Server, StreamServiceFactory};
pub use actix_server_config::{Io, ServerConfig};
use futures::Future;
use futures::future::{lazy, Future, IntoFuture};
use net2::TcpBuilder;
use tokio_reactor::Handle;
use tokio_tcp::TcpStream;
@@ -99,6 +99,15 @@ impl TestServerRuntime {
self.rt.block_on(fut)
}
/// Runs the provided function, with runtime enabled.
pub fn run_on<F, R>(&mut self, f: F) -> Result<R::Item, R::Error>
where
F: FnOnce() -> R,
R: IntoFuture,
{
self.rt.block_on(lazy(|| f().into_future()))
}
/// Spawn future to the current runtime
pub fn spawn<F>(&mut self, fut: F)
where

View File

@@ -1,9 +1,16 @@
# Changes
## [0.3.5] - 2019-04-04
### Added
* Allow to send messages to `FramedTransport` via mpsc channel.
### Changed
* Remove 'static constraint from Clonable service
## [0.3.4] - 2019-03-12

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-utils"
version = "0.3.4"
version = "0.3.5"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix utils - various actix net related services"
keywords = ["network", "framework", "async", "futures"]

View File

@@ -7,12 +7,12 @@ use futures::Poll;
use super::cell::Cell;
/// Service that allows to turn non-clone service to a service with `Clone` impl
pub struct CloneableService<T: 'static> {
pub struct CloneableService<T> {
service: Cell<T>,
_t: PhantomData<Rc<()>>,
}
impl<T: 'static> CloneableService<T> {
impl<T> CloneableService<T> {
pub fn new(service: T) -> Self
where
T: Service,
@@ -24,7 +24,7 @@ impl<T: 'static> CloneableService<T> {
}
}
impl<T: 'static> Clone for CloneableService<T> {
impl<T> Clone for CloneableService<T> {
fn clone(&self) -> Self {
Self {
service: self.service.clone(),
@@ -35,7 +35,7 @@ impl<T: 'static> Clone for CloneableService<T> {
impl<T> Service for CloneableService<T>
where
T: Service + 'static,
T: Service,
{
type Request = T::Request;
type Response = T::Response;

View File

@@ -1,5 +1,11 @@
# Changes
## [0.1.2] - 2019-04-07
* Export `Quoter` type
* Allow to reset `Path` instance
## [0.1.1] - 2019-04-03
* Get dynamic segment by name instead of iterator.

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-router"
version = "0.1.1"
version = "0.1.2"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Path router"
keywords = ["actix"]

View File

@@ -39,7 +39,7 @@ impl<T: AsRef<[u8]>> ResourcePath for string::String<T> {
mod url;
#[cfg(feature = "http")]
pub use self::url::Url;
pub use self::url::{Quoter, Url};
#[cfg(feature = "http")]
mod http_support {

View File

@@ -51,16 +51,19 @@ impl<T: ResourcePath> Path<T> {
}
}
#[inline]
/// Get reference to inner path instance
pub fn get_ref(&self) -> &T {
&self.path
}
#[inline]
/// Get mutable reference to inner path instance
pub fn get_mut(&mut self) -> &mut T {
&mut self.path
}
#[inline]
/// Path
pub fn path(&self) -> &str {
let skip = self.skip as usize;
@@ -72,13 +75,22 @@ impl<T: ResourcePath> Path<T> {
}
}
/// Reset inner path
#[inline]
/// Set new path
pub fn set(&mut self, path: T) {
self.skip = 0;
self.path = path;
self.segments.clear();
}
#[inline]
/// Reset state
pub fn reset(&mut self) {
self.skip = 0;
self.segments.clear();
}
#[inline]
/// Skip first `n` chars in path
pub fn skip(&mut self, n: u16) {
self.skip = self.skip + n;
@@ -99,11 +111,13 @@ impl<T: ResourcePath> Path<T> {
.push((Rc::new(name.to_string()), PathItem::Static(value)));
}
#[inline]
/// Check if there are any matched patterns
pub fn is_empty(&self) -> bool {
self.segments.is_empty()
}
#[inline]
/// Check number of extracted parameters
pub fn len(&self) -> usize {
self.segments.len()

View File

@@ -118,6 +118,7 @@ impl ResourceDef {
&self.pattern
}
#[inline]
/// Check if path matchs this pattern?
pub fn is_match(&self, path: &str) -> bool {
match self.tp {

View File

@@ -1,5 +1,3 @@
use std::rc::Rc;
use crate::ResourcePath;
#[allow(dead_code)]
@@ -39,7 +37,7 @@ thread_local! {
#[derive(Default, Clone, Debug)]
pub struct Url {
uri: http::Uri,
path: Option<Rc<String>>,
path: Option<String>,
}
impl Url {
@@ -49,6 +47,13 @@ impl Url {
Url { uri, path }
}
pub fn with_quoter(uri: http::Uri, quoter: &Quoter) -> Url {
Url {
path: quoter.requote(uri.path().as_bytes()),
uri,
}
}
pub fn uri(&self) -> &http::Uri {
&self.uri
}
@@ -61,19 +66,27 @@ impl Url {
}
}
#[inline]
pub fn update(&mut self, uri: &http::Uri) {
self.uri = uri.clone();
self.path = DEFAULT_QUOTER.with(|q| q.requote(uri.path().as_bytes()));
}
#[inline]
pub fn update_with_quoter(&mut self, uri: &http::Uri, quoter: &Quoter) {
self.uri = uri.clone();
self.path = quoter.requote(uri.path().as_bytes());
}
}
impl ResourcePath for Url {
#[inline]
fn path(&self) -> &str {
self.path()
}
}
pub(crate) struct Quoter {
pub struct Quoter {
safe_table: [u8; 16],
protected_table: [u8; 16],
}
@@ -108,7 +121,7 @@ impl Quoter {
q
}
pub fn requote(&self, val: &[u8]) -> Option<Rc<String>> {
pub fn requote(&self, val: &[u8]) -> Option<String> {
let mut has_pct = 0;
let mut pct = [b'%', 0, 0];
let mut idx = 0;
@@ -160,7 +173,7 @@ impl Quoter {
if let Some(data) = cloned {
// Unsafe: we get data from http::Uri, which does utf-8 checks already
// this code only decodes valid pct encoded values
Some(Rc::new(unsafe { String::from_utf8_unchecked(data) }))
Some(unsafe { String::from_utf8_unchecked(data) })
} else {
None
}