1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! An HTTP/1, HTTP/2 and HTTP/3 library.
//!
//! Soyokaze speaks all three versions of HTTP through one set of types. A
//! [`Message`] carries a request or a response regardless of the version that
//! framed it, and every connection implements [`protocol::base::Connection`],
//! so code written against the trait works unchanged over HTTP/1.1, HTTP/2 and
//! HTTP/3.
//!
//! # Layers
//!
//! The crate is arranged in three layers, each usable on its own:
//!
//! - [`api`] holds the entry points: [`Client`] dials an origin, [`Server`]
//! binds ports and accepts connections, and [`api::common`] holds what the
//! two configure in common. The BoringSSL contexts both of them negotiate
//! with are built in [`tls`].
//! - [`protocol`] holds one connection type per version — [`protocol::h1`],
//! [`protocol::h2`] and [`protocol::h3`] — implementing the traits in
//! [`protocol::base`] over the shared vocabulary in [`protocol::common`],
//! with [`protocol::handler`] bridging each transport into a connection the
//! same way. A higher layer drives a lower one exactly the way an outside
//! caller would.
//! - [`helpers`] holds the codecs the versions share: [`helpers::huffman`],
//! [`helpers::hpack`] for HTTP/2 and [`helpers::qpack`] for HTTP/3, plus the
//! small pieces ([`helpers::base64`], [`helpers::sha1`]) the WebSocket
//! handshake needs.
//!
//! # Symmetry
//!
//! Corresponding pieces are kept interchangeable on purpose. Client and server,
//! request and response, encoder and decoder, HTTP/1 and HTTP/2 and HTTP/3 —
//! each pair shares the shape of its counterpart, and version-specific
//! connections are drop-in replacements for one another wherever the protocol
//! itself does not force a difference. Prefer naming the base type
//! ([`protocol::base::Connection`], [`AnyConnection`]) over a concrete
//! version wherever a choice exists.
//!
//! # Getting started
//!
//! Fetch a resource:
//!
//! ```no_run
//! # async fn example() -> Result<(), soyokaze::Error> {
//! let client = soyokaze::Client::default();
//! let response = client.get("https://example.com/").await?;
//!
//! println!("{:?}", response.status_code);
//! # Ok(())
//! # }
//! ```
//!
//! Serve one:
//!
//! ```no_run
//! # async fn example() -> Result<(), soyokaze::Error> {
//! use soyokaze::{Port, Server};
//!
//! struct Echo;
//! impl soyokaze::Handler for Echo {}
//!
//! let server = Server::default();
//! let handle = server.serve(Echo, &[Port::TCP(8080)]).await?;
//!
//! handle.close(None).await;
//! # Ok(())
//! # }
//! ```
//!
//! [`AnyConnection`]: protocol::base::AnyConnection
pub use Error;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use Text;
pub use WebSocketConnection;