trillium_async_std/
client.rs1use crate::AsyncStdTransport;
2use async_std::net::TcpStream;
3use std::{
4 future::Future,
5 io::{Error, ErrorKind, Result},
6};
7use trillium_server_common::{
8 async_trait,
9 url::{Host, Url},
10 Connector, Transport,
11};
12
13#[derive(Default, Debug, Clone, Copy)]
17pub struct ClientConfig {
18 pub nodelay: Option<bool>,
20
21 pub ttl: Option<u32>,
23}
24
25impl ClientConfig {
26 pub const fn new() -> Self {
28 Self {
29 nodelay: None,
30 ttl: None,
31 }
32 }
33
34 pub const fn with_nodelay(mut self, nodelay: bool) -> Self {
36 self.nodelay = Some(nodelay);
37 self
38 }
39
40 pub const fn with_ttl(mut self, ttl: u32) -> Self {
42 self.ttl = Some(ttl);
43 self
44 }
45}
46
47#[async_trait]
48impl Connector for ClientConfig {
49 type Transport = AsyncStdTransport<TcpStream>;
50
51 async fn connect(&self, url: &Url) -> Result<Self::Transport> {
52 if url.scheme() != "http" {
53 return Err(Error::new(
54 ErrorKind::InvalidInput,
55 format!("unknown scheme {}", url.scheme()),
56 ));
57 }
58
59 let host = url
60 .host()
61 .ok_or_else(|| Error::new(ErrorKind::InvalidInput, format!("{url} missing host")))?;
62
63 let port = url
64 .port_or_known_default()
65 .ok_or_else(|| Error::new(ErrorKind::InvalidInput, format!("{url} missing port")))?;
67
68 let mut tcp = match host {
69 Host::Domain(domain) => Self::Transport::connect((domain, port)).await?,
70 Host::Ipv4(ip) => Self::Transport::connect((ip, port)).await?,
71 Host::Ipv6(ip) => Self::Transport::connect((ip, port)).await?,
72 };
73
74 if let Some(nodelay) = self.nodelay {
75 tcp.set_nodelay(nodelay)?;
76 }
77
78 if let Some(ttl) = self.ttl {
79 tcp.set_ip_ttl(ttl)?;
80 }
81
82 Ok(tcp)
83 }
84
85 fn spawn<Fut: Future<Output = ()> + Send + 'static>(&self, fut: Fut) {
86 async_std::task::spawn(fut);
87 }
88}