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
//! # http_net
//!
//! An HTTP/1.1 engine that does no I/O itself. Feed it the bytes a socket
//! delivered; it hands back requests (or responses) as borrowed views of
//! those bytes, decodes their bodies, and serializes what you send back.
//! The caller owns sockets, threads, and timers, so the same core runs
//! under a blocking loop, an event loop, or a test that never opens a
//! socket.
//!
//! Parsing follows RFC 9112 strictly. Messages that recipients could
//! disagree about are refused rather than repaired: conflicting
//! `Content-Length` / `Transfer-Encoding`, duplicate `Content-Length`,
//! obsolete line folding, bare CR or LF, whitespace before a colon, and
//! control characters in field values each have their own [`HttpError`].
//! Every buffer is bounded by [`Limits`], and each limit is checked before
//! the bytes it governs are buffered.
//!
//! ## Tier 1: serve and fetch (blocking, `std`)
//!
//! ```
//! # #[cfg(feature = "std")]
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use http_net::{blocking, Response};
//!
//! let server = blocking::Server::bind("127.0.0.1:0")?;
//! let addr = server.local_addr();
//! let stop = server.shutdown_handle();
//! let t = std::thread::spawn(move || server.serve(|req, _body| Response::text(200, req.path())));
//!
//! let resp = blocking::get(&format!("http://{addr}/hi"))?;
//! assert_eq!(resp.text(), Some("/hi"));
//!
//! stop.shutdown();
//! t.join().unwrap()?;
//! # Ok(())
//! # }
//! # #[cfg(not(feature = "std"))]
//! # fn main() {}
//! ```
//!
//! ## Tier 2: the sans-IO connection
//!
//! ```
//! use http_net::{Response, ServerConn, ServerEvent};
//!
//! let mut conn = ServerConn::new();
//! let mut out = Vec::new();
//! let _ = conn.feed(b"GET /status HTTP/1.1\r\nHost: localhost\r\n\r\n");
//! loop {
//! match conn.poll()? {
//! ServerEvent::Request(req) => assert_eq!(req.path(), "/status"),
//! ServerEvent::Body(_) => {}
//! ServerEvent::RequestEnd => conn.respond(&Response::text(200, "up"), &mut out)?,
//! _ => break, // NeedInput: read more from the socket
//! }
//! }
//! assert!(out.starts_with(b"HTTP/1.1 200 OK\r\n"));
//! # Ok::<(), http_net::HttpError>(())
//! ```
//!
//! [`ClientConn`] is the mirror image for the client side, and the
//! `blocking` module shows how either is driven over `std::net`.
//!
//! ## Protocol upgrades
//!
//! A request with `Connection: upgrade` and an `Upgrade` field reports
//! [`RequestHead::is_upgrade`]. Answering it with
//! [`Response::switching_protocols`] moves the connection to
//! [`ServerEvent::Upgraded`], after which
//! [`ServerConn::remaining_input`] holds any bytes of the new protocol that
//! arrived with the request. This is the hand-off point for a WebSocket
//! engine such as `ws-net`.
//!
//! ## Feature flags
//!
//! | Feature | Default | Description |
//! |---|---|---|
//! | `std` | yes | The `blocking` adapter over `std::net`. Without it the crate is `no_std` and needs only `alloc`. |
extern crate alloc;
pub use ;
pub use HttpError;
pub use ;
pub use Limits;
pub use ;
pub use ;
// The README's examples run as doctests, so its claims stay true.
;