1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-07-03 01:34:32 +02:00

Merge branch 'master' into origin/feature/awc-retry-middleware

This commit is contained in:
fakeshadow
2021-05-29 20:42:20 +08:00
committed by GitHub
136 changed files with 5044 additions and 3688 deletions

View File

@ -3,6 +3,13 @@
## Unreleased - 2021-xx-xx
## 3.0.0-beta.5 - 2021-04-17
### Removed
* Deprecated methods on `ClientRequest`: `if_true`, `if_some`. [#2148]
[#2148]: https://github.com/actix/actix-web/pull/2148
## 3.0.0-beta.4 - 2021-04-02
### Added
* Add `Client::headers` to get default mut reference of `HeaderMap` of client object. [#2114]

View File

@ -1,22 +1,20 @@
[package]
name = "awc"
version = "3.0.0-beta.4"
version = "3.0.0-beta.5"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"fakeshadow <24548779@qq.com>",
]
description = "Async HTTP and WebSocket client library built on the Actix ecosystem"
readme = "README.md"
keywords = ["actix", "http", "framework", "async", "web"]
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-web.git"
documentation = "https://docs.rs/awc/"
categories = [
"network-programming",
"asynchronous",
"web-programming::http-client",
"web-programming::websocket",
]
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-web"
license = "MIT OR Apache-2.0"
edition = "2018"
@ -41,19 +39,20 @@ rustls = ["tls-rustls", "actix-http/rustls"]
compress = ["actix-http/compress"]
# cookie parsing and cookie jar
cookies = ["actix-http/cookies"]
cookies = ["cookie"]
# trust-dns as dns resolver
trust-dns = ["actix-http/trust-dns"]
[dependencies]
actix-codec = "0.4.0-beta.1"
actix-service = "2.0.0-beta.4"
actix-http = "3.0.0-beta.5"
actix-codec = "0.4.0"
actix-service = "2.0.0"
actix-http = "3.0.0-beta.6"
actix-rt = { version = "2.1", default-features = false }
base64 = "0.13"
bytes = "1"
cookie = { version = "0.15", features = ["percent-encode"], optional = true }
derive_more = "0.99.5"
futures-core = { version = "0.3.7", default-features = false }
itoa = "0.4"
@ -69,13 +68,13 @@ tls-openssl = { version = "0.10.9", package = "openssl", optional = true }
tls-rustls = { version = "0.19.0", package = "rustls", optional = true, features = ["dangerous_configuration"] }
[dev-dependencies]
actix-web = { version = "4.0.0-beta.5", features = ["openssl"] }
actix-http = { version = "3.0.0-beta.5", features = ["openssl"] }
actix-web = { version = "4.0.0-beta.6", features = ["openssl"] }
actix-http = { version = "3.0.0-beta.6", features = ["openssl"] }
actix-http-test = { version = "3.0.0-beta.4", features = ["openssl"] }
actix-utils = "3.0.0-beta.4"
actix-utils = "3.0.0"
actix-server = "2.0.0-beta.3"
actix-tls = { version = "3.0.0-beta.5", features = ["openssl", "rustls"] }
actix-test = { version = "0.1.0-beta.1", features = ["openssl", "rustls"] }
actix-test = { version = "0.1.0-beta.2", features = ["openssl", "rustls"] }
brotli2 = "0.3.2"
env_logger = "0.8"

View File

@ -93,12 +93,11 @@
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
use std::convert::TryFrom;
use std::rc::Rc;
use std::time::Duration;
use std::{convert::TryFrom, rc::Rc, time::Duration};
#[cfg(feature = "cookies")]
pub use actix_http::cookie;
pub use cookie;
pub use actix_http::{client::Connector, http};
use actix_http::{

View File

@ -8,14 +8,14 @@ use futures_core::Stream;
use serde::Serialize;
use actix_http::body::Body;
#[cfg(feature = "cookies")]
use actix_http::cookie::{Cookie, CookieJar};
use actix_http::http::header::{self, IntoHeaderPair};
use actix_http::http::{
uri, ConnectionType, Error as HttpError, HeaderMap, HeaderValue, Method, Uri, Version,
};
use actix_http::{Error, RequestHead};
#[cfg(feature = "cookies")]
use crate::cookie::{Cookie, CookieJar};
use crate::error::{FreezeRequestError, InvalidUrl};
use crate::frozen::FrozenClientRequest;
use crate::sender::{PrepForSendingError, RequestSender, SendClientRequest};
@ -271,7 +271,7 @@ impl ClientRequest {
/// async fn main() {
/// let resp = awc::Client::new().get("https://www.rust-lang.org")
/// .cookie(
/// awc::http::Cookie::build("name", "value")
/// awc::cookie::Cookie::build("name", "value")
/// .domain("www.rust-lang.org")
/// .path("/")
/// .secure(true)
@ -311,34 +311,6 @@ impl ClientRequest {
self
}
/// This method calls provided closure with builder reference if value is `true`.
#[doc(hidden)]
#[deprecated = "Use an if statement."]
pub fn if_true<F>(self, value: bool, f: F) -> Self
where
F: FnOnce(ClientRequest) -> ClientRequest,
{
if value {
f(self)
} else {
self
}
}
/// This method calls provided closure with builder reference if value is `Some`.
#[doc(hidden)]
#[deprecated = "Use an if-let construction."]
pub fn if_some<T, F>(self, value: Option<T>, f: F) -> Self
where
F: FnOnce(T, ClientRequest) -> ClientRequest,
{
if let Some(val) = value {
f(val, self)
} else {
self
}
}
/// Sets the query part of the request
pub fn query<T: Serialize>(
mut self,
@ -494,7 +466,7 @@ impl ClientRequest {
let cookie: String = jar
.delta()
// ensure only name=value is written to cookie header
.map(|c| Cookie::new(c.name(), c.value()).encoded().to_string())
.map(|c| c.stripped().encoded().to_string())
.collect::<Vec<_>>()
.join("; ");

View File

@ -20,8 +20,7 @@ use futures_core::{ready, Stream};
use serde::de::DeserializeOwned;
#[cfg(feature = "cookies")]
use actix_http::{cookie::Cookie, error::CookieParseError};
use crate::cookie::{Cookie, ParseError as CookieParseError};
use crate::error::JsonPayloadError;
/// Client Response
@ -80,24 +79,6 @@ impl<S> HttpMessage for ClientResponse<S> {
fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.head.extensions_mut()
}
/// Load request cookies.
#[cfg(feature = "cookies")]
fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
struct Cookies(Vec<Cookie<'static>>);
if self.extensions().get::<Cookies>().is_none() {
let mut cookies = Vec::new();
for hdr in self.headers().get_all(&header::SET_COOKIE) {
let s = std::str::from_utf8(hdr.as_bytes()).map_err(CookieParseError::from)?;
cookies.push(Cookie::parse_encoded(s)?.into_owned());
}
self.extensions_mut().insert(Cookies(cookies));
}
Ok(Ref::map(self.extensions(), |ext| {
&ext.get::<Cookies>().unwrap().0
}))
}
}
impl<S> ClientResponse<S> {
@ -180,6 +161,37 @@ impl<S> ClientResponse<S> {
self.timeout = ResponseTimeout::Disabled(timeout);
self
}
/// Load request cookies.
#[cfg(feature = "cookies")]
pub fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
struct Cookies(Vec<Cookie<'static>>);
if self.extensions().get::<Cookies>().is_none() {
let mut cookies = Vec::new();
for hdr in self.headers().get_all(&header::SET_COOKIE) {
let s = std::str::from_utf8(hdr.as_bytes()).map_err(CookieParseError::from)?;
cookies.push(Cookie::parse_encoded(s)?.into_owned());
}
self.extensions_mut().insert(Cookies(cookies));
}
Ok(Ref::map(self.extensions(), |ext| {
&ext.get::<Cookies>().unwrap().0
}))
}
/// Return request cookie.
#[cfg(feature = "cookies")]
pub fn cookie(&self, name: &str) -> Option<Cookie<'static>> {
if let Ok(cookies) = self.cookies() {
for cookie in cookies.iter() {
if cookie.name() == name {
return Some(cookie.to_owned());
}
}
}
None
}
}
impl<S> ClientResponse<S>

View File

@ -1,6 +1,6 @@
use std::{
future::Future,
net,
io, net,
pin::Pin,
rc::Rc,
task::{Context, Poll},
@ -209,7 +209,8 @@ impl RequestSender {
) -> SendClientRequest {
let body = match serde_json::to_string(value) {
Ok(body) => body,
Err(e) => return Error::from(e).into(),
// TODO: own error type
Err(e) => return Error::from(io::Error::new(io::ErrorKind::Other, e)).into(),
};
if let Err(e) = self.set_header_if_none(header::CONTENT_TYPE, "application/json") {
@ -235,7 +236,8 @@ impl RequestSender {
) -> SendClientRequest {
let body = match serde_urlencoded::to_string(value) {
Ok(body) => body,
Err(e) => return Error::from(e).into(),
// TODO: own error type
Err(e) => return Error::from(io::Error::new(io::ErrorKind::Other, e)).into(),
};
// set content-type

View File

@ -1,14 +1,11 @@
//! Test helpers for actix http client to use during testing.
use actix_http::http::header::IntoHeaderPair;
use actix_http::http::{StatusCode, Version};
#[cfg(feature = "cookies")]
use actix_http::{
cookie::{Cookie, CookieJar},
http::header::{self, HeaderValue},
};
use actix_http::{h1, Payload, ResponseHead};
use bytes::Bytes;
#[cfg(feature = "cookies")]
use crate::cookie::{Cookie, CookieJar};
use crate::ClientResponse;
/// Test `ClientResponse` builder
@ -92,6 +89,8 @@ impl TestResponse {
#[cfg(feature = "cookies")]
for cookie in self.cookies.delta() {
use actix_http::http::header::{self, HeaderValue};
head.headers.insert(
header::SET_COOKIE,
HeaderValue::from_str(&cookie.encoded().to_string()).unwrap(),

View File

@ -31,8 +31,6 @@ use std::net::SocketAddr;
use std::{fmt, str};
use actix_codec::Framed;
#[cfg(feature = "cookies")]
use actix_http::cookie::{Cookie, CookieJar};
use actix_http::{ws, Payload, RequestHead};
use actix_rt::time::timeout;
use actix_service::Service;
@ -40,6 +38,8 @@ use actix_service::Service;
pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message};
use crate::connect::{BoxedSocket, ConnectRequest};
#[cfg(feature = "cookies")]
use crate::cookie::{Cookie, CookieJar};
use crate::error::{InvalidUrl, SendRequestError, WsClientError};
use crate::http::header::{self, HeaderName, HeaderValue, IntoHeaderValue, AUTHORIZATION};
use crate::http::{ConnectionType, Error as HttpError, Method, StatusCode, Uri, Version};
@ -280,7 +280,7 @@ impl WebsocketsRequest {
let cookie: String = jar
.delta()
// ensure only name=value is written to cookie header
.map(|c| Cookie::new(c.name(), c.value()).encoded().to_string())
.map(|c| c.stripped().encoded().to_string())
.collect::<Vec<_>>()
.join("; ");

View File

@ -8,6 +8,7 @@ use std::time::Duration;
use actix_utils::future::ok;
use brotli2::write::BrotliEncoder;
use bytes::Bytes;
use cookie::Cookie;
use flate2::read::GzDecoder;
use flate2::write::GzEncoder;
use flate2::Compression;
@ -19,12 +20,12 @@ use actix_http::{
HttpService,
};
use actix_http_test::test_server;
use actix_service::{map_config, pipeline_factory};
use actix_service::{fn_service, map_config, ServiceFactoryExt as _};
use actix_web::{
dev::{AppConfig, BodyEncoding},
http::{header, Cookie},
http::header,
middleware::Compress,
web, App, Error, HttpMessage, HttpRequest, HttpResponse,
web, App, Error, HttpRequest, HttpResponse,
};
use awc::error::{JsonPayloadError, PayloadError, SendRequestError};
@ -238,7 +239,7 @@ async fn test_connection_reuse() {
let srv = test_server(move || {
let num2 = num2.clone();
pipeline_factory(move |io| {
fn_service(move |io| {
num2.fetch_add(1, Ordering::Relaxed);
ok(io)
})
@ -275,7 +276,7 @@ async fn test_connection_force_close() {
let srv = test_server(move || {
let num2 = num2.clone();
pipeline_factory(move |io| {
fn_service(move |io| {
num2.fetch_add(1, Ordering::Relaxed);
ok(io)
})
@ -312,7 +313,7 @@ async fn test_connection_server_close() {
let srv = test_server(move || {
let num2 = num2.clone();
pipeline_factory(move |io| {
fn_service(move |io| {
num2.fetch_add(1, Ordering::Relaxed);
ok(io)
})
@ -352,7 +353,7 @@ async fn test_connection_wait_queue() {
let srv = test_server(move || {
let num2 = num2.clone();
pipeline_factory(move |io| {
fn_service(move |io| {
num2.fetch_add(1, Ordering::Relaxed);
ok(io)
})
@ -400,7 +401,7 @@ async fn test_connection_wait_queue_force_close() {
let srv = test_server(move || {
let num2 = num2.clone();
pipeline_factory(move |io| {
fn_service(move |io| {
num2.fetch_add(1, Ordering::Relaxed);
ok(io)
})

View File

@ -12,7 +12,7 @@ use std::{
use actix_http::HttpService;
use actix_http_test::test_server;
use actix_service::{map_config, pipeline_factory, ServiceFactoryExt};
use actix_service::{fn_service, map_config, ServiceFactoryExt};
use actix_utils::future::ok;
use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse};
use rustls::internal::pemfile::{certs, pkcs8_private_keys};
@ -57,7 +57,7 @@ async fn test_connection_reuse_h2() {
let srv = test_server(move || {
let num2 = num2.clone();
pipeline_factory(move |io| {
fn_service(move |io| {
num2.fetch_add(1, Ordering::Relaxed);
ok(io)
})

View File

@ -7,7 +7,7 @@ use std::sync::Arc;
use actix_http::HttpService;
use actix_http_test::test_server;
use actix_service::{map_config, pipeline_factory, ServiceFactoryExt};
use actix_service::{fn_service, map_config, ServiceFactoryExt};
use actix_utils::future::ok;
use actix_web::http::Version;
use actix_web::{dev::AppConfig, web, App, HttpResponse};
@ -48,7 +48,7 @@ async fn test_connection_reuse_h2() {
let srv = test_server(move || {
let num2 = num2.clone();
pipeline_factory(move |io| {
fn_service(move |io| {
num2.fetch_add(1, Ordering::Relaxed);
ok(io)
})

View File

@ -36,7 +36,7 @@ async fn test_simple() {
ws::Dispatcher::with(framed, ws_service).await
}
})
.finish(|_| ok::<_, Error>(Response::NotFound()))
.finish(|_| ok::<_, Error>(Response::not_found()))
.tcp()
})
.await;