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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#![forbid(unsafe_code)]
#![deny(
    clippy::dbg_macro,
    missing_copy_implementations,
    rustdoc::missing_crate_level_docs,
    missing_debug_implementations,
    nonstandard_style,
    unused_qualifications
)]
#![warn(missing_docs, clippy::pedantic, clippy::perf, clippy::cargo)]
#![allow(clippy::must_use_candidate, clippy::module_name_repetitions)]
/*!
This crate provides the http 1.x implementation for Trillium.

## Stability

As this is primarily intended for internal use by the [Trillium
crate](https://docs.trillium.rs/trillium), the api is likely to be
less stable than that of the higher level abstractions in Trillium.

## Example

This is an elaborate example that demonstrates some of `trillium_http`'s
capabilities.  Please note that trillium itself provides a much more
usable interface on top of `trillium_http`, at very little cost.

```
# fn main() -> trillium_http::Result<()> { smol::block_on(async {
use async_net::{TcpListener, TcpStream};
use futures_lite::StreamExt;
use stopper::Stopper;
use trillium_http::{Conn, Result};

let stopper = Stopper::new();
let listener = TcpListener::bind(("localhost", 0)).await?;
let port = listener.local_addr()?.port();

let server_stopper = stopper.clone();
let server_handle = smol::spawn(async move {
    let mut incoming = server_stopper.stop_stream(listener.incoming());

    while let Some(Ok(stream)) = incoming.next().await {
        let stopper = server_stopper.clone();
        smol::spawn(Conn::map(stream, stopper, |mut conn: Conn<TcpStream>| async move {
            conn.set_response_body("hello world");
            conn.set_status(200);
            conn
         })).detach()
    }

    Result::Ok(())
});

// this example uses the trillium client
// any other http client would work here too
let url = format!("http://localhost:{}/", port);
let client = trillium_client::Client::new(trillium_smol::ClientConfig::default());
let mut client_conn = client.get(&*url).await?;

assert_eq!(client_conn.status().unwrap(), 200);
assert_eq!(client_conn.response_headers().get_str("content-length"), Some("11"));
assert_eq!(
    client_conn.response_body().read_string().await?,
    "hello world"
);

stopper.stop(); // stop the server after one request
server_handle.await?; // wait for the server to shut down
# Result::Ok(()) }) }
```
*/

mod received_body;
pub use received_body::ReceivedBody;

#[cfg(feature = "unstable")]
pub use received_body::ReceivedBodyState;

mod error;
pub use error::{Error, Result};

mod conn;
pub use conn::{Conn, SERVER};

mod connection_status;
pub use connection_status::ConnectionStatus;

mod synthetic;
pub use synthetic::Synthetic;

mod upgrade;
pub use upgrade::Upgrade;

pub use stopper::Stopper;

mod mut_cow;
pub(crate) use mut_cow::MutCow;

mod util;

mod body;
pub use body::Body;

mod state_set;
pub use state_set::StateSet;

mod headers;
pub use headers::{HeaderName, HeaderValue, HeaderValues, Headers, KnownHeaderName};

mod status;
pub use status::Status;

mod method;
pub use method::Method;

mod version;
pub use version::Version;

/// Types to represent the bidirectional data stream over which the
/// HTTP protocol is communicated
pub mod transport;

/// A pre-rendered http response to send when the server is at capacity.
pub const SERVICE_UNAVAILABLE: &[u8] = b"HTTP/1.1 503 Service Unavailable\r
Connection: close\r
Content-Length: 0\r
Retry-After: 60\r
\r\n";

#[cfg(feature = "http-compat-1")]
pub mod http_compat1;

#[cfg(feature = "http-compat")]
pub mod http_compat0;

#[cfg(feature = "http-compat")]
pub use http_compat0 as http_compat; // for semver

mod bufwriter;
pub(crate) use bufwriter::BufWriter;

mod http_config;
pub use http_config::HttpConfig;

pub(crate) mod after_send;

mod buffer;
#[cfg(feature = "unstable")]
pub use buffer::Buffer;
#[cfg(not(feature = "unstable"))]
pub(crate) use buffer::Buffer;

mod copy;
#[cfg(feature = "unstable")]
pub use copy::copy;
#[cfg(not(feature = "unstable"))]
pub(crate) use copy::copy;