mirror of
https://github.com/fafhrd91/actix-net
synced 2025-08-16 06:49:00 +02:00
Compare commits
27 Commits
connect-v0
...
connect-v0
Author | SHA1 | Date | |
---|---|---|---|
|
54f62b5035 | ||
|
d3208bf7a8 | ||
|
21507d3da1 | ||
|
b9d8a215b4 | ||
|
51c4dfe5cb | ||
|
a60112c71e | ||
|
bd814d6f80 | ||
|
a4e0c71baa | ||
|
b9ea445e70 | ||
|
ba2901269d | ||
|
5cbc29306a | ||
|
810fa869ae | ||
|
33cd51aabf | ||
|
629ed05f82 | ||
|
5e8ae210f7 | ||
|
3add90628f | ||
|
02ab804e0b | ||
|
feac0b43d9 | ||
|
1441355d4f | ||
|
7c5afc09a6 | ||
|
16856c7d3f | ||
|
95d02659d5 | ||
|
bcbd7e6ddf | ||
|
e0d3581239 | ||
|
ef1bdb2eb2 | ||
|
10301ff49d | ||
|
27c28d6597 |
27
.travis.yml
27
.travis.yml
@@ -37,36 +37,13 @@ script:
|
|||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_RUST_VERSION" != "nightly-2019-03-02" ]]; then
|
if [[ "$TRAVIS_RUST_VERSION" != "nightly-2019-03-02" ]]; then
|
||||||
cargo clean
|
cargo clean
|
||||||
cargo test --features="ssl,tls,rust-tls" -- --nocapture
|
cargo test --all --all-features -- --nocapture
|
||||||
cd actix-codec && cargo test && cd ..
|
|
||||||
cd actix-service && cargo test && cd ..
|
|
||||||
cd actix-server && cargo test --all-features -- --nocapture && cd ..
|
|
||||||
cd actix-rt && cargo test && cd ..
|
|
||||||
cd actix-connect && cargo test && cd ..
|
|
||||||
cd actix-utils && cargo test && cd ..
|
|
||||||
cd router && cargo test && cd ..
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_RUST_VERSION" == "nightly-2019-03-02" ]]; then
|
if [[ "$TRAVIS_RUST_VERSION" == "nightly-2019-03-02" ]]; then
|
||||||
#cd actix-service && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
|
taskset -c 0 cargo tarpaulin --all --all-features --out Xml
|
||||||
#cd actix-rt && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
|
|
||||||
#cd actix-connect && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
|
|
||||||
#cd actix-codec && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
|
|
||||||
#cd actix-server && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
|
|
||||||
#cd actix-utils && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
|
|
||||||
#cd router && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
|
|
||||||
|
|
||||||
cd actix-service && cargo tarpaulin --out Xml && cd ..
|
|
||||||
#cd actix-rt && cargo tarpaulin --out Xml && cd ..
|
|
||||||
cd actix-connect && cargo tarpaulin --out Xml && cd ..
|
|
||||||
#cd actix-codec && cargo tarpaulin --out Xml && cd ..
|
|
||||||
#cd actix-server && cargo tarpaulin --out Xml && cd ..
|
|
||||||
cd actix-utils && cargo tarpaulin --out Xml && cd ..
|
|
||||||
cd router && cargo tarpaulin --out Xml && cd ..
|
|
||||||
|
|
||||||
# cargo tarpaulin --all --all-features --out Xml
|
|
||||||
echo "Uploaded code coverage"
|
echo "Uploaded code coverage"
|
||||||
bash <(curl -s https://codecov.io/bash)
|
bash <(curl -s https://codecov.io/bash)
|
||||||
fi
|
fi
|
||||||
|
@@ -22,6 +22,7 @@ members = [
|
|||||||
"actix-server",
|
"actix-server",
|
||||||
"actix-server-config",
|
"actix-server-config",
|
||||||
"actix-test-server",
|
"actix-test-server",
|
||||||
|
"actix-threadpool",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"router",
|
"router",
|
||||||
]
|
]
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## [0.1.0] - 2019-03-06
|
## [0.1.2] - 2019-03-27
|
||||||
|
|
||||||
|
* Added `Framed::map_io()` method.
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.1] - 2019-03-06
|
||||||
|
|
||||||
* Added `FramedParts::with_read_buffer()` method.
|
* Added `FramedParts::with_read_buffer()` method.
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-codec"
|
name = "actix-codec"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Utilities for encoding and decoding frames"
|
description = "Utilities for encoding and decoding frames"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
@@ -11,15 +11,15 @@ categories = ["network-programming", "asynchronous"]
|
|||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
workspace = "../"
|
workspace = ".."
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "actix_codec"
|
name = "actix_codec"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = "0.4"
|
bytes = "0.4.12"
|
||||||
futures = "0.1.24"
|
futures = "0.1.24"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1.12"
|
||||||
tokio-codec = "0.1"
|
tokio-codec = "0.1.1"
|
||||||
log = "0.4"
|
log = "0.4"
|
@@ -167,6 +167,22 @@ impl<T, U> Framed<T, U> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Consume the `Frame`, returning `Frame` with different io.
|
||||||
|
pub fn map_io<F, T2>(self, f: F) -> Framed<T2, U>
|
||||||
|
where
|
||||||
|
F: Fn(T) -> T2,
|
||||||
|
{
|
||||||
|
let (inner, read_buf) = self.inner.into_parts();
|
||||||
|
let (inner, write_buf, lw, hw) = inner.into_parts();
|
||||||
|
|
||||||
|
Framed {
|
||||||
|
inner: framed_read2_with_buffer(
|
||||||
|
framed_write2_with_buffer(Fuse(f(inner.0), inner.1), write_buf, lw, hw),
|
||||||
|
read_buf,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Consume the `Frame`, returning `Frame` with different codec.
|
/// Consume the `Frame`, returning `Frame` with different codec.
|
||||||
pub fn map_codec<F, U2>(self, f: F) -> Framed<T, U2>
|
pub fn map_codec<F, U2>(self, f: F) -> Framed<T, U2>
|
||||||
where
|
where
|
||||||
|
@@ -1,5 +1,36 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [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
|
||||||
|
|
||||||
|
* Rename connect Connector to TcpConnector #10
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.1] - 2019-03-15
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix error handling for single address
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0] - 2019-03-14
|
## [0.1.0] - 2019-03-14
|
||||||
|
|
||||||
* Refactor resolver and connector services
|
* Refactor resolver and connector services
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-connect"
|
name = "actix-connect"
|
||||||
version = "0.1.0"
|
version = "0.1.4"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix Connector - tcp connector service"
|
description = "Actix Connector - tcp connector service"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
@@ -30,9 +30,9 @@ ssl = ["openssl", "tokio-openssl"]
|
|||||||
uri = ["http"]
|
uri = ["http"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-service = "0.3.4"
|
actix-service = "0.3.6"
|
||||||
actix-codec = "0.1.1"
|
actix-codec = "0.1.2"
|
||||||
actix-utils = "0.3.4"
|
actix-utils = "0.3.5"
|
||||||
derive_more = "0.14.0"
|
derive_more = "0.14.0"
|
||||||
either = "1.5.1"
|
either = "1.5.1"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
@@ -40,7 +40,7 @@ http = { version = "0.1.16", optional = true }
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
tokio-tcp = "0.1.3"
|
tokio-tcp = "0.1.3"
|
||||||
tokio-current-thread = "0.1.5"
|
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-alpha.3", default-features = false }
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
openssl = { version="0.10", optional = true }
|
openssl = { version="0.10", optional = true }
|
||||||
@@ -48,8 +48,7 @@ tokio-openssl = { version="0.3", optional = true }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
actix-connect = { path=".", features=["ssl"] }
|
actix-test-server = { version="0.2.1", features=["ssl"] }
|
||||||
actix-test-server = { version="0.2.0", features=["ssl"] }
|
|
||||||
actix-server-config = "0.1.0"
|
actix-server-config = "0.1.0"
|
||||||
actix-utils = "0.3.4"
|
actix-utils = "0.3.4"
|
||||||
tokio-tcp = "0.1"
|
tokio-tcp = "0.1"
|
@@ -12,54 +12,54 @@ use super::error::ConnectError;
|
|||||||
|
|
||||||
/// Tcp connector service factory
|
/// Tcp connector service factory
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConnectorFactory<T>(PhantomData<T>);
|
pub struct TcpConnectorFactory<T>(PhantomData<T>);
|
||||||
|
|
||||||
impl<T> ConnectorFactory<T> {
|
impl<T> TcpConnectorFactory<T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ConnectorFactory(PhantomData)
|
TcpConnectorFactory(PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Clone for ConnectorFactory<T> {
|
impl<T> Clone for TcpConnectorFactory<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
ConnectorFactory(PhantomData)
|
TcpConnectorFactory(PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Address> NewService for ConnectorFactory<T> {
|
impl<T: Address> NewService for TcpConnectorFactory<T> {
|
||||||
type Request = Connect<T>;
|
type Request = Connect<T>;
|
||||||
type Response = Connection<T, TcpStream>;
|
type Response = Connection<T, TcpStream>;
|
||||||
type Error = ConnectError;
|
type Error = ConnectError;
|
||||||
type Service = Connector<T>;
|
type Service = TcpConnector<T>;
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
type Future = FutureResult<Self::Service, Self::InitError>;
|
||||||
|
|
||||||
fn new_service(&self, _: &()) -> Self::Future {
|
fn new_service(&self, _: &()) -> Self::Future {
|
||||||
ok(Connector(PhantomData))
|
ok(TcpConnector(PhantomData))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tcp connector service
|
/// Tcp connector service
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Connector<T>(PhantomData<T>);
|
pub struct TcpConnector<T>(PhantomData<T>);
|
||||||
|
|
||||||
impl<T> Connector<T> {
|
impl<T> TcpConnector<T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Connector(PhantomData)
|
TcpConnector(PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Clone for Connector<T> {
|
impl<T> Clone for TcpConnector<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Connector(PhantomData)
|
TcpConnector(PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Address> Service for Connector<T> {
|
impl<T: Address> Service for TcpConnector<T> {
|
||||||
type Request = Connect<T>;
|
type Request = Connect<T>;
|
||||||
type Response = Connection<T, TcpStream>;
|
type Response = Connection<T, TcpStream>;
|
||||||
type Error = ConnectError;
|
type Error = ConnectError;
|
||||||
type Future = Either<ConnectorResponse<T>, FutureResult<Self::Response, Self::Error>>;
|
type Future = Either<TcpConnectorResponse<T>, FutureResult<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
Ok(Async::Ready(()))
|
Ok(Async::Ready(()))
|
||||||
@@ -70,7 +70,7 @@ impl<T: Address> Service for Connector<T> {
|
|||||||
let Connect { req, addr, .. } = req;
|
let Connect { req, addr, .. } = req;
|
||||||
|
|
||||||
if let Some(addr) = addr {
|
if let Some(addr) = addr {
|
||||||
Either::A(ConnectorResponse::new(req, port, addr))
|
Either::A(TcpConnectorResponse::new(req, port, addr))
|
||||||
} else {
|
} else {
|
||||||
error!("TCP connector: got unresolved address");
|
error!("TCP connector: got unresolved address");
|
||||||
Either::B(err(ConnectError::Unresolverd))
|
Either::B(err(ConnectError::Unresolverd))
|
||||||
@@ -80,19 +80,19 @@ impl<T: Address> Service for Connector<T> {
|
|||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Tcp stream connector response future
|
/// Tcp stream connector response future
|
||||||
pub struct ConnectorResponse<T> {
|
pub struct TcpConnectorResponse<T> {
|
||||||
req: Option<T>,
|
req: Option<T>,
|
||||||
port: u16,
|
port: u16,
|
||||||
addrs: Option<VecDeque<SocketAddr>>,
|
addrs: Option<VecDeque<SocketAddr>>,
|
||||||
stream: Option<ConnectFuture>,
|
stream: Option<ConnectFuture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Address> ConnectorResponse<T> {
|
impl<T: Address> TcpConnectorResponse<T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
req: T,
|
req: T,
|
||||||
port: u16,
|
port: u16,
|
||||||
addr: either::Either<SocketAddr, VecDeque<SocketAddr>>,
|
addr: either::Either<SocketAddr, VecDeque<SocketAddr>>,
|
||||||
) -> ConnectorResponse<T> {
|
) -> TcpConnectorResponse<T> {
|
||||||
trace!(
|
trace!(
|
||||||
"TCP connector - connecting to {:?} port:{}",
|
"TCP connector - connecting to {:?} port:{}",
|
||||||
req.host(),
|
req.host(),
|
||||||
@@ -100,13 +100,13 @@ impl<T: Address> ConnectorResponse<T> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
match addr {
|
match addr {
|
||||||
either::Either::Left(addr) => ConnectorResponse {
|
either::Either::Left(addr) => TcpConnectorResponse {
|
||||||
req: Some(req),
|
req: Some(req),
|
||||||
port,
|
port,
|
||||||
addrs: None,
|
addrs: None,
|
||||||
stream: Some(TcpStream::connect(&addr)),
|
stream: Some(TcpStream::connect(&addr)),
|
||||||
},
|
},
|
||||||
either::Either::Right(addrs) => ConnectorResponse {
|
either::Either::Right(addrs) => TcpConnectorResponse {
|
||||||
req: Some(req),
|
req: Some(req),
|
||||||
port,
|
port,
|
||||||
addrs: Some(addrs),
|
addrs: Some(addrs),
|
||||||
@@ -116,7 +116,7 @@ impl<T: Address> ConnectorResponse<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Address> Future for ConnectorResponse<T> {
|
impl<T: Address> Future for TcpConnectorResponse<T> {
|
||||||
type Item = Connection<T, TcpStream>;
|
type Item = Connection<T, TcpStream>;
|
||||||
type Error = ConnectError;
|
type Error = ConnectError;
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ impl<T: Address> Future for ConnectorResponse<T> {
|
|||||||
self.req.as_ref().unwrap().host(),
|
self.req.as_ref().unwrap().host(),
|
||||||
self.port,
|
self.port,
|
||||||
);
|
);
|
||||||
if self.addrs.as_ref().unwrap().is_empty() {
|
if self.addrs.is_none() || self.addrs.as_ref().unwrap().is_empty() {
|
||||||
return Err(err.into());
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
mod connect;
|
mod connect;
|
||||||
mod connector;
|
mod connector;
|
||||||
mod error;
|
mod error;
|
||||||
@@ -17,17 +19,28 @@ pub mod ssl;
|
|||||||
#[cfg(feature = "uri")]
|
#[cfg(feature = "uri")]
|
||||||
mod 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 trust_dns_resolver::{error::ResolveError, AsyncResolver};
|
||||||
|
|
||||||
pub use self::connect::{Address, Connect, Connection};
|
pub use self::connect::{Address, Connect, Connection};
|
||||||
pub use self::connector::{Connector, ConnectorFactory};
|
pub use self::connector::{TcpConnector, TcpConnectorFactory};
|
||||||
pub use self::error::ConnectError;
|
pub use self::error::ConnectError;
|
||||||
pub use self::resolver::{Resolver, ResolverFactory};
|
pub use self::resolver::{Resolver, ResolverFactory};
|
||||||
|
|
||||||
use actix_service::{NewService, Service, ServiceExt};
|
use actix_service::{NewService, Service, ServiceExt};
|
||||||
use tokio_tcp::TcpStream;
|
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`")]
|
||||||
|
pub type Connector<T> = TcpConnector<T>;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.1.2",
|
||||||
|
note = "please use `actix_connect::TcpConnectorFactory`"
|
||||||
|
)]
|
||||||
|
pub type ConnectorFactory<T> = TcpConnectorFactory<T>;
|
||||||
|
|
||||||
pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> AsyncResolver {
|
pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> AsyncResolver {
|
||||||
let (resolver, bg) = AsyncResolver::new(cfg, opts);
|
let (resolver, bg) = AsyncResolver::new(cfg, opts);
|
||||||
@@ -35,16 +48,34 @@ pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> AsyncResolver
|
|||||||
resolver
|
resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_default_resolver() -> AsyncResolver {
|
thread_local! {
|
||||||
let (cfg, opts) = if let Ok((cfg, opts)) = read_system_conf() {
|
static DEFAULT_RESOLVER: RefCell<Option<AsyncResolver>> = RefCell::new(None);
|
||||||
(cfg, opts)
|
}
|
||||||
} else {
|
|
||||||
|
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())
|
(ResolverConfig::default(), ResolverOpts::default())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (resolver, bg) = AsyncResolver::new(cfg, opts);
|
let (resolver, bg) = AsyncResolver::new(cfg, opts);
|
||||||
tokio_current_thread::spawn(bg);
|
tokio_current_thread::spawn(bg);
|
||||||
|
|
||||||
|
*cell.borrow_mut() = Some(resolver.clone());
|
||||||
resolver
|
resolver
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_default_resolver() -> AsyncResolver {
|
||||||
|
get_default_resolver()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create tcp connector service
|
/// Create tcp connector service
|
||||||
@@ -52,7 +83,7 @@ pub fn new_connector<T: Address>(
|
|||||||
resolver: AsyncResolver,
|
resolver: AsyncResolver,
|
||||||
) -> impl Service<Request = Connect<T>, Response = Connection<T, TcpStream>, Error = ConnectError>
|
) -> impl Service<Request = Connect<T>, Response = Connection<T, TcpStream>, Error = ConnectError>
|
||||||
+ Clone {
|
+ Clone {
|
||||||
Resolver::new(resolver).and_then(Connector::new())
|
Resolver::new(resolver).and_then(TcpConnector::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create tcp connector service
|
/// Create tcp connector service
|
||||||
@@ -64,14 +95,14 @@ pub fn new_connector_factory<T: Address>(
|
|||||||
Error = ConnectError,
|
Error = ConnectError,
|
||||||
InitError = (),
|
InitError = (),
|
||||||
> + Clone {
|
> + Clone {
|
||||||
ResolverFactory::new(resolver).and_then(ConnectorFactory::new())
|
ResolverFactory::new(resolver).and_then(TcpConnectorFactory::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create connector service with default parameters
|
/// Create connector service with default parameters
|
||||||
pub fn default_connector<T: Address>(
|
pub fn default_connector<T: Address>(
|
||||||
) -> impl Service<Request = Connect<T>, Response = Connection<T, TcpStream>, Error = ConnectError>
|
) -> impl Service<Request = Connect<T>, Response = Connection<T, TcpStream>, Error = ConnectError>
|
||||||
+ Clone {
|
+ Clone {
|
||||||
Resolver::new(start_default_resolver()).and_then(Connector::new())
|
Resolver::default().and_then(TcpConnector::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create connector service factory with default parameters
|
/// Create connector service factory with default parameters
|
||||||
@@ -81,5 +112,5 @@ pub fn default_connector_factory<T: Address>() -> impl NewService<
|
|||||||
Error = ConnectError,
|
Error = ConnectError,
|
||||||
InitError = (),
|
InitError = (),
|
||||||
> + Clone {
|
> + Clone {
|
||||||
ResolverFactory::new(start_default_resolver()).and_then(ConnectorFactory::new())
|
ResolverFactory::default().and_then(TcpConnectorFactory::new())
|
||||||
}
|
}
|
||||||
|
@@ -10,10 +10,11 @@ use trust_dns_resolver::{AsyncResolver, Background};
|
|||||||
|
|
||||||
use crate::connect::{Address, Connect};
|
use crate::connect::{Address, Connect};
|
||||||
use crate::error::ConnectError;
|
use crate::error::ConnectError;
|
||||||
|
use crate::get_default_resolver;
|
||||||
|
|
||||||
/// DNS Resolver Service factory
|
/// DNS Resolver Service factory
|
||||||
pub struct ResolverFactory<T> {
|
pub struct ResolverFactory<T> {
|
||||||
resolver: AsyncResolver,
|
resolver: Option<AsyncResolver>,
|
||||||
_t: PhantomData<T>,
|
_t: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,13 +22,18 @@ impl<T> ResolverFactory<T> {
|
|||||||
/// Create new resolver instance with custom configuration and options.
|
/// Create new resolver instance with custom configuration and options.
|
||||||
pub fn new(resolver: AsyncResolver) -> Self {
|
pub fn new(resolver: AsyncResolver) -> Self {
|
||||||
ResolverFactory {
|
ResolverFactory {
|
||||||
resolver,
|
resolver: Some(resolver),
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolver(&self) -> &AsyncResolver {
|
impl<T> Default for ResolverFactory<T> {
|
||||||
&self.resolver
|
fn default() -> Self {
|
||||||
|
ResolverFactory {
|
||||||
|
resolver: None,
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +64,7 @@ impl<T: Address> NewService for ResolverFactory<T> {
|
|||||||
|
|
||||||
/// DNS Resolver Service
|
/// DNS Resolver Service
|
||||||
pub struct Resolver<T> {
|
pub struct Resolver<T> {
|
||||||
resolver: AsyncResolver,
|
resolver: Option<AsyncResolver>,
|
||||||
_t: PhantomData<T>,
|
_t: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +72,16 @@ impl<T> Resolver<T> {
|
|||||||
/// Create new resolver instance with custom configuration and options.
|
/// Create new resolver instance with custom configuration and options.
|
||||||
pub fn new(resolver: AsyncResolver) -> Self {
|
pub fn new(resolver: AsyncResolver) -> Self {
|
||||||
Resolver {
|
Resolver {
|
||||||
resolver,
|
resolver: Some(resolver),
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Resolver<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Resolver {
|
||||||
|
resolver: None,
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +115,10 @@ impl<T: Address> Service for Resolver<T> {
|
|||||||
Either::B(ok(req))
|
Either::B(ok(req))
|
||||||
} else {
|
} else {
|
||||||
trace!("DNS resolver: resolving host {:?}", req.host());
|
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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +171,9 @@ impl<T: Address> Future for ResolverFuture<T> {
|
|||||||
req.host(),
|
req.host(),
|
||||||
addrs
|
addrs
|
||||||
);
|
);
|
||||||
if addrs.len() == 1 {
|
if addrs.is_empty() {
|
||||||
|
Err(ConnectError::NoRecords)
|
||||||
|
} else if addrs.len() == 1 {
|
||||||
req.addr = Some(either::Either::Left(addrs.pop_front().unwrap()));
|
req.addr = Some(either::Either::Left(addrs.pop_front().unwrap()));
|
||||||
Ok(Async::Ready(req))
|
Ok(Async::Ready(req))
|
||||||
} else {
|
} else {
|
||||||
|
@@ -26,6 +26,7 @@ fn port(scheme: Option<&str>) -> Option<u16> {
|
|||||||
"wss" => Some(443),
|
"wss" => Some(443),
|
||||||
"amqp" => Some(5672),
|
"amqp" => Some(5672),
|
||||||
"amqps" => Some(5671),
|
"amqps" => Some(5671),
|
||||||
|
"sb" => Some(5671),
|
||||||
"mqtt" => Some(1883),
|
"mqtt" => Some(1883),
|
||||||
"mqtts" => Some(8883),
|
"mqtts" => Some(8883),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@@ -9,6 +9,7 @@ use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
|
|||||||
|
|
||||||
use actix_connect::{default_connector, Connect};
|
use actix_connect::{default_connector, Connect};
|
||||||
|
|
||||||
|
#[cfg(feature = "ssl")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_string() {
|
fn test_string() {
|
||||||
let mut srv = TestServer::with(|| {
|
let mut srv = TestServer::with(|| {
|
||||||
@@ -19,11 +20,9 @@ fn test_string() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut conn = srv
|
let mut conn = default_connector();
|
||||||
.block_on(lazy(|| Ok::<_, ()>(default_connector())))
|
|
||||||
.unwrap();
|
|
||||||
let addr = format!("localhost:{}", srv.port());
|
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());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,13 +42,22 @@ fn test_static_str() {
|
|||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut conn = srv
|
let mut conn = srv
|
||||||
.block_on(lazy(|| Ok::<_, ()>(actix_connect::new_connector(resolver))))
|
.block_on(lazy(|| {
|
||||||
|
Ok::<_, ()>(actix_connect::new_connector(resolver.clone()))
|
||||||
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let con = srv
|
let con = srv
|
||||||
.block_on(conn.call(Connect::with("10", srv.addr())))
|
.block_on(conn.call(Connect::with("10", srv.addr())))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
|
|
||||||
|
let connect = Connect::new(srv.host().to_owned());
|
||||||
|
let mut conn = srv
|
||||||
|
.block_on(lazy(|| Ok::<_, ()>(actix_connect::new_connector(resolver))))
|
||||||
|
.unwrap();
|
||||||
|
let con = srv.block_on(conn.call(connect));
|
||||||
|
assert!(con.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -83,6 +91,7 @@ fn test_new_service() {
|
|||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssl")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uri() {
|
fn test_uri() {
|
||||||
let mut srv = TestServer::with(|| {
|
let mut srv = TestServer::with(|| {
|
||||||
@@ -93,10 +102,8 @@ fn test_uri() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut conn = srv
|
let mut conn = default_connector();
|
||||||
.block_on(lazy(|| Ok::<_, ()>(default_connector())))
|
|
||||||
.unwrap();
|
|
||||||
let addr = Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
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());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.2.2] - 2019-03-28
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Moved `blocking` module to `actix-threadpool` crate
|
||||||
|
|
||||||
## [0.2.1] - 2019-03-11
|
## [0.2.1] - 2019-03-11
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-rt"
|
name = "actix-rt"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix runtime"
|
description = "Actix runtime"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
@@ -11,21 +11,15 @@ categories = ["network-programming", "asynchronous"]
|
|||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
workspace = "../"
|
workspace = ".."
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "actix_rt"
|
name = "actix_rt"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = "0.4"
|
actix-threadpool = "0.1.0"
|
||||||
derive_more = "0.14"
|
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
parking_lot = "0.7"
|
|
||||||
lazy_static = "1.2"
|
|
||||||
log = "0.4"
|
|
||||||
num_cpus = "1.10"
|
|
||||||
threadpool = "1.7"
|
|
||||||
tokio-current-thread = "0.1"
|
tokio-current-thread = "0.1"
|
||||||
tokio-executor = "0.1.5"
|
tokio-executor = "0.1.5"
|
||||||
tokio-reactor = "0.1.7"
|
tokio-reactor = "0.1.7"
|
||||||
|
@@ -86,8 +86,7 @@ impl Builder {
|
|||||||
let (stop_tx, stop) = channel();
|
let (stop_tx, stop) = channel();
|
||||||
let (sys_sender, sys_receiver) = unbounded();
|
let (sys_sender, sys_receiver) = unbounded();
|
||||||
|
|
||||||
let arbiter = Arbiter::new_system();
|
let system = System::construct(sys_sender, Arbiter::new_system(), self.stop_on_panic);
|
||||||
let system = System::construct(sys_sender, arbiter.clone(), self.stop_on_panic);
|
|
||||||
|
|
||||||
// system arbiter
|
// system arbiter
|
||||||
let arb = SystemArbiter::new(stop_tx, sys_receiver);
|
let arb = SystemArbiter::new(stop_tx, sys_receiver);
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
//! A runtime implementation that runs everything on the current thread.
|
//! A runtime implementation that runs everything on the current thread.
|
||||||
|
|
||||||
mod arbiter;
|
mod arbiter;
|
||||||
pub mod blocking;
|
|
||||||
mod builder;
|
mod builder;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod system;
|
mod system;
|
||||||
@@ -11,6 +10,9 @@ pub use self::builder::{Builder, SystemRunner};
|
|||||||
pub use self::runtime::Runtime;
|
pub use self::runtime::Runtime;
|
||||||
pub use self::system::System;
|
pub use self::system::System;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use actix_threadpool as blocking;
|
||||||
|
|
||||||
/// Spawns a future on the current arbiter.
|
/// Spawns a future on the current arbiter.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@@ -1,5 +1,12 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.4.2] - 2019-03-30
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix SIGINT force shutdown
|
||||||
|
|
||||||
|
|
||||||
## [0.4.1] - 2019-03-14
|
## [0.4.1] - 2019-03-14
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-server"
|
name = "actix-server"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix server - General purpose tcp server"
|
description = "Actix server - General purpose tcp server"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
|
@@ -328,7 +328,7 @@ impl ServerBuilder {
|
|||||||
self.accept.send(Command::Stop);
|
self.accept.send(Command::Stop);
|
||||||
|
|
||||||
// stop workers
|
// stop workers
|
||||||
if !self.workers.is_empty() {
|
if !self.workers.is_empty() && graceful {
|
||||||
spawn(
|
spawn(
|
||||||
futures_unordered(
|
futures_unordered(
|
||||||
self.workers
|
self.workers
|
||||||
|
@@ -1,5 +1,19 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.3.6] - 2019-04-07
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Poll boxed service call result immediately
|
||||||
|
|
||||||
|
|
||||||
|
## [0.3.5] - 2019-03-29
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add `impl<S: Service> Service for Rc<RefCell<S>>`
|
||||||
|
|
||||||
|
|
||||||
## [0.3.4] - 2019-03-12
|
## [0.3.4] - 2019-03-12
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-service"
|
name = "actix-service"
|
||||||
version = "0.3.4"
|
version = "0.3.6"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix Service"
|
description = "Actix Service"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
|
use futures::future::{err, ok, Either, FutureResult};
|
||||||
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
use crate::{NewService, Service};
|
use crate::{NewService, Service};
|
||||||
use futures::{Future, IntoFuture, Poll};
|
|
||||||
|
|
||||||
pub type BoxedService<Req, Res, Err> = Box<
|
pub type BoxedService<Req, Res, Err> = Box<
|
||||||
Service<
|
Service<
|
||||||
Request = Req,
|
Request = Req,
|
||||||
Response = Res,
|
Response = Res,
|
||||||
Error = Err,
|
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 Request = Req;
|
||||||
type Response = Res;
|
type Response = Res;
|
||||||
type Error = Err;
|
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> {
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
self.0.poll_ready()
|
self.0.poll_ready()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
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)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -391,6 +392,24 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S> Service for Rc<RefCell<S>>
|
||||||
|
where
|
||||||
|
S: Service,
|
||||||
|
{
|
||||||
|
type Request = S::Request;
|
||||||
|
type Response = S::Response;
|
||||||
|
type Error = S::Error;
|
||||||
|
type Future = S::Future;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self) -> Poll<(), S::Error> {
|
||||||
|
self.borrow_mut().poll_ready()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, request: Self::Request) -> S::Future {
|
||||||
|
self.borrow_mut().call(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S, C> NewService<C> for Rc<S>
|
impl<S, C> NewService<C> for Rc<S>
|
||||||
where
|
where
|
||||||
S: NewService<C>,
|
S: NewService<C>,
|
||||||
|
@@ -6,9 +6,16 @@ use futures::{Async, Future, IntoFuture, Poll};
|
|||||||
use crate::transform_err::{TransformFromErr, TransformMapInitErr};
|
use crate::transform_err::{TransformFromErr, TransformMapInitErr};
|
||||||
use crate::{IntoNewService, NewService, Service};
|
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.
|
/// `Config` is a service factory configuration type.
|
||||||
pub trait Transform<S> {
|
pub trait Transform<S> {
|
||||||
/// Requests handled by the service.
|
/// Requests handled by the service.
|
||||||
@@ -33,7 +40,7 @@ pub trait Transform<S> {
|
|||||||
/// The future response value.
|
/// The future response value.
|
||||||
type Future: Future<Item = Self::Transform, Error = Self::InitError>;
|
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;
|
fn new_transform(&self, service: S) -> Self::Future;
|
||||||
|
|
||||||
/// Map this service's factory error to a different error,
|
/// Map this service's factory error to a different error,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-test-server"
|
name = "actix-test-server"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix test server"
|
description = "Actix test server"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
|
@@ -6,7 +6,7 @@ use actix_rt::{Runtime, System};
|
|||||||
use actix_server::{Server, StreamServiceFactory};
|
use actix_server::{Server, StreamServiceFactory};
|
||||||
pub use actix_server_config::{Io, ServerConfig};
|
pub use actix_server_config::{Io, ServerConfig};
|
||||||
|
|
||||||
use futures::Future;
|
use futures::future::{lazy, Future, IntoFuture};
|
||||||
use net2::TcpBuilder;
|
use net2::TcpBuilder;
|
||||||
use tokio_reactor::Handle;
|
use tokio_reactor::Handle;
|
||||||
use tokio_tcp::TcpStream;
|
use tokio_tcp::TcpStream;
|
||||||
@@ -99,6 +99,15 @@ impl TestServerRuntime {
|
|||||||
self.rt.block_on(fut)
|
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
|
/// Spawn future to the current runtime
|
||||||
pub fn spawn<F>(&mut self, fut: F)
|
pub fn spawn<F>(&mut self, fut: F)
|
||||||
where
|
where
|
||||||
|
5
actix-threadpool/CHANGES.md
Normal file
5
actix-threadpool/CHANGES.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Changes
|
||||||
|
|
||||||
|
## [0.1.0] - 2019-03-28
|
||||||
|
|
||||||
|
* Move threadpool to separate crate
|
27
actix-threadpool/Cargo.toml
Normal file
27
actix-threadpool/Cargo.toml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "actix-threadpool"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
|
description = "Actix thread pool for sync code"
|
||||||
|
keywords = ["actix", "network", "framework", "async", "futures"]
|
||||||
|
homepage = "https://actix.rs"
|
||||||
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
|
documentation = "https://docs.rs/actix-threadpool/"
|
||||||
|
categories = ["network-programming", "asynchronous"]
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||||
|
edition = "2018"
|
||||||
|
workspace = ".."
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "actix_threadpool"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
derive_more = "0.14"
|
||||||
|
futures = "0.1.25"
|
||||||
|
parking_lot = "0.7"
|
||||||
|
lazy_static = "1.2"
|
||||||
|
log = "0.4"
|
||||||
|
num_cpus = "1.10"
|
||||||
|
threadpool = "1.7"
|
@@ -9,7 +9,7 @@ use parking_lot::Mutex;
|
|||||||
use threadpool::ThreadPool;
|
use threadpool::ThreadPool;
|
||||||
|
|
||||||
/// Env variable for default cpu pool size
|
/// Env variable for default cpu pool size
|
||||||
const ENV_CPU_POOL_VAR: &str = "ACTIX_CPU_POOL";
|
const ENV_CPU_POOL_VAR: &str = "ACTIX_THREADPOOL";
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub(crate) static ref DEFAULT_POOL: Mutex<ThreadPool> = {
|
pub(crate) static ref DEFAULT_POOL: Mutex<ThreadPool> = {
|
||||||
@@ -18,7 +18,7 @@ lazy_static::lazy_static! {
|
|||||||
if let Ok(val) = val.parse() {
|
if let Ok(val) = val.parse() {
|
||||||
val
|
val
|
||||||
} else {
|
} else {
|
||||||
log::error!("Can not parse ACTIX_CPU_POOL value");
|
log::error!("Can not parse ACTIX_THREADPOOL value");
|
||||||
num_cpus::get() * 5
|
num_cpus::get() * 5
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,17 @@
|
|||||||
# Changes
|
# 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
|
## [0.3.4] - 2019-03-12
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-utils"
|
name = "actix-utils"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix utils - various actix net related services"
|
description = "Actix utils - various actix net related services"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
|
@@ -7,12 +7,12 @@ use futures::Poll;
|
|||||||
use super::cell::Cell;
|
use super::cell::Cell;
|
||||||
|
|
||||||
/// Service that allows to turn non-clone service to a service with `Clone` impl
|
/// 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>,
|
service: Cell<T>,
|
||||||
_t: PhantomData<Rc<()>>,
|
_t: PhantomData<Rc<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> CloneableService<T> {
|
impl<T> CloneableService<T> {
|
||||||
pub fn new(service: T) -> Self
|
pub fn new(service: T) -> Self
|
||||||
where
|
where
|
||||||
T: Service,
|
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 {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
service: self.service.clone(),
|
service: self.service.clone(),
|
||||||
@@ -35,7 +35,7 @@ impl<T: 'static> Clone for CloneableService<T> {
|
|||||||
|
|
||||||
impl<T> Service for CloneableService<T>
|
impl<T> Service for CloneableService<T>
|
||||||
where
|
where
|
||||||
T: Service + 'static,
|
T: Service,
|
||||||
{
|
{
|
||||||
type Request = T::Request;
|
type Request = T::Request;
|
||||||
type Response = T::Response;
|
type Response = T::Response;
|
||||||
|
@@ -7,6 +7,7 @@ use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed};
|
|||||||
use actix_service::{IntoNewService, IntoService, NewService, Service};
|
use actix_service::{IntoNewService, IntoService, NewService, Service};
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, FutureResult};
|
||||||
use futures::task::AtomicTask;
|
use futures::task::AtomicTask;
|
||||||
|
use futures::unsync::mpsc;
|
||||||
use futures::{Async, Future, IntoFuture, Poll, Sink, Stream};
|
use futures::{Async, Future, IntoFuture, Poll, Sink, Stream};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
@@ -178,6 +179,11 @@ impl<E, U: Encoder + Decoder> From<E> for FramedTransportError<E, U> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum FramedMessage<T> {
|
||||||
|
Message(T),
|
||||||
|
Close,
|
||||||
|
}
|
||||||
|
|
||||||
/// FramedTransport - is a future that reads frames from Framed object
|
/// FramedTransport - is a future that reads frames from Framed object
|
||||||
/// and pass then to the service.
|
/// and pass then to the service.
|
||||||
pub struct FramedTransport<S, T, U>
|
pub struct FramedTransport<S, T, U>
|
||||||
@@ -193,6 +199,7 @@ where
|
|||||||
service: S,
|
service: S,
|
||||||
state: TransportState<S, U>,
|
state: TransportState<S, U>,
|
||||||
framed: Framed<T, U>,
|
framed: Framed<T, U>,
|
||||||
|
rx: Option<mpsc::UnboundedReceiver<FramedMessage<<U as Encoder>::Item>>>,
|
||||||
inner: Cell<FramedTransportInner<<U as Encoder>::Item, S::Error>>,
|
inner: Cell<FramedTransportInner<<U as Encoder>::Item, S::Error>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +207,7 @@ enum TransportState<S: Service, U: Encoder + Decoder> {
|
|||||||
Processing,
|
Processing,
|
||||||
Error(FramedTransportError<S::Error, U>),
|
Error(FramedTransportError<S::Error, U>),
|
||||||
FramedError(FramedTransportError<S::Error, U>),
|
FramedError(FramedTransportError<S::Error, U>),
|
||||||
|
FlushAndStop,
|
||||||
Stopping,
|
Stopping,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,10 +265,12 @@ where
|
|||||||
/// write to framed object
|
/// write to framed object
|
||||||
fn poll_write(&mut self) -> bool {
|
fn poll_write(&mut self) -> bool {
|
||||||
let inner = self.inner.get_mut();
|
let inner = self.inner.get_mut();
|
||||||
|
let mut rx_done = self.rx.is_none();
|
||||||
|
let mut buf_empty = inner.buf.is_empty();
|
||||||
loop {
|
loop {
|
||||||
while !self.framed.is_write_buf_full() {
|
while !self.framed.is_write_buf_full() {
|
||||||
if let Some(msg) = inner.buf.pop_front() {
|
if !buf_empty {
|
||||||
match msg {
|
match inner.buf.pop_front().unwrap() {
|
||||||
Ok(msg) => {
|
Ok(msg) => {
|
||||||
if let Err(err) = self.framed.force_send(msg) {
|
if let Err(err) = self.framed.force_send(msg) {
|
||||||
self.state = TransportState::FramedError(
|
self.state = TransportState::FramedError(
|
||||||
@@ -268,6 +278,7 @@ where
|
|||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
buf_empty = inner.buf.is_empty();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.state =
|
self.state =
|
||||||
@@ -275,7 +286,33 @@ where
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if !rx_done && self.rx.is_some() {
|
||||||
|
match self.rx.as_mut().unwrap().poll() {
|
||||||
|
Ok(Async::Ready(Some(FramedMessage::Message(msg)))) => {
|
||||||
|
if let Err(err) = self.framed.force_send(msg) {
|
||||||
|
self.state = TransportState::FramedError(
|
||||||
|
FramedTransportError::Encoder(err),
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Async::Ready(Some(FramedMessage::Close))) => {
|
||||||
|
self.state = TransportState::FlushAndStop;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Ok(Async::Ready(None)) => {
|
||||||
|
let _ = self.rx.take();
|
||||||
|
}
|
||||||
|
Ok(Async::NotReady) => rx_done = true,
|
||||||
|
Err(_e) => {
|
||||||
|
let _ = self.rx.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rx_done && buf_empty {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,6 +350,7 @@ where
|
|||||||
pub fn new<F: IntoService<S>>(framed: Framed<T, U>, service: F) -> Self {
|
pub fn new<F: IntoService<S>>(framed: Framed<T, U>, service: F) -> Self {
|
||||||
FramedTransport {
|
FramedTransport {
|
||||||
framed,
|
framed,
|
||||||
|
rx: None,
|
||||||
service: service.into_service(),
|
service: service.into_service(),
|
||||||
state: TransportState::Processing,
|
state: TransportState::Processing,
|
||||||
inner: Cell::new(FramedTransportInner {
|
inner: Cell::new(FramedTransportInner {
|
||||||
@@ -322,6 +360,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get Sender
|
||||||
|
pub fn set_receiver(
|
||||||
|
mut self,
|
||||||
|
rx: mpsc::UnboundedReceiver<FramedMessage<<U as Encoder>::Item>>,
|
||||||
|
) -> Self {
|
||||||
|
self.rx = Some(rx);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Get reference to a service wrapped by `FramedTransport` instance.
|
/// Get reference to a service wrapped by `FramedTransport` instance.
|
||||||
pub fn get_ref(&self) -> &S {
|
pub fn get_ref(&self) -> &S {
|
||||||
&self.service
|
&self.service
|
||||||
@@ -378,6 +425,20 @@ where
|
|||||||
Ok(Async::NotReady)
|
Ok(Async::NotReady)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TransportState::FlushAndStop => {
|
||||||
|
if !self.framed.is_write_buf_empty() {
|
||||||
|
match self.framed.poll_complete() {
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Error sending data: {:?}", err);
|
||||||
|
Ok(Async::Ready(()))
|
||||||
|
}
|
||||||
|
Ok(Async::NotReady) => Ok(Async::NotReady),
|
||||||
|
Ok(Async::Ready(_)) => Ok(Async::Ready(())),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(Async::Ready(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
TransportState::FramedError(err) => Err(err),
|
TransportState::FramedError(err) => Err(err),
|
||||||
TransportState::Stopping => Ok(Async::Ready(())),
|
TransportState::Stopping => Ok(Async::Ready(())),
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,15 @@
|
|||||||
# Changes
|
# 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.
|
||||||
|
|
||||||
## [0.1.0] - 2019-03-09
|
## [0.1.0] - 2019-03-09
|
||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-router"
|
name = "actix-router"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Path router"
|
description = "Path router"
|
||||||
keywords = ["actix"]
|
keywords = ["actix"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://actix.rs/api/actix-net/stable/actix_router/"
|
documentation = "https://docs.rs/actix-router/"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
workspace = "../"
|
workspace = ".."
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "actix_router"
|
name = "actix_router"
|
||||||
@@ -23,7 +23,8 @@ default = ["http"]
|
|||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
serde = "1.0.80"
|
serde = "1.0.80"
|
||||||
string = "0.1.3"
|
string = "0.2.0"
|
||||||
|
log = "0.4"
|
||||||
http = { version="0.1.14", optional=true }
|
http = { version="0.1.14", optional=true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@@ -39,7 +39,7 @@ impl<T: AsRef<[u8]>> ResourcePath for string::String<T> {
|
|||||||
mod url;
|
mod url;
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
pub use self::url::Url;
|
pub use self::url::{Quoter, Url};
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
mod http_support {
|
mod http_support {
|
||||||
|
@@ -51,16 +51,19 @@ impl<T: ResourcePath> Path<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Get reference to inner path instance
|
/// Get reference to inner path instance
|
||||||
pub fn get_ref(&self) -> &T {
|
pub fn get_ref(&self) -> &T {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Get mutable reference to inner path instance
|
/// Get mutable reference to inner path instance
|
||||||
pub fn get_mut(&mut self) -> &mut T {
|
pub fn get_mut(&mut self) -> &mut T {
|
||||||
&mut self.path
|
&mut self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Path
|
/// Path
|
||||||
pub fn path(&self) -> &str {
|
pub fn path(&self) -> &str {
|
||||||
let skip = self.skip as usize;
|
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) {
|
pub fn set(&mut self, path: T) {
|
||||||
self.skip = 0;
|
self.skip = 0;
|
||||||
self.path = path;
|
self.path = path;
|
||||||
self.segments.clear();
|
self.segments.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Reset state
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.skip = 0;
|
||||||
|
self.segments.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Skip first `n` chars in path
|
/// Skip first `n` chars in path
|
||||||
pub fn skip(&mut self, n: u16) {
|
pub fn skip(&mut self, n: u16) {
|
||||||
self.skip = self.skip + n;
|
self.skip = self.skip + n;
|
||||||
@@ -99,11 +111,13 @@ impl<T: ResourcePath> Path<T> {
|
|||||||
.push((Rc::new(name.to_string()), PathItem::Static(value)));
|
.push((Rc::new(name.to_string()), PathItem::Static(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Check if there are any matched patterns
|
/// Check if there are any matched patterns
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.segments.is_empty()
|
self.segments.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Check number of extracted parameters
|
/// Check number of extracted parameters
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.segments.len()
|
self.segments.len()
|
||||||
|
@@ -118,6 +118,7 @@ impl ResourceDef {
|
|||||||
&self.pattern
|
&self.pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Check if path matchs this pattern?
|
/// Check if path matchs this pattern?
|
||||||
pub fn is_match(&self, path: &str) -> bool {
|
pub fn is_match(&self, path: &str) -> bool {
|
||||||
match self.tp {
|
match self.tp {
|
||||||
@@ -196,18 +197,17 @@ impl ResourceDef {
|
|||||||
[PathItem::Static(""); MAX_DYNAMIC_SEGMENTS];
|
[PathItem::Static(""); MAX_DYNAMIC_SEGMENTS];
|
||||||
|
|
||||||
if let Some(captures) = re.captures(path.path()) {
|
if let Some(captures) = re.captures(path.path()) {
|
||||||
let mut passed = false;
|
for (no, name) in names.iter().enumerate() {
|
||||||
|
if let Some(m) = captures.name(&name) {
|
||||||
for capture in captures.iter() {
|
|
||||||
if let Some(ref m) = capture {
|
|
||||||
if !passed {
|
|
||||||
passed = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
segments[idx] = PathItem::Segment(m.start() as u16, m.end() as u16);
|
|
||||||
idx += 1;
|
idx += 1;
|
||||||
pos = m.end();
|
pos = m.end();
|
||||||
|
segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16);
|
||||||
|
} else {
|
||||||
|
log::error!(
|
||||||
|
"Dynamic path match but not all segments found: {}",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::ResourcePath;
|
use crate::ResourcePath;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -39,7 +37,7 @@ thread_local! {
|
|||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct Url {
|
pub struct Url {
|
||||||
uri: http::Uri,
|
uri: http::Uri,
|
||||||
path: Option<Rc<String>>,
|
path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Url {
|
impl Url {
|
||||||
@@ -49,6 +47,13 @@ impl Url {
|
|||||||
Url { uri, path }
|
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 {
|
pub fn uri(&self) -> &http::Uri {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
@@ -61,19 +66,27 @@ impl Url {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn update(&mut self, uri: &http::Uri) {
|
pub fn update(&mut self, uri: &http::Uri) {
|
||||||
self.uri = uri.clone();
|
self.uri = uri.clone();
|
||||||
self.path = DEFAULT_QUOTER.with(|q| q.requote(uri.path().as_bytes()));
|
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 {
|
impl ResourcePath for Url {
|
||||||
|
#[inline]
|
||||||
fn path(&self) -> &str {
|
fn path(&self) -> &str {
|
||||||
self.path()
|
self.path()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Quoter {
|
pub struct Quoter {
|
||||||
safe_table: [u8; 16],
|
safe_table: [u8; 16],
|
||||||
protected_table: [u8; 16],
|
protected_table: [u8; 16],
|
||||||
}
|
}
|
||||||
@@ -108,7 +121,7 @@ impl Quoter {
|
|||||||
q
|
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 has_pct = 0;
|
||||||
let mut pct = [b'%', 0, 0];
|
let mut pct = [b'%', 0, 0];
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
@@ -160,7 +173,7 @@ impl Quoter {
|
|||||||
if let Some(data) = cloned {
|
if let Some(data) = cloned {
|
||||||
// Unsafe: we get data from http::Uri, which does utf-8 checks already
|
// Unsafe: we get data from http::Uri, which does utf-8 checks already
|
||||||
// this code only decodes valid pct encoded values
|
// 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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user