Merge branch 'master' into style/h1_poll_response_loop

This commit is contained in:
fakeshadow 2021-03-11 16:39:49 -08:00 committed by GitHub
commit f8de43f74c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 19 deletions

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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>,

View File

@ -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()
} }

View File

@ -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");