mirror of
https://github.com/actix/actix-web.git
synced 2025-02-16 19:15:13 +00:00
move client to own module
This commit is contained in:
parent
d2590fd46c
commit
3756dfc2ce
7 changed files with 203 additions and 207 deletions
|
@ -9,11 +9,13 @@ use actix_rt::net::{ActixStream, TcpStream};
|
|||
use actix_service::{boxed, Service};
|
||||
|
||||
use crate::{
|
||||
client::{ConnectInfo, Connector, ConnectorService, TcpConnectError, TcpConnection},
|
||||
client::{
|
||||
ClientConfig, ConnectInfo, Connector, ConnectorService, TcpConnectError, TcpConnection,
|
||||
},
|
||||
connect::DefaultConnector,
|
||||
error::SendRequestError,
|
||||
middleware::{NestTransform, Redirect, Transform},
|
||||
Client, ClientConfig, ConnectRequest, ConnectResponse,
|
||||
Client, ConnectRequest, ConnectResponse,
|
||||
};
|
||||
|
||||
/// An HTTP Client builder
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
//! HTTP client.
|
||||
|
||||
use http::Uri;
|
||||
use std::{convert::TryFrom, rc::Rc, time::Duration};
|
||||
|
||||
use actix_http::{error::HttpError, header::HeaderMap, Method, RequestHead, Uri};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_service::Service;
|
||||
pub use actix_tls::connect::{
|
||||
ConnectError as TcpConnectError, ConnectInfo, Connection as TcpConnection,
|
||||
};
|
||||
|
||||
use crate::{ws, BoxConnectorService, ClientBuilder, ClientRequest};
|
||||
|
||||
mod config;
|
||||
mod connection;
|
||||
|
@ -10,10 +19,6 @@ mod h1proto;
|
|||
mod h2proto;
|
||||
mod pool;
|
||||
|
||||
pub use actix_tls::connect::{
|
||||
ConnectError as TcpConnectError, ConnectInfo, Connection as TcpConnection,
|
||||
};
|
||||
|
||||
pub use self::connection::{Connection, ConnectionIo};
|
||||
pub use self::connector::{Connector, ConnectorService};
|
||||
pub use self::error::{ConnectError, FreezeRequestError, InvalidUrl, SendRequestError};
|
||||
|
@ -23,3 +28,176 @@ pub struct Connect {
|
|||
pub uri: Uri,
|
||||
pub addr: Option<std::net::SocketAddr>,
|
||||
}
|
||||
|
||||
/// An asynchronous HTTP and WebSocket client.
|
||||
///
|
||||
/// You should take care to create, at most, one `Client` per thread. Otherwise, expect higher CPU
|
||||
/// and memory usage.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use awc::Client;
|
||||
///
|
||||
/// #[actix_rt::main]
|
||||
/// async fn main() {
|
||||
/// let mut client = Client::default();
|
||||
///
|
||||
/// let res = client.get("http://www.rust-lang.org")
|
||||
/// .insert_header(("User-Agent", "my-app/1.2"))
|
||||
/// .send()
|
||||
/// .await;
|
||||
///
|
||||
/// println!("Response: {:?}", res);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct Client(pub(crate) ClientConfig);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ClientConfig {
|
||||
pub(crate) connector: BoxConnectorService,
|
||||
pub(crate) default_headers: Rc<HeaderMap>,
|
||||
pub(crate) timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
impl Default for Client {
|
||||
fn default() -> Self {
|
||||
ClientBuilder::new().finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
/// Create new client instance with default settings.
|
||||
pub fn new() -> Client {
|
||||
Client::default()
|
||||
}
|
||||
|
||||
/// Create `Client` builder.
|
||||
/// This function is equivalent of `ClientBuilder::new()`.
|
||||
pub fn builder() -> ClientBuilder<
|
||||
impl Service<
|
||||
ConnectInfo<Uri>,
|
||||
Response = TcpConnection<Uri, TcpStream>,
|
||||
Error = TcpConnectError,
|
||||
> + Clone,
|
||||
> {
|
||||
ClientBuilder::new()
|
||||
}
|
||||
|
||||
/// Construct HTTP request.
|
||||
pub fn request<U>(&self, method: Method, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
let mut req = ClientRequest::new(method, url, self.0.clone());
|
||||
|
||||
for header in self.0.default_headers.iter() {
|
||||
// header map is empty
|
||||
// TODO: probably append instead
|
||||
req = req.insert_header_if_none(header);
|
||||
}
|
||||
req
|
||||
}
|
||||
|
||||
/// Create `ClientRequest` from `RequestHead`
|
||||
///
|
||||
/// It is useful for proxy requests. This implementation
|
||||
/// copies all headers and the method.
|
||||
pub fn request_from<U>(&self, url: U, head: &RequestHead) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
let mut req = self.request(head.method.clone(), url);
|
||||
for header in head.headers.iter() {
|
||||
req = req.insert_header_if_none(header);
|
||||
}
|
||||
req
|
||||
}
|
||||
|
||||
/// Construct HTTP *GET* request.
|
||||
pub fn get<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::GET, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *HEAD* request.
|
||||
pub fn head<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::HEAD, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *PUT* request.
|
||||
pub fn put<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::PUT, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *POST* request.
|
||||
pub fn post<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::POST, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *PATCH* request.
|
||||
pub fn patch<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::PATCH, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *DELETE* request.
|
||||
pub fn delete<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::DELETE, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *OPTIONS* request.
|
||||
pub fn options<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::OPTIONS, url)
|
||||
}
|
||||
|
||||
/// Initialize a WebSocket connection.
|
||||
/// Returns a WebSocket connection builder.
|
||||
pub fn ws<U>(&self, url: U) -> ws::WebsocketsRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
let mut req = ws::WebsocketsRequest::new(url, self.0.clone());
|
||||
for (key, value) in self.0.default_headers.iter() {
|
||||
req.head.headers.insert(key.clone(), value.clone());
|
||||
}
|
||||
req
|
||||
}
|
||||
|
||||
/// Get default HeaderMap of Client.
|
||||
///
|
||||
/// Returns Some(&mut HeaderMap) when Client object is unique
|
||||
/// (No other clone of client exists at the same time).
|
||||
pub fn headers(&mut self) -> Option<&mut HeaderMap> {
|
||||
Rc::get_mut(&mut self.0.default_headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,9 @@ use actix_http::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
client::ClientConfig,
|
||||
sender::{RequestSender, SendClientRequest},
|
||||
BoxError, ClientConfig,
|
||||
BoxError,
|
||||
};
|
||||
|
||||
/// `FrozenClientRequest` struct represents cloneable client request.
|
||||
|
|
183
awc/src/lib.rs
183
awc/src/lib.rs
|
@ -124,7 +124,7 @@ pub use actix_http as http;
|
|||
pub use cookie;
|
||||
|
||||
pub use self::builder::ClientBuilder;
|
||||
pub use self::client::Connector;
|
||||
pub use self::client::{Client, Connector};
|
||||
pub use self::connect::{BoxConnectorService, BoxedSocket, ConnectRequest, ConnectResponse};
|
||||
pub use self::frozen::{FrozenClientRequest, FrozenSendBuilder};
|
||||
pub use self::request::ClientRequest;
|
||||
|
@ -132,185 +132,4 @@ pub use self::request::ClientRequest;
|
|||
pub use self::responses::{ClientResponse, JsonBody, MessageBody, ResponseBody};
|
||||
pub use self::sender::SendClientRequest;
|
||||
|
||||
use std::{convert::TryFrom, rc::Rc, time::Duration};
|
||||
|
||||
use actix_http::{error::HttpError, header::HeaderMap, Method, RequestHead, Uri};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_service::Service;
|
||||
|
||||
use self::client::{ConnectInfo, TcpConnectError, TcpConnection};
|
||||
|
||||
pub(crate) type BoxError = Box<dyn std::error::Error>;
|
||||
|
||||
/// An asynchronous HTTP and WebSocket client.
|
||||
///
|
||||
/// You should take care to create, at most, one `Client` per thread. Otherwise, expect higher CPU
|
||||
/// and memory usage.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use awc::Client;
|
||||
///
|
||||
/// #[actix_rt::main]
|
||||
/// async fn main() {
|
||||
/// let mut client = Client::default();
|
||||
///
|
||||
/// let res = client.get("http://www.rust-lang.org")
|
||||
/// .insert_header(("User-Agent", "my-app/1.2"))
|
||||
/// .send()
|
||||
/// .await;
|
||||
///
|
||||
/// println!("Response: {:?}", res);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct Client(ClientConfig);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ClientConfig {
|
||||
pub(crate) connector: BoxConnectorService,
|
||||
pub(crate) default_headers: Rc<HeaderMap>,
|
||||
pub(crate) timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
impl Default for Client {
|
||||
fn default() -> Self {
|
||||
ClientBuilder::new().finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
/// Create new client instance with default settings.
|
||||
pub fn new() -> Client {
|
||||
Client::default()
|
||||
}
|
||||
|
||||
/// Create `Client` builder.
|
||||
/// This function is equivalent of `ClientBuilder::new()`.
|
||||
pub fn builder() -> ClientBuilder<
|
||||
impl Service<
|
||||
ConnectInfo<Uri>,
|
||||
Response = TcpConnection<Uri, TcpStream>,
|
||||
Error = TcpConnectError,
|
||||
> + Clone,
|
||||
> {
|
||||
ClientBuilder::new()
|
||||
}
|
||||
|
||||
/// Construct HTTP request.
|
||||
pub fn request<U>(&self, method: Method, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
let mut req = ClientRequest::new(method, url, self.0.clone());
|
||||
|
||||
for header in self.0.default_headers.iter() {
|
||||
// header map is empty
|
||||
// TODO: probably append instead
|
||||
req = req.insert_header_if_none(header);
|
||||
}
|
||||
req
|
||||
}
|
||||
|
||||
/// Create `ClientRequest` from `RequestHead`
|
||||
///
|
||||
/// It is useful for proxy requests. This implementation
|
||||
/// copies all headers and the method.
|
||||
pub fn request_from<U>(&self, url: U, head: &RequestHead) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
let mut req = self.request(head.method.clone(), url);
|
||||
for header in head.headers.iter() {
|
||||
req = req.insert_header_if_none(header);
|
||||
}
|
||||
req
|
||||
}
|
||||
|
||||
/// Construct HTTP *GET* request.
|
||||
pub fn get<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::GET, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *HEAD* request.
|
||||
pub fn head<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::HEAD, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *PUT* request.
|
||||
pub fn put<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::PUT, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *POST* request.
|
||||
pub fn post<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::POST, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *PATCH* request.
|
||||
pub fn patch<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::PATCH, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *DELETE* request.
|
||||
pub fn delete<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::DELETE, url)
|
||||
}
|
||||
|
||||
/// Construct HTTP *OPTIONS* request.
|
||||
pub fn options<U>(&self, url: U) -> ClientRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
self.request(Method::OPTIONS, url)
|
||||
}
|
||||
|
||||
/// Initialize a WebSocket connection.
|
||||
/// Returns a WebSocket connection builder.
|
||||
pub fn ws<U>(&self, url: U) -> ws::WebsocketsRequest
|
||||
where
|
||||
Uri: TryFrom<U>,
|
||||
<Uri as TryFrom<U>>::Error: Into<HttpError>,
|
||||
{
|
||||
let mut req = ws::WebsocketsRequest::new(url, self.0.clone());
|
||||
for (key, value) in self.0.default_headers.iter() {
|
||||
req.head.headers.insert(key.clone(), value.clone());
|
||||
}
|
||||
req
|
||||
}
|
||||
|
||||
/// Get default HeaderMap of Client.
|
||||
///
|
||||
/// Returns Some(&mut HeaderMap) when Client object is unique
|
||||
/// (No other clone of client exists at the same time).
|
||||
pub fn headers(&mut self) -> Option<&mut HeaderMap> {
|
||||
Rc::get_mut(&mut self.0.default_headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,11 @@ use actix_http::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
client::ClientConfig,
|
||||
error::{FreezeRequestError, InvalidUrl},
|
||||
frozen::FrozenClientRequest,
|
||||
sender::{PrepForSendingError, RequestSender, SendClientRequest},
|
||||
BoxError, ClientConfig,
|
||||
BoxError,
|
||||
};
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
|
@ -249,23 +250,16 @@ impl ClientRequest {
|
|||
/// Set a cookie
|
||||
///
|
||||
/// ```no_run
|
||||
/// use awc::{cookie, Client};
|
||||
/// use awc::{cookie::Cookie, Client};
|
||||
///
|
||||
/// # #[actix_rt::main]
|
||||
/// # async fn main() {
|
||||
/// let resp = Client::new().get("https://www.rust-lang.org")
|
||||
/// .cookie(
|
||||
/// awc::cookie::Cookie::build("name", "value")
|
||||
/// .domain("www.rust-lang.org")
|
||||
/// .path("/")
|
||||
/// .secure(true)
|
||||
/// .http_only(true)
|
||||
/// .finish(),
|
||||
/// )
|
||||
/// .send()
|
||||
/// .await;
|
||||
/// let res = Client::new().get("https://httpbin.org/cookies")
|
||||
/// .cookie(Cookie::new("name", "value"))
|
||||
/// .send()
|
||||
/// .await;
|
||||
///
|
||||
/// println!("Response: {:?}", resp);
|
||||
/// println!("Response: {:?}", res);
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(feature = "cookies")]
|
||||
|
|
|
@ -24,8 +24,9 @@ use actix_http::{encoding::Decoder, header::ContentEncoding, Payload};
|
|||
|
||||
use crate::{
|
||||
any_body::AnyBody,
|
||||
client::ClientConfig,
|
||||
error::{FreezeRequestError, InvalidUrl, SendRequestError},
|
||||
BoxError, ClientConfig, ClientResponse, ConnectRequest, ConnectResponse,
|
||||
BoxError, ClientResponse, ConnectRequest, ConnectResponse,
|
||||
};
|
||||
|
||||
#[derive(Debug, From)]
|
||||
|
|
|
@ -31,18 +31,19 @@ use std::{convert::TryFrom, fmt, net::SocketAddr, str};
|
|||
use actix_codec::Framed;
|
||||
use actix_http::{ws, Payload, RequestHead};
|
||||
use actix_rt::time::timeout;
|
||||
use actix_service::Service;
|
||||
use actix_service::Service as _;
|
||||
|
||||
pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message};
|
||||
|
||||
use crate::{
|
||||
client::ClientConfig,
|
||||
connect::{BoxedSocket, ConnectRequest},
|
||||
error::{HttpError, InvalidUrl, SendRequestError, WsClientError},
|
||||
http::{
|
||||
header::{self, HeaderName, HeaderValue, TryIntoHeaderValue, AUTHORIZATION},
|
||||
ConnectionType, Method, StatusCode, Uri, Version,
|
||||
},
|
||||
ClientConfig, ClientResponse,
|
||||
ClientResponse,
|
||||
};
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
|
|
Loading…
Reference in a new issue