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
//! 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::common::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::tls`] builds the BoringSSL
//! contexts both of them negotiate with.
//! - [`protocol`] holds one connection type per version — [`protocol::h1`],
//! [`protocol::h2`] and [`protocol::h3`] — over the shared vocabulary in
//! [`protocol::common`]. A higher layer drives a lower one exactly the way an
//! outside caller would; HTTP/1.1 over TCP is built from a `TCPServer` and an
//! `H1Connection` with no private back channel between them.
//! - [`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::common::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::builder().build();
//! 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::builder().build();
//! let handle = server.serve(Echo, &[Port::TCP(8080)]).await?;
//!
//! handle.close(None).await;
//! # Ok(())
//! # }
//! ```
//!
//! [`AnyConnection`]: protocol::common::AnyConnection
pub use Error;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use Text;
pub use WebSocketConnection;