mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into style/h1_poll_response_loop
This commit is contained in:
commit
f8de43f74c
|
@ -1,6 +1,14 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Fixed
|
||||||
|
* Double ampersand in Logger format is escaped correctly. [#2067]
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* The `client` mod was removed. Clients should now use `awc` directly.
|
||||||
|
[871ca5e4](https://github.com/actix/actix-web/commit/871ca5e4ae2bdc22d1ea02701c2992fa8d04aed7)
|
||||||
|
|
||||||
|
[#2067]: https://github.com/actix/actix-web/pull/2067
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0-beta.4 - 2021-03-09
|
## 4.0.0-beta.4 - 2021-03-09
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Chaged
|
||||||
|
* `client::Connector` type now only have one generic type for `actix_service::Service`. [#2063]
|
||||||
|
|
||||||
|
[#2063]: https://github.com/actix/actix-web/pull/2063
|
||||||
|
|
||||||
|
|
||||||
## 3.0.0-beta.4 - 2021-03-08
|
## 3.0.0-beta.4 - 2021-03-08
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
future::Future,
|
future::Future,
|
||||||
marker::PhantomData,
|
|
||||||
net::IpAddr,
|
net::IpAddr,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
|
@ -15,6 +14,7 @@ use actix_tls::connect::{
|
||||||
new_connector, Connect as TcpConnect, Connection as TcpConnection, Resolver,
|
new_connector, Connect as TcpConnect, Connection as TcpConnection, Resolver,
|
||||||
};
|
};
|
||||||
use actix_utils::timeout::{TimeoutError, TimeoutService};
|
use actix_utils::timeout::{TimeoutError, TimeoutService};
|
||||||
|
use futures_core::ready;
|
||||||
use http::Uri;
|
use http::Uri;
|
||||||
|
|
||||||
use super::config::ConnectorConfig;
|
use super::config::ConnectorConfig;
|
||||||
|
@ -54,18 +54,17 @@ type SslConnector = ();
|
||||||
/// .timeout(Duration::from_secs(5))
|
/// .timeout(Duration::from_secs(5))
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Connector<T, U> {
|
pub struct Connector<T> {
|
||||||
connector: T,
|
connector: T,
|
||||||
config: ConnectorConfig,
|
config: ConnectorConfig,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
ssl: SslConnector,
|
ssl: SslConnector,
|
||||||
_phantom: PhantomData<U>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Io: AsyncRead + AsyncWrite + Unpin {}
|
pub trait Io: AsyncRead + AsyncWrite + Unpin {}
|
||||||
impl<T: AsyncRead + AsyncWrite + Unpin> Io for T {}
|
impl<T: AsyncRead + AsyncWrite + Unpin> Io for T {}
|
||||||
|
|
||||||
impl Connector<(), ()> {
|
impl Connector<()> {
|
||||||
#[allow(clippy::new_ret_no_self, clippy::let_unit_value)]
|
#[allow(clippy::new_ret_no_self, clippy::let_unit_value)]
|
||||||
pub fn new() -> Connector<
|
pub fn new() -> Connector<
|
||||||
impl Service<
|
impl Service<
|
||||||
|
@ -73,13 +72,11 @@ impl Connector<(), ()> {
|
||||||
Response = TcpConnection<Uri, TcpStream>,
|
Response = TcpConnection<Uri, TcpStream>,
|
||||||
Error = actix_tls::connect::ConnectError,
|
Error = actix_tls::connect::ConnectError,
|
||||||
> + Clone,
|
> + Clone,
|
||||||
TcpStream,
|
|
||||||
> {
|
> {
|
||||||
Connector {
|
Connector {
|
||||||
ssl: Self::build_ssl(vec![b"h2".to_vec(), b"http/1.1".to_vec()]),
|
ssl: Self::build_ssl(vec![b"h2".to_vec(), b"http/1.1".to_vec()]),
|
||||||
connector: new_connector(resolver::resolver()),
|
connector: new_connector(resolver::resolver()),
|
||||||
config: ConnectorConfig::default(),
|
config: ConnectorConfig::default(),
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,9 +115,9 @@ impl Connector<(), ()> {
|
||||||
fn build_ssl(_: Vec<Vec<u8>>) -> SslConnector {}
|
fn build_ssl(_: Vec<Vec<u8>>) -> SslConnector {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> Connector<T, U> {
|
impl<T> Connector<T> {
|
||||||
/// Use custom connector.
|
/// Use custom connector.
|
||||||
pub fn connector<T1, U1>(self, connector: T1) -> Connector<T1, U1>
|
pub fn connector<T1, U1>(self, connector: T1) -> Connector<T1>
|
||||||
where
|
where
|
||||||
U1: AsyncRead + AsyncWrite + Unpin + fmt::Debug,
|
U1: AsyncRead + AsyncWrite + Unpin + fmt::Debug,
|
||||||
T1: Service<
|
T1: Service<
|
||||||
|
@ -133,12 +130,11 @@ impl<T, U> Connector<T, U> {
|
||||||
connector,
|
connector,
|
||||||
config: self.config,
|
config: self.config,
|
||||||
ssl: self.ssl,
|
ssl: self.ssl,
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> Connector<T, U>
|
impl<T, U> Connector<T>
|
||||||
where
|
where
|
||||||
U: AsyncRead + AsyncWrite + Unpin + fmt::Debug + 'static,
|
U: AsyncRead + AsyncWrite + Unpin + fmt::Debug + 'static,
|
||||||
T: Service<
|
T: Service<
|
||||||
|
@ -405,7 +401,11 @@ where
|
||||||
type Future = InnerConnectorResponse<S1, S2, Io1, Io2>;
|
type Future = InnerConnectorResponse<S1, S2, Io1, Io2>;
|
||||||
|
|
||||||
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
self.tcp_pool.poll_ready(cx)
|
ready!(self.tcp_pool.poll_ready(cx))?;
|
||||||
|
if let Some(ref tls_pool) = self.tls_pool {
|
||||||
|
ready!(tls_pool.poll_ready(cx))?;
|
||||||
|
}
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, req: Connect) -> Self::Future {
|
fn call(&self, req: Connect) -> Self::Future {
|
||||||
|
|
|
@ -21,14 +21,14 @@ use crate::{Client, ClientConfig, ConnectRequest, ConnectResponse, ConnectorServ
|
||||||
///
|
///
|
||||||
/// This type can be used to construct an instance of `Client` through a
|
/// This type can be used to construct an instance of `Client` through a
|
||||||
/// builder-like pattern.
|
/// builder-like pattern.
|
||||||
pub struct ClientBuilder<S = (), Io = (), M = ()> {
|
pub struct ClientBuilder<S = (), M = ()> {
|
||||||
default_headers: bool,
|
default_headers: bool,
|
||||||
max_http_version: Option<http::Version>,
|
max_http_version: Option<http::Version>,
|
||||||
stream_window_size: Option<u32>,
|
stream_window_size: Option<u32>,
|
||||||
conn_window_size: Option<u32>,
|
conn_window_size: Option<u32>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
connector: Connector<S, Io>,
|
connector: Connector<S>,
|
||||||
middleware: M,
|
middleware: M,
|
||||||
local_address: Option<IpAddr>,
|
local_address: Option<IpAddr>,
|
||||||
max_redirects: u8,
|
max_redirects: u8,
|
||||||
|
@ -42,7 +42,6 @@ impl ClientBuilder {
|
||||||
Response = TcpConnection<Uri, TcpStream>,
|
Response = TcpConnection<Uri, TcpStream>,
|
||||||
Error = TcpConnectError,
|
Error = TcpConnectError,
|
||||||
> + Clone,
|
> + Clone,
|
||||||
TcpStream,
|
|
||||||
(),
|
(),
|
||||||
> {
|
> {
|
||||||
ClientBuilder {
|
ClientBuilder {
|
||||||
|
@ -60,7 +59,7 @@ impl ClientBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, Io, M> ClientBuilder<S, Io, M>
|
impl<S, Io, M> ClientBuilder<S, M>
|
||||||
where
|
where
|
||||||
S: Service<TcpConnect<Uri>, Response = TcpConnection<Uri, Io>, Error = TcpConnectError>
|
S: Service<TcpConnect<Uri>, Response = TcpConnection<Uri, Io>, Error = TcpConnectError>
|
||||||
+ Clone
|
+ Clone
|
||||||
|
@ -68,7 +67,7 @@ where
|
||||||
Io: AsyncRead + AsyncWrite + Unpin + fmt::Debug + 'static,
|
Io: AsyncRead + AsyncWrite + Unpin + fmt::Debug + 'static,
|
||||||
{
|
{
|
||||||
/// Use custom connector service.
|
/// Use custom connector service.
|
||||||
pub fn connector<S1, Io1>(self, connector: Connector<S1, Io1>) -> ClientBuilder<S1, Io1, M>
|
pub fn connector<S1, Io1>(self, connector: Connector<S1>) -> ClientBuilder<S1, M>
|
||||||
where
|
where
|
||||||
S1: Service<
|
S1: Service<
|
||||||
TcpConnect<Uri>,
|
TcpConnect<Uri>,
|
||||||
|
@ -213,7 +212,7 @@ where
|
||||||
pub fn wrap<S1, M1>(
|
pub fn wrap<S1, M1>(
|
||||||
self,
|
self,
|
||||||
mw: M1,
|
mw: M1,
|
||||||
) -> ClientBuilder<S, Io, NestTransform<M, M1, S1, ConnectRequest>>
|
) -> ClientBuilder<S, NestTransform<M, M1, S1, ConnectRequest>>
|
||||||
where
|
where
|
||||||
M: Transform<S1, ConnectRequest>,
|
M: Transform<S1, ConnectRequest>,
|
||||||
M1: Transform<M::Transform, ConnectRequest>,
|
M1: Transform<M::Transform, ConnectRequest>,
|
||||||
|
|
|
@ -175,7 +175,6 @@ impl Client {
|
||||||
Response = TcpConnection<Uri, TcpStream>,
|
Response = TcpConnection<Uri, TcpStream>,
|
||||||
Error = TcpConnectError,
|
Error = TcpConnectError,
|
||||||
> + Clone,
|
> + Clone,
|
||||||
TcpStream,
|
|
||||||
> {
|
> {
|
||||||
ClientBuilder::new()
|
ClientBuilder::new()
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,7 +363,7 @@ impl Format {
|
||||||
/// Returns `None` if the format string syntax is incorrect.
|
/// Returns `None` if the format string syntax is incorrect.
|
||||||
pub fn new(s: &str) -> Format {
|
pub fn new(s: &str) -> Format {
|
||||||
log::trace!("Access log format: {}", s);
|
log::trace!("Access log format: {}", s);
|
||||||
let fmt = Regex::new(r"%(\{([A-Za-z0-9\-_]+)\}([aioe]|xi)|[atPrUsbTD]?)").unwrap();
|
let fmt = Regex::new(r"%(\{([A-Za-z0-9\-_]+)\}([aioe]|xi)|[%atPrUsbTD]?)").unwrap();
|
||||||
|
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
@ -639,6 +639,38 @@ mod tests {
|
||||||
let _res = srv.call(req).await.unwrap();
|
let _res = srv.call(req).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_escape_percent() {
|
||||||
|
let mut format = Format::new("%%{r}a");
|
||||||
|
|
||||||
|
let req = TestRequest::default()
|
||||||
|
.insert_header((
|
||||||
|
header::FORWARDED,
|
||||||
|
header::HeaderValue::from_static("for=192.0.2.60;proto=http;by=203.0.113.43"),
|
||||||
|
))
|
||||||
|
.to_srv_request();
|
||||||
|
|
||||||
|
let now = OffsetDateTime::now_utc();
|
||||||
|
for unit in &mut format.0 {
|
||||||
|
unit.render_request(now, &req);
|
||||||
|
}
|
||||||
|
|
||||||
|
let resp = HttpResponse::build(StatusCode::OK).force_close().finish();
|
||||||
|
for unit in &mut format.0 {
|
||||||
|
unit.render_response(&resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry_time = OffsetDateTime::now_utc();
|
||||||
|
let render = |fmt: &mut fmt::Formatter<'_>| {
|
||||||
|
for unit in &format.0 {
|
||||||
|
unit.render(fmt, 1024, entry_time)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
let s = format!("{}", FormatDisplay(&render));
|
||||||
|
assert_eq!(s, "%{r}a");
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_url_path() {
|
async fn test_url_path() {
|
||||||
let mut format = Format::new("%T %U");
|
let mut format = Format::new("%T %U");
|
||||||
|
|
Loading…
Reference in New Issue