summaryrefslogtreecommitdiffstats
path: root/src/async/client.rs
diff options
context:
space:
mode:
authorPaul Woolcock <paul@woolcock.us>2020-10-07 05:47:39 -0400
committerPaul Woolcock <paul@woolcock.us>2020-10-07 09:06:13 -0400
commit02ca0a89515413ac9fb3b655de2f21f6a711e0f2 (patch)
tree004bcd9f88eca168e10e1ac85c5987fdd6769fcf /src/async/client.rs
parent04b5b54212629f058bdab1ba55c89a3d417e0454 (diff)
Add basic async client
This adds a module, accessible by compiling with `--features async`, that provides an `elefren::async::Client`. The client is runtime-agnostic, and currently only provides unauthenticated access, see the docs for the full list of methods that can be performed* with this client. * note that some API calls are publicly available by default, but can be changed via instance settings to not be publicly accessible
Diffstat (limited to 'src/async/client.rs')
-rw-r--r--src/async/client.rs52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/async/client.rs b/src/async/client.rs
new file mode 100644
index 0000000..5081c6f
--- /dev/null
+++ b/src/async/client.rs
@@ -0,0 +1,52 @@
+use crate::{
+ entities::{account::Account, card::Card, context::Context, status::Status},
+ errors::{Error, Result},
+};
+use http_types::{Method, Request, Response};
+use hyper_old_types::header::{parsing, Link, RelationType};
+use smol::{prelude::*, Async};
+use std::net::{TcpStream, ToSocketAddrs};
+use url::Url;
+
+// taken pretty much verbatim from `smol`s example
+
+/// Sends a request and fetches the response.
+pub(super) async fn fetch(req: Request) -> Result<Response> {
+ // Figure out the host and the port.
+ let host = req
+ .url()
+ .host()
+ .ok_or_else(|| String::from("No host found"))?
+ .to_string();
+ let port = req
+ .url()
+ .port_or_known_default()
+ .ok_or_else(|| Error::Other(String::from("No port found")))?;
+
+ // Connect to the host.
+ let socket_addr = {
+ let host = host.clone();
+ smol::unblock(move || (host.as_str(), port).to_socket_addrs())
+ .await?
+ .next()
+ .ok_or_else(|| Error::Other(String::from("No socket addr")))?
+ };
+ let stream = Async::<TcpStream>::connect(socket_addr).await?;
+
+ // Send the request and wait for the response.
+ let resp = match req.url().scheme() {
+ "http" => async_h1::connect(stream, req).await?,
+ "https" => {
+ // In case of HTTPS, establish a secure TLS connection first.
+ let stream = async_native_tls::connect(&host, stream).await?;
+ async_h1::connect(stream, req).await?
+ },
+ scheme => return Err(Error::Other(format!("unsupported scheme '{}'", scheme))),
+ };
+ Ok(resp)
+}
+
+pub(super) async fn get(url: Url) -> Result<Response> {
+ let req = Request::new(Method::Get, url);
+ Ok(fetch(req).await?)
+}