Merge branch 'http-send-trait' into master
commit
fe572017b1
|
@ -17,6 +17,7 @@ encryption = ["matrix-sdk-base/encryption"]
|
|||
sqlite-cryptostore = ["matrix-sdk-base/sqlite-cryptostore"]
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.36"
|
||||
http = "0.2.1"
|
||||
# FIXME: Revert to regular dependency once 0.10.8 or 0.11.0 is released
|
||||
reqwest = { git = "https://github.com/seanmonstar/reqwest", rev = "dd8441fd23dae6ffb79b4cea2862e5bca0c59743" }
|
||||
|
|
|
@ -47,15 +47,14 @@ use url::Url;
|
|||
|
||||
use crate::{
|
||||
events::{room::message::MessageEventContent, EventType},
|
||||
http_client::DefaultHttpClient,
|
||||
identifiers::{EventId, RoomId, RoomIdOrAliasId, UserId},
|
||||
Endpoint,
|
||||
Endpoint, HttpSend,
|
||||
};
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
use crate::{identifiers::DeviceId, sas::Sas};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::VERSION;
|
||||
use crate::{api, http_client::HttpClient, EventEmitter, Result};
|
||||
use matrix_sdk_base::{BaseClient, BaseClientConfig, Room, Session, StateStore};
|
||||
|
||||
|
@ -108,11 +107,12 @@ impl Debug for Client {
|
|||
#[derive(Default)]
|
||||
pub struct ClientConfig {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
proxy: Option<reqwest::Proxy>,
|
||||
user_agent: Option<HeaderValue>,
|
||||
disable_ssl_verification: bool,
|
||||
base_config: BaseClientConfig,
|
||||
timeout: Option<Duration>,
|
||||
pub(crate) proxy: Option<reqwest::Proxy>,
|
||||
pub(crate) user_agent: Option<HeaderValue>,
|
||||
pub(crate) disable_ssl_verification: bool,
|
||||
pub(crate) base_config: BaseClientConfig,
|
||||
pub(crate) timeout: Option<Duration>,
|
||||
pub(crate) client: Option<Arc<dyn HttpSend>>,
|
||||
}
|
||||
|
||||
// #[cfg_attr(tarpaulin, skip)]
|
||||
|
@ -212,6 +212,15 @@ impl ClientConfig {
|
|||
self.timeout = Some(timeout);
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify a client to handle sending requests and receiving responses.
|
||||
///
|
||||
/// Any type that implements the `HttpSend` trait can be used to send/receive
|
||||
/// `http` types.
|
||||
pub fn client(mut self, client: Arc<dyn HttpSend>) -> Self {
|
||||
self.client = Some(client);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
@ -322,48 +331,21 @@ impl Client {
|
|||
config: ClientConfig,
|
||||
) -> Result<Self> {
|
||||
let homeserver = if let Ok(u) = homeserver_url.try_into() {
|
||||
u
|
||||
Arc::new(u)
|
||||
} else {
|
||||
panic!("Error parsing homeserver url")
|
||||
};
|
||||
|
||||
let http_client = reqwest::Client::builder();
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let http_client = {
|
||||
let http_client = match config.timeout {
|
||||
Some(x) => http_client.timeout(x),
|
||||
None => http_client,
|
||||
};
|
||||
|
||||
let http_client = if config.disable_ssl_verification {
|
||||
http_client.danger_accept_invalid_certs(true)
|
||||
} else {
|
||||
http_client
|
||||
};
|
||||
|
||||
let http_client = match config.proxy {
|
||||
Some(p) => http_client.proxy(p),
|
||||
None => http_client,
|
||||
};
|
||||
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
|
||||
let user_agent = match config.user_agent {
|
||||
Some(a) => a,
|
||||
None => HeaderValue::from_str(&format!("matrix-rust-sdk {}", VERSION)).unwrap(),
|
||||
};
|
||||
|
||||
headers.insert(reqwest::header::USER_AGENT, user_agent);
|
||||
|
||||
http_client.default_headers(headers)
|
||||
};
|
||||
|
||||
let homeserver = Arc::new(homeserver);
|
||||
|
||||
let http_client = HttpClient {
|
||||
homeserver: homeserver.clone(),
|
||||
inner: http_client.build()?,
|
||||
let http_client = if let Some(client) = config.client {
|
||||
HttpClient {
|
||||
homeserver: homeserver.clone(),
|
||||
inner: client,
|
||||
}
|
||||
} else {
|
||||
HttpClient {
|
||||
homeserver: homeserver.clone(),
|
||||
inner: Arc::new(DefaultHttpClient::with_config(&config)?),
|
||||
}
|
||||
};
|
||||
|
||||
let base_client = BaseClient::new_with_config(config.base_config)?;
|
||||
|
|
|
@ -12,23 +12,20 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{convert::TryFrom, sync::Arc};
|
||||
|
||||
use http::{HeaderValue, Method as HttpMethod, Response as HttpResponse};
|
||||
use matrix_sdk_common::{locks::RwLock, FromHttpResponseError};
|
||||
use matrix_sdk_common_macros::async_trait;
|
||||
use reqwest::{Client, Response};
|
||||
use tracing::trace;
|
||||
use url::Url;
|
||||
|
||||
use matrix_sdk_common::{locks::RwLock, FromHttpResponseError};
|
||||
|
||||
use crate::{Endpoint, Error, Result, Session};
|
||||
use crate::{ClientConfig, Endpoint, Error, HttpSend, Result, Session};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct HttpClient {
|
||||
pub(crate) inner: Client,
|
||||
pub(crate) inner: Arc<dyn HttpSend>,
|
||||
pub(crate) homeserver: Arc<Url>,
|
||||
}
|
||||
|
||||
|
@ -62,7 +59,7 @@ impl HttpClient {
|
|||
);
|
||||
}
|
||||
|
||||
Ok(self.inner.execute(request.try_into()?).await?)
|
||||
self.inner.send_request(request).await
|
||||
}
|
||||
|
||||
async fn response_to_http_response(
|
||||
|
@ -100,3 +97,66 @@ impl HttpClient {
|
|||
Ok(Request::IncomingResponse::try_from(response)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Default http client used if none is specified using `Client::with_client`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DefaultHttpClient {
|
||||
inner: Client,
|
||||
}
|
||||
|
||||
impl DefaultHttpClient {
|
||||
/// Build a client with the specified configuration.
|
||||
pub fn with_config(config: &ClientConfig) -> Result<Self> {
|
||||
let http_client = reqwest::Client::builder();
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let http_client = {
|
||||
let http_client = match config.timeout {
|
||||
Some(x) => http_client.timeout(x),
|
||||
None => http_client,
|
||||
};
|
||||
|
||||
let http_client = if config.disable_ssl_verification {
|
||||
http_client.danger_accept_invalid_certs(true)
|
||||
} else {
|
||||
http_client
|
||||
};
|
||||
|
||||
let http_client = match &config.proxy {
|
||||
Some(p) => http_client.proxy(p.clone()),
|
||||
None => http_client,
|
||||
};
|
||||
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
|
||||
let user_agent = match &config.user_agent {
|
||||
Some(a) => a.clone(),
|
||||
None => {
|
||||
HeaderValue::from_str(&format!("matrix-rust-sdk {}", crate::VERSION)).unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
headers.insert(reqwest::header::USER_AGENT, user_agent);
|
||||
|
||||
http_client.default_headers(headers)
|
||||
};
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[allow(unused)]
|
||||
let _ = config;
|
||||
|
||||
Ok(Self {
|
||||
inner: http_client.build()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl HttpSend for DefaultHttpClient {
|
||||
async fn send_request(&self, request: http::Request<Vec<u8>>) -> Result<Response> {
|
||||
Ok(self
|
||||
.inner
|
||||
.execute(reqwest::Request::try_from(request)?)
|
||||
.await?)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use matrix_sdk_common_macros::async_trait;
|
||||
use reqwest::Response;
|
||||
|
||||
use crate::Result;
|
||||
|
||||
/// Abstraction around the http layer. The allows implementors to use different
|
||||
/// http libraries.
|
||||
#[async_trait]
|
||||
pub trait HttpSend: Sync + Send + Debug {
|
||||
/// The method abstracting sending request types and receiving response types.
|
||||
///
|
||||
/// This is called by the client every time it wants to send anything to a homeserver.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `request` - The http request that has been converted from a ruma `Request`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A `reqwest::Response` that will be converted to a ruma `Response` in the `Client`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use matrix_sdk::HttpSend;
|
||||
/// use matrix_sdk_common_macros::async_trait;
|
||||
/// use reqwest::Response;
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// struct TestSend;
|
||||
///
|
||||
/// impl HttpSend for TestSend {
|
||||
/// async fn send_request(&self, request: http::Request<Vec<u8>>) -> Result<Response>
|
||||
/// // send the request somehow
|
||||
/// let response = send(request, method, homeserver).await?;
|
||||
///
|
||||
/// // reqwest can convert to and from `http::Response` types.
|
||||
/// Ok(reqwest::Response::from(response))
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
async fn send_request(&self, request: http::Request<Vec<u8>>) -> Result<Response>;
|
||||
}
|
|
@ -51,6 +51,7 @@ pub use reqwest::header::InvalidHeaderValue;
|
|||
mod client;
|
||||
mod error;
|
||||
mod http_client;
|
||||
mod http_send;
|
||||
mod request_builder;
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
|
@ -58,6 +59,7 @@ mod sas;
|
|||
|
||||
pub use client::{Client, ClientConfig, SyncSettings};
|
||||
pub use error::{Error, Result};
|
||||
pub use http_send::HttpSend;
|
||||
pub use request_builder::{
|
||||
MessagesRequestBuilder, RegistrationBuilder, RoomBuilder, RoomListFilterBuilder,
|
||||
};
|
||||
|
|
|
@ -14,5 +14,5 @@ version = "0.1.0"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = "1.0.34"
|
||||
syn = "1.0.38"
|
||||
quote = "1.0.7"
|
||||
|
|
Loading…
Reference in New Issue