client: Add support for isahc as an HTTP client

This commit is contained in:
Jonas Platte 2021-05-01 21:19:47 +02:00
parent 7eb5f1e775
commit 92826df304
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
5 changed files with 95 additions and 2 deletions

View File

@ -20,6 +20,7 @@ client-api = ["ruma-client-api"]
# HTTP clients
hyper-native-tls = ["hyper", "hyper-tls"]
hyper-rustls = ["hyper", "hyper-rustls-crate"]
isahc = ["isahc-crate", "futures-lite"]
reqwest-native-tls = ["reqwest", "reqwest/native-tls"]
reqwest-native-tls-vendored = ["reqwest", "reqwest/native-tls-vendored"]
reqwest-rustls-manual-roots = ["reqwest", "reqwest/rustls-tls-manual-roots"]
@ -32,10 +33,12 @@ async-stream = "0.3.0"
async-trait = "0.1.50"
bytes = "1.0.1"
futures-core = "0.3.8"
futures-lite = { version = "1.11.3", optional = true }
http = "0.2.2"
hyper = { version = "0.14.2", optional = true, features = ["client", "http1", "http2", "tcp"] }
hyper-tls = { version = "0.5.0", optional = true }
hyper-rustls-crate = { package = "hyper-rustls", version = "0.22.1", optional = true, default-features = false }
isahc-crate = { package = "isahc", version = "1.3.1", optional = true }
reqwest = { version = "0.11.3", optional = true, default-features = false }
ruma-api = { version = "=0.17.0-alpha.4", path = "../ruma-api" }
ruma-client-api = { version = "=0.10.0-alpha.3", path = "../ruma-client-api", optional = true, features = ["client"] }
@ -56,6 +59,10 @@ tokio-stream = { version = "0.1.1", default-features = false }
name = "hello_world"
required-features = ["client-api", "hyper-native-tls"]
[[example]]
name = "hello_isahc"
required-features = ["client-api", "isahc"]
[[example]]
name = "message_log"
required-features = ["client-api", "hyper-native-tls"]

View File

@ -0,0 +1,56 @@
//! Same as the hello_world example, but using the isahc http client (a Rust wrapper around
//! libcurl).
// "Undo" rename from `Cargo.toml` that only serves to make crate names available as a Cargo
// feature names.
extern crate isahc_crate as isahc;
use std::{convert::TryFrom, env, process::exit};
use ruma::{
api::client::r0::{alias::get_alias, membership::join_room_by_id, message::send_message_event},
events::{room::message::MessageEventContent, AnyMessageEventContent},
RoomAliasId,
};
type MatrixClient = ruma_client::Client<ruma_client::http_client::Isahc>;
async fn hello_world(
homeserver_url: String,
username: &str,
password: &str,
room_alias: &RoomAliasId,
) -> anyhow::Result<()> {
let http_client = isahc::HttpClient::new()?;
let client = MatrixClient::with_http_client(http_client, homeserver_url, None);
client.log_in(username, password, None, Some("ruma-example-client")).await?;
let room_id = client.send_request(get_alias::Request::new(room_alias)).await?.room_id;
client.send_request(join_room_by_id::Request::new(&room_id)).await?;
client
.send_request(send_message_event::Request::new(
&room_id,
"1",
&AnyMessageEventContent::RoomMessage(MessageEventContent::text_plain("Hello World!")),
))
.await?;
Ok(())
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let (homeserver_url, username, password, room) =
match (env::args().nth(1), env::args().nth(2), env::args().nth(3), env::args().nth(4)) {
(Some(a), Some(b), Some(c), Some(d)) => (a, b, c, d),
_ => {
eprintln!(
"Usage: {} <homeserver_url> <username> <password> <room>",
env::args().next().unwrap()
);
exit(1)
}
};
hello_world(homeserver_url, &username, &password, &RoomAliasId::try_from(room.as_str())?).await
}

View File

@ -12,6 +12,8 @@ use crate::{add_user_id_to_query, ResponseError, ResponseResult};
#[cfg(feature = "hyper")]
mod hyper;
#[cfg(feature = "isahc")]
mod isahc;
#[cfg(feature = "reqwest")]
mod reqwest;
@ -21,6 +23,8 @@ pub use self::hyper::Hyper;
pub use self::hyper::HyperNativeTls;
#[cfg(feature = "hyper-rustls")]
pub use self::hyper::HyperRustls;
#[cfg(feature = "isahc")]
pub use self::isahc::Isahc;
#[cfg(feature = "reqwest")]
pub use self::reqwest::Reqwest;

View File

@ -0,0 +1,24 @@
use super::HttpClient;
use async_trait::async_trait;
use futures_lite::AsyncReadExt;
/// The `isahc` crate's `HttpClient`.
pub type Isahc = isahc::HttpClient;
#[async_trait]
impl HttpClient for Isahc {
type RequestBody = Vec<u8>;
type ResponseBody = Vec<u8>;
type Error = isahc::Error;
async fn send_http_request(
&self,
req: http::Request<Vec<u8>>,
) -> Result<http::Response<Vec<u8>>, isahc::Error> {
let (head, mut body) = self.send_async(req).await?.into_parts();
let mut full_body = Vec::new();
body.read_to_end(&mut full_body).await?;
Ok(http::Response::from_parts(head, full_body))
}
}

View File

@ -82,10 +82,12 @@ use std::{
use ruma_api::{OutgoingRequest, SendAccessToken};
use ruma_identifiers::UserId;
// "Undo" rename from `Cargo.toml` that only serves to make `hyper-rustls` available as a Cargo
// feature name.
// "Undo" rename from `Cargo.toml` that only serves to make crate names available as a Cargo
// feature names.
#[cfg(feature = "hyper-rustls")]
extern crate hyper_rustls_crate as hyper_rustls;
#[cfg(feature = "isahc")]
extern crate isahc_crate as isahc;
#[cfg(feature = "client-api")]
mod client_api;