http_net/blocking.rs
1//! A small blocking adapter over `std::net`: the Tier-1 path.
2//!
3//! [`Server`] serves a handler on a socket with one thread per connection
4//! (bounded by [`ServerConfig::with_max_connections`]); [`Connection`] is the
5//! per-connection loop for callers who run their own accept loop or need the
6//! socket back after an upgrade; [`get`] fetches a URL. Everything here is a
7//! thin shell around [`ServerConn`] and [`ClientConn`]: all parsing, framing,
8//! and limit enforcement happens in the sans-IO core.
9//!
10//! Only plain `http://` is spoken; there is no TLS in this crate.
11//!
12//! The server is for local, development, and trusted-network use. One
13//! thread serves each connection, up to the connection cap (64 by
14//! default), and the cap is the only admission control: a peer that holds
15//! that many slow connections keeps other clients waiting until the
16//! request timeout ends each one. An internet-facing server drives
17//! [`ServerConn`] from an event loop with per-peer limits (serve-net does).
18
19use std::{
20 cell::Cell,
21 fmt, io,
22 io::{IoSlice, Read, Write},
23 net::{
24 IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, TcpListener, TcpStream, ToSocketAddrs,
25 },
26 string::{String, ToString},
27 sync::{
28 Arc, Condvar, Mutex,
29 atomic::{AtomicBool, Ordering},
30 },
31 thread,
32 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
33 vec::Vec,
34};
35
36use crate::{
37 BodyPlan, ClientConn, ClientEvent, DateCache, HttpDate, HttpError, Limits, Method, Progress,
38 Request, RequestHead, Response, ServerConn, ServerEvent,
39 message::OutBody,
40 redact::{FieldValue, Target, serialized_fields},
41};
42
43/// Bytes a closing connection reads and discards so the peer's unread data
44/// does not turn the close into a reset that destroys the last response.
45const DRAIN_LIMIT: usize = 256 * 1024;
46/// How long one read of the lingering close may wait.
47const DRAIN_READ_TIMEOUT: Duration = Duration::from_millis(250);
48/// How long the whole lingering close may take, however the peer behaves:
49/// a peer that keeps sending must not keep the connection (and its slot).
50const DRAIN_TOTAL: Duration = Duration::from_secs(1);
51/// Responses larger than this do not keep their output buffer afterwards.
52const OUT_RETAIN: usize = 64 * 1024;
53/// Full bodies larger than this are written after the head with one
54/// vectored write instead of being copied into the output buffer.
55const VECTORED_BODY: usize = 4 * 1024;
56
57/// What can go wrong in the blocking adapter.
58///
59/// # Examples
60///
61/// ```
62/// let err = http_net::blocking::get("https://example.com/").unwrap_err();
63/// assert!(matches!(err, http_net::blocking::Error::InvalidUrl(_)));
64/// ```
65#[non_exhaustive]
66#[derive(Debug)]
67pub enum Error {
68 /// The socket failed (connect, read, write, or timeout).
69 Io(io::Error),
70 /// The peer sent a message this crate refuses, or a call was out of
71 /// order.
72 Http(HttpError),
73 /// The URL is not `http://host[:port][/path[?query]]` (a `#fragment` is
74 /// dropped); the text says which part is wrong.
75 InvalidUrl(&'static str),
76}
77
78impl fmt::Display for Error {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 match self {
81 Self::Io(e) => write!(f, "I/O error: {e}"),
82 Self::Http(e) => write!(f, "HTTP error: {e}"),
83 Self::InvalidUrl(why) => write!(f, "invalid URL: {why}"),
84 }
85 }
86}
87
88impl std::error::Error for Error {
89 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
90 match self {
91 Self::Io(e) => Some(e),
92 Self::Http(e) => Some(e),
93 Self::InvalidUrl(_) => None,
94 }
95 }
96}
97
98impl From<io::Error> for Error {
99 fn from(e: io::Error) -> Self {
100 Self::Io(e)
101 }
102}
103
104impl From<HttpError> for Error {
105 fn from(e: HttpError) -> Self {
106 Self::Http(e)
107 }
108}
109
110/// Settings for [`Server`].
111///
112/// | Setting | Default |
113/// |---|---|
114/// | limits | [`Limits::new`] |
115/// | concurrent connections | 64 (the 65th is answered `503` and closed) |
116/// | read timeout (also the idle keep-alive timeout) | 10 s |
117/// | request timeout (first byte of a request to the end of its body) | 30 s |
118/// | write timeout (each write) | 10 s |
119/// | response deadline (writing one whole response) | 60 s |
120/// | requests per connection | no cap |
121///
122/// # Examples
123///
124/// ```
125/// use std::time::Duration;
126/// use http_net::{blocking::ServerConfig, Limits};
127///
128/// let config = ServerConfig::new()
129/// .with_limits(Limits::new().with_max_body(16 * 1024))
130/// .with_max_connections(8)
131/// .with_read_timeout(Duration::from_secs(5));
132/// assert_eq!(config.max_connections(), 8);
133/// ```
134#[derive(Clone, Copy, Debug, PartialEq, Eq)]
135pub struct ServerConfig {
136 limits: Limits,
137 max_connections: usize,
138 read_timeout: Option<Duration>,
139 request_timeout: Option<Duration>,
140 write_timeout: Option<Duration>,
141 response_deadline: Option<Duration>,
142 max_requests: Option<u64>,
143}
144
145impl Default for ServerConfig {
146 fn default() -> Self {
147 Self::new()
148 }
149}
150
151impl ServerConfig {
152 /// The defaults (see the table on [`ServerConfig`]).
153 ///
154 /// # Examples
155 ///
156 /// ```
157 /// assert_eq!(http_net::blocking::ServerConfig::new().max_connections(), 64);
158 /// ```
159 #[must_use]
160 pub const fn new() -> Self {
161 Self {
162 limits: Limits::new(),
163 max_connections: 64,
164 read_timeout: Some(Duration::from_secs(10)),
165 request_timeout: Some(Duration::from_secs(30)),
166 write_timeout: Some(Duration::from_secs(10)),
167 response_deadline: Some(Duration::from_secs(60)),
168 max_requests: None,
169 }
170 }
171
172 /// Sets the message limits for every connection.
173 ///
174 /// # Examples
175 ///
176 /// ```
177 /// let c = http_net::blocking::ServerConfig::new()
178 /// .with_limits(http_net::Limits::new().with_max_headers(10));
179 /// assert_eq!(c.limits().max_headers(), 10);
180 /// ```
181 #[must_use]
182 pub const fn with_limits(mut self, limits: Limits) -> Self {
183 self.limits = limits;
184 self
185 }
186
187 /// Sets how many connections are served at once (at least 1).
188 ///
189 /// # Examples
190 ///
191 /// ```
192 /// let c = http_net::blocking::ServerConfig::new().with_max_connections(0);
193 /// assert_eq!(c.max_connections(), 1);
194 /// ```
195 #[must_use]
196 pub const fn with_max_connections(mut self, n: usize) -> Self {
197 self.max_connections = if n == 0 { 1 } else { n };
198 self
199 }
200
201 /// Sets the socket read timeout: the longest a single read may wait for
202 /// bytes (the longest pause within a request), and how long an idle
203 /// keep-alive connection is held. Pass a `Duration`, or `None` to wait
204 /// forever.
205 ///
206 /// # Examples
207 ///
208 /// ```
209 /// use std::time::Duration;
210 /// use http_net::blocking::ServerConfig;
211 ///
212 /// let c = ServerConfig::new().with_read_timeout(Duration::from_secs(5));
213 /// assert_eq!(c.read_timeout(), Some(Duration::from_secs(5)));
214 /// assert_eq!(c.with_read_timeout(None).read_timeout(), None);
215 /// ```
216 #[must_use]
217 pub fn with_read_timeout(mut self, timeout: impl Into<Option<Duration>>) -> Self {
218 self.read_timeout = timeout.into();
219 self
220 }
221
222 /// Sets the request timeout: the most time one request may take to
223 /// arrive, from its first byte to the end of its body. The read timeout
224 /// alone cannot stop a client that sends one byte just inside it
225 /// ("slowloris"); this deadline can. A request still incomplete when it
226 /// passes is answered `408 Request Timeout` and the connection closed.
227 /// Time spent idle between keep-alive requests does not count (the read
228 /// timeout governs that). Pass a `Duration`, or `None` to disable the
229 /// deadline.
230 ///
231 /// # Examples
232 ///
233 /// ```
234 /// use std::time::Duration;
235 /// let c = http_net::blocking::ServerConfig::new().with_request_timeout(Duration::from_secs(10));
236 /// assert_eq!(c.request_timeout(), Some(Duration::from_secs(10)));
237 /// ```
238 #[must_use]
239 pub fn with_request_timeout(mut self, timeout: impl Into<Option<Duration>>) -> Self {
240 self.request_timeout = timeout.into();
241 self
242 }
243
244 /// Sets the socket write timeout. Pass a `Duration`, or `None` to wait
245 /// forever.
246 ///
247 /// # Examples
248 ///
249 /// ```
250 /// use std::time::Duration;
251 /// let c = http_net::blocking::ServerConfig::new().with_write_timeout(Duration::from_secs(1));
252 /// assert_eq!(c.write_timeout(), Some(Duration::from_secs(1)));
253 /// ```
254 #[must_use]
255 pub fn with_write_timeout(mut self, timeout: impl Into<Option<Duration>>) -> Self {
256 self.write_timeout = timeout.into();
257 self
258 }
259
260 /// Sets the response deadline: the most time writing one response may
261 /// take, from its first byte to its last (a streamed body included).
262 /// The write timeout bounds each write; it cannot stop a client that
263 /// reads one byte just inside it and so holds a thread for as long as a
264 /// large response takes. This deadline can: when it passes, the
265 /// connection is closed. Pass a `Duration`, or `None` to disable it.
266 ///
267 /// # Examples
268 ///
269 /// ```
270 /// use std::time::Duration;
271 /// let c = http_net::blocking::ServerConfig::new().with_response_deadline(Duration::from_secs(5));
272 /// assert_eq!(c.response_deadline(), Some(Duration::from_secs(5)));
273 /// ```
274 #[must_use]
275 pub fn with_response_deadline(mut self, deadline: impl Into<Option<Duration>>) -> Self {
276 self.response_deadline = deadline.into();
277 self
278 }
279
280 /// Sets the most requests served on one connection: the response that
281 /// reaches the cap carries `connection: close` and the connection ends
282 /// after it. Pass a count (0 is raised to 1), or `None` (the default)
283 /// for no cap.
284 ///
285 /// # Examples
286 ///
287 /// ```
288 /// let c = http_net::blocking::ServerConfig::new().with_max_requests_per_connection(100);
289 /// assert_eq!(c.max_requests_per_connection(), Some(100));
290 /// ```
291 #[must_use]
292 pub fn with_max_requests_per_connection(mut self, max: impl Into<Option<u64>>) -> Self {
293 self.max_requests = match max.into() {
294 Some(0) => Some(1),
295 other => other,
296 };
297 self
298 }
299
300 /// The message limits.
301 ///
302 /// # Examples
303 ///
304 /// ```
305 /// assert_eq!(http_net::blocking::ServerConfig::new().limits(), http_net::Limits::new());
306 /// ```
307 #[must_use]
308 pub const fn limits(&self) -> Limits {
309 self.limits
310 }
311
312 /// The concurrent connection cap.
313 ///
314 /// # Examples
315 ///
316 /// ```
317 /// assert_eq!(http_net::blocking::ServerConfig::new().max_connections(), 64);
318 /// ```
319 #[must_use]
320 pub const fn max_connections(&self) -> usize {
321 self.max_connections
322 }
323
324 /// The read timeout.
325 ///
326 /// # Examples
327 ///
328 /// ```
329 /// use std::time::Duration;
330 /// assert_eq!(http_net::blocking::ServerConfig::new().read_timeout(), Some(Duration::from_secs(10)));
331 /// ```
332 #[must_use]
333 pub const fn read_timeout(&self) -> Option<Duration> {
334 self.read_timeout
335 }
336
337 /// The request timeout.
338 ///
339 /// # Examples
340 ///
341 /// ```
342 /// use std::time::Duration;
343 /// assert_eq!(http_net::blocking::ServerConfig::new().request_timeout(), Some(Duration::from_secs(30)));
344 /// ```
345 #[must_use]
346 pub const fn request_timeout(&self) -> Option<Duration> {
347 self.request_timeout
348 }
349
350 /// The write timeout.
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// use std::time::Duration;
356 /// assert_eq!(http_net::blocking::ServerConfig::new().write_timeout(), Some(Duration::from_secs(10)));
357 /// ```
358 #[must_use]
359 pub const fn write_timeout(&self) -> Option<Duration> {
360 self.write_timeout
361 }
362
363 /// The response deadline.
364 ///
365 /// # Examples
366 ///
367 /// ```
368 /// use std::time::Duration;
369 /// assert_eq!(http_net::blocking::ServerConfig::new().response_deadline(), Some(Duration::from_secs(60)));
370 /// ```
371 #[must_use]
372 pub const fn response_deadline(&self) -> Option<Duration> {
373 self.response_deadline
374 }
375
376 /// The cap on requests per connection.
377 ///
378 /// # Examples
379 ///
380 /// ```
381 /// assert_eq!(http_net::blocking::ServerConfig::new().max_requests_per_connection(), None);
382 /// ```
383 #[must_use]
384 pub const fn max_requests_per_connection(&self) -> Option<u64> {
385 self.max_requests
386 }
387}
388
389/// A connection handed over by a `101 Switching Protocols` (or a 2xx to
390/// `CONNECT`): the socket, the bytes of the new protocol that already
391/// arrived, and the target of the request that asked for the switch.
392///
393/// # Examples
394///
395/// Not run: it serves until the process ends.
396///
397/// ```no_run
398/// use http_net::{blocking::Server, Response};
399///
400/// let server = Server::bind("127.0.0.1:0")?.on_upgrade(|up| {
401/// // Hand `up.stream` and `up.leftover` to a protocol engine.
402/// let _ = (up.stream, up.leftover, up.target);
403/// });
404/// server.serve(|req, _body| {
405/// if req.is_upgrade() {
406/// Response::switching_protocols("x")
407/// } else {
408/// Response::new(404)
409/// }
410/// })?;
411/// # Ok::<(), std::io::Error>(())
412/// ```
413#[non_exhaustive]
414pub struct Upgraded {
415 /// The socket, now speaking the new protocol.
416 pub stream: TcpStream,
417 /// Bytes of the new protocol received together with the request.
418 pub leftover: Vec<u8>,
419 /// The target of the request that asked for the switch.
420 pub target: String,
421}
422
423/// `leftover` prints as its length: after a `CONNECT` it can be a whole
424/// request in clear text, credentials included.
425impl fmt::Debug for Upgraded {
426 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
427 f.debug_struct("Upgraded")
428 .field("stream", &self.stream)
429 .field("leftover", &format_args!("{} bytes", self.leftover.len()))
430 .field("target", &Target(&self.target))
431 .finish()
432 }
433}
434
435type UpgradeHook = Arc<dyn Fn(Upgraded) + Send + Sync>;
436
437/// A blocking HTTP/1.1 server: one thread per connection, bounded.
438///
439/// # Examples
440///
441/// ```
442/// use http_net::{blocking::{self, Server}, Response};
443///
444/// let server = Server::bind("127.0.0.1:0")?;
445/// let addr = server.local_addr();
446/// let stop = server.shutdown_handle();
447/// let thread = std::thread::spawn(move || {
448/// server.serve(|req, _body| Response::text(200, &format!("you asked for {}", req.path())))
449/// });
450///
451/// let resp = blocking::get(&format!("http://{addr}/hello"))?;
452/// assert_eq!(resp.status(), 200);
453/// assert_eq!(resp.text(), Some("you asked for /hello"));
454///
455/// stop.shutdown();
456/// thread.join().unwrap()?;
457/// # Ok::<(), Box<dyn std::error::Error>>(())
458/// ```
459pub struct Server {
460 listener: TcpListener,
461 local: SocketAddr,
462 config: ServerConfig,
463 stop: Arc<AtomicBool>,
464 upgrade: Option<UpgradeHook>,
465}
466
467impl fmt::Debug for Server {
468 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
469 f.debug_struct("Server")
470 .field("local_addr", &self.local)
471 .field("config", &self.config)
472 .finish()
473 }
474}
475
476/// Stops a running [`Server::serve`] from another thread.
477///
478/// # Examples
479///
480/// ```
481/// let server = http_net::blocking::Server::bind("127.0.0.1:0")?;
482/// let stop = server.shutdown_handle();
483/// let t = std::thread::spawn(move || server.serve(|_, _| http_net::Response::new(204)));
484/// stop.shutdown();
485/// t.join().unwrap()?;
486/// # Ok::<(), std::io::Error>(())
487/// ```
488#[derive(Clone, Debug)]
489pub struct ShutdownHandle {
490 stop: Arc<AtomicBool>,
491 wake: SocketAddr,
492}
493
494impl ShutdownHandle {
495 /// Asks the server to stop: it accepts no new connections and returns
496 /// from `serve` once every open connection has ended. The stop is
497 /// checked between exchanges, so an exchange in progress finishes. An
498 /// idle keep-alive connection ends when its read timeout passes, or
499 /// after one more request if the client sends one first; with no read
500 /// timeout, `serve` does not return while a client holds an idle
501 /// connection.
502 ///
503 /// # Examples
504 ///
505 /// See [`ShutdownHandle`].
506 pub fn shutdown(&self) {
507 self.stop.store(true, Ordering::SeqCst);
508 // `accept` blocks; a throwaway connection wakes it so it sees the
509 // flag. If the connect fails the listener is already gone, which is
510 // the outcome being asked for, so the error carries no information.
511 if let Ok(stream) = TcpStream::connect_timeout(&self.wake, Duration::from_secs(1)) {
512 drop(stream);
513 }
514 }
515}
516
517/// Counts live connection threads so shutdown can wait for them.
518#[derive(Default)]
519struct Active {
520 count: Mutex<usize>,
521 idle: Condvar,
522}
523
524impl Active {
525 fn try_enter(&self, max: usize) -> bool {
526 let mut n = self
527 .count
528 .lock()
529 .unwrap_or_else(std::sync::PoisonError::into_inner);
530 if *n >= max {
531 return false;
532 }
533 *n += 1;
534 true
535 }
536
537 fn leave(&self) {
538 let mut n = self
539 .count
540 .lock()
541 .unwrap_or_else(std::sync::PoisonError::into_inner);
542 *n = n.saturating_sub(1);
543 if *n == 0 {
544 self.idle.notify_all();
545 }
546 }
547
548 fn wait_idle(&self) {
549 let mut n = self
550 .count
551 .lock()
552 .unwrap_or_else(std::sync::PoisonError::into_inner);
553 while *n > 0 {
554 n = self
555 .idle
556 .wait(n)
557 .unwrap_or_else(std::sync::PoisonError::into_inner);
558 }
559 }
560}
561
562/// Leaves the active set even if the handler panics.
563struct ActiveGuard(Arc<Active>);
564
565impl Drop for ActiveGuard {
566 fn drop(&mut self) {
567 self.0.leave();
568 }
569}
570
571impl Server {
572 /// Binds a listening socket. Use `127.0.0.1:0` for an ephemeral
573 /// localhost port and read it back with [`local_addr`](Self::local_addr).
574 ///
575 /// # Errors
576 ///
577 /// The bind error from the operating system.
578 ///
579 /// # Examples
580 ///
581 /// ```
582 /// let server = http_net::blocking::Server::bind("127.0.0.1:0")?;
583 /// assert!(server.local_addr().ip().is_loopback());
584 /// # Ok::<(), std::io::Error>(())
585 /// ```
586 pub fn bind(addr: impl ToSocketAddrs) -> io::Result<Self> {
587 let listener = TcpListener::bind(addr)?;
588 let local = listener.local_addr()?;
589 Ok(Self {
590 listener,
591 local,
592 config: ServerConfig::new(),
593 stop: Arc::new(AtomicBool::new(false)),
594 upgrade: None,
595 })
596 }
597
598 /// Replaces the configuration.
599 ///
600 /// # Examples
601 ///
602 /// ```
603 /// use http_net::blocking::{Server, ServerConfig};
604 /// let s = Server::bind("127.0.0.1:0")?.with_config(ServerConfig::new().with_max_connections(4));
605 /// # Ok::<(), std::io::Error>(())
606 /// ```
607 #[must_use]
608 pub fn with_config(mut self, config: ServerConfig) -> Self {
609 self.config = config;
610 self
611 }
612
613 /// Sets what happens to a connection after the handler answers with
614 /// `101 Switching Protocols` (or a 2xx to `CONNECT`): `hook` receives
615 /// the socket on the
616 /// connection's thread. Without a hook such connections are closed.
617 ///
618 /// # Examples
619 ///
620 /// See [`Upgraded`].
621 #[must_use]
622 pub fn on_upgrade(mut self, hook: impl Fn(Upgraded) + Send + Sync + 'static) -> Self {
623 self.upgrade = Some(Arc::new(hook));
624 self
625 }
626
627 /// The bound address (with the real port when bound to port 0).
628 ///
629 /// # Examples
630 ///
631 /// ```
632 /// let server = http_net::blocking::Server::bind("127.0.0.1:0")?;
633 /// assert_ne!(server.local_addr().port(), 0);
634 /// # Ok::<(), std::io::Error>(())
635 /// ```
636 #[must_use]
637 pub fn local_addr(&self) -> SocketAddr {
638 self.local
639 }
640
641 /// A handle that stops [`serve`](Self::serve) from another thread.
642 ///
643 /// # Examples
644 ///
645 /// See [`ShutdownHandle`].
646 #[must_use]
647 pub fn shutdown_handle(&self) -> ShutdownHandle {
648 let mut wake = self.local;
649 if wake.ip().is_unspecified() {
650 wake.set_ip(match wake.ip() {
651 IpAddr::V4(_) => IpAddr::V4(Ipv4Addr::LOCALHOST),
652 IpAddr::V6(_) => IpAddr::V6(Ipv6Addr::LOCALHOST),
653 });
654 }
655 ShutdownHandle {
656 stop: Arc::clone(&self.stop),
657 wake,
658 }
659 }
660
661 /// Serves `handler` until [`ShutdownHandle::shutdown`] is called.
662 ///
663 /// The handler gets each request's head and its complete body (bounded
664 /// by [`Limits::max_body`]) and returns the response. Requests that fail
665 /// to parse are answered with [`Response::from_error`] and the
666 /// connection is closed; the handler never sees them. A request with
667 /// `Expect: 100-continue` gets `100 Continue` before its body is read;
668 /// one with any other expectation is answered `417 Expectation Failed`
669 /// without reading its body (RFC 9110 section 10.1.1), and the
670 /// connection is closed. A handler that returns a streamed response
671 /// (`chunked` or `content_length`, except to `HEAD`), or one that
672 /// [`ServerConn::respond`] refuses, is replaced by a `500` with
673 /// `connection: close`. Every response gets a `date` field (from
674 /// [`now_date`]) unless the handler set one, except the `503` sent to a
675 /// connection over the connection cap. The time limits and the request
676 /// cap of [`ServerConfig`] apply to every connection.
677 ///
678 /// # Errors
679 ///
680 /// Only if accepting connections fails persistently; transient accept
681 /// errors are retried. Before the error is returned, live connections
682 /// finish their current exchange, as after a shutdown.
683 ///
684 /// # Examples
685 ///
686 /// See [`Server`].
687 pub fn serve<H>(self, handler: H) -> io::Result<()>
688 where
689 H: Fn(&RequestHead<'_>, &[u8]) -> Response + Send + Sync + 'static,
690 {
691 let handler = Arc::new(handler);
692 let active = Arc::new(Active::default());
693 let mut backoff = AcceptBackoff::default();
694 for incoming in self.listener.incoming() {
695 if self.stop.load(Ordering::SeqCst) {
696 break;
697 }
698 let stream = match incoming {
699 Ok(stream) => {
700 backoff.success();
701 stream
702 }
703 Err(e) => match backoff.failure(e) {
704 Ok(wait) => {
705 thread::sleep(wait);
706 continue;
707 }
708 Err(e) => {
709 // Give up as a shutdown does: live connections
710 // finish their exchange before `serve` returns.
711 self.stop.store(true, Ordering::SeqCst);
712 active.wait_idle();
713 return Err(e);
714 }
715 },
716 };
717 if !active.try_enter(self.config.max_connections) {
718 refuse_busy(stream, &self.config);
719 continue;
720 }
721 let guard = ActiveGuard(Arc::clone(&active));
722 let handler = Arc::clone(&handler);
723 let upgrade = self.upgrade.clone();
724 let stop = Arc::clone(&self.stop);
725 let config = self.config;
726 let spawned = thread::Builder::new()
727 .name("http-net-conn".into())
728 .spawn(move || {
729 let _guard = guard;
730 serve_stream(stream, &config, &*handler, upgrade.as_deref(), &stop);
731 });
732 // A failed spawn drops the closure, its guard, and the stream:
733 // the connection is closed and the slot released.
734 drop(spawned);
735 }
736 active.wait_idle();
737 Ok(())
738 }
739}
740
741/// What the accept loop does after an accept error (threat T-41). Aborted
742/// handshakes and descriptor exhaustion are transient, so it waits instead
743/// of spinning a core, and gives up only when accept never recovers.
744#[derive(Debug, Default)]
745struct AcceptBackoff {
746 consecutive: u32,
747}
748
749impl AcceptBackoff {
750 /// The wait after each failed accept.
751 const WAIT: Duration = Duration::from_millis(10);
752 /// Consecutive failures tolerated before `serve` returns the error.
753 const LIMIT: u32 = 1000;
754
755 fn success(&mut self) {
756 self.consecutive = 0;
757 }
758
759 /// The wait before the next accept, or the error to stop with.
760 fn failure(&mut self, error: io::Error) -> io::Result<Duration> {
761 self.consecutive += 1;
762 if self.consecutive > Self::LIMIT {
763 Err(error)
764 } else {
765 Ok(Self::WAIT)
766 }
767 }
768}
769
770fn refuse_busy(mut stream: TcpStream, config: &ServerConfig) {
771 const BUSY: &[u8] =
772 b"HTTP/1.1 503 Service Unavailable\r\ncontent-length: 0\r\nconnection: close\r\n\r\n";
773 // Best effort on a connection being turned away: a failure here only
774 // means the client already left. This runs on the accept thread, so it
775 // must never wait on the peer: the 503 fits in an empty send buffer,
776 // and only what has already arrived is drained (without blocking) so
777 // that it does not turn the close into a reset.
778 if stream.set_write_timeout(config.write_timeout).is_err()
779 || stream.write_all(BUSY).is_err()
780 || stream.shutdown(Shutdown::Write).is_err()
781 || stream.set_nonblocking(true).is_err()
782 {
783 return;
784 }
785 let mut scratch = [0u8; 4096];
786 let mut drained = 0;
787 while drained < DRAIN_LIMIT {
788 match stream.read(&mut scratch) {
789 Ok(n) if n > 0 => drained += n,
790 _ => break,
791 }
792 }
793}
794
795fn serve_stream(
796 stream: TcpStream,
797 config: &ServerConfig,
798 handler: &(dyn Fn(&RequestHead<'_>, &[u8]) -> Response + Send + Sync),
799 upgrade: Option<&(dyn Fn(Upgraded) + Send + Sync)>,
800 stop: &AtomicBool,
801) {
802 let configured = stream.set_read_timeout(config.read_timeout).is_ok()
803 && stream.set_write_timeout(config.write_timeout).is_ok()
804 && stream.set_nodelay(true).is_ok();
805 if !configured {
806 return;
807 }
808 let mut conn = Connection::new(stream)
809 .with_limits(config.limits)
810 .with_request_timeout(config.request_timeout)
811 .with_response_deadline(config.response_deadline);
812 conn.refuse_unknown_expectations = true;
813 while !stop.load(Ordering::SeqCst) {
814 // The handler runs inside the first match; errors (which borrow
815 // nothing) are handled in the second, where `conn` is free again.
816 let outcome = match conn.next_request() {
817 Ok(Some(incoming)) => {
818 let head = incoming.head();
819 Ok((
820 handler(&head, incoming.body()),
821 head.method() == Method::Head,
822 ))
823 }
824 Ok(None) => break,
825 Err(e) => Err(e),
826 };
827 let (response, is_head) = match outcome {
828 Ok(answer) => answer,
829 Err(Error::Http(e)) => {
830 if conn.respond(&Response::from_error(&e)).is_err() {
831 return;
832 }
833 break;
834 }
835 Err(Error::Io(e)) if is_timeout(&e) && conn.request_in_progress() => {
836 // A request that did not arrive in time: say so, then
837 // close (the rest of it can no longer be framed).
838 if conn.send_request_timeout().is_ok() {
839 conn.close();
840 }
841 return;
842 }
843 Err(_) => return,
844 };
845 // `Server` writes full bodies only: the handler has no way to send
846 // a streamed one, so it would leave the client waiting. A `HEAD`
847 // answer is the exception: it announces a length or chunked
848 // framing but carries no body, so it is complete once written.
849 let streamed = response.body_bytes().is_none();
850 let response = if streamed && !is_head {
851 Response::text(
852 500,
853 "handler error: Server cannot send a streamed response; \
854 use Connection for streaming",
855 )
856 .close()
857 } else {
858 response
859 };
860 if config
861 .max_requests
862 .is_some_and(|max| conn.conn.requests_served().saturating_add(1) >= max)
863 {
864 // This response reaches the cap: it carries `connection: close`.
865 conn.conn.set_keep_alive(false);
866 }
867 match conn.respond(&response) {
868 Ok(()) if streamed && is_head => {
869 if conn.end_body().is_err() {
870 return;
871 }
872 }
873 Ok(()) => {}
874 // Refused before anything was written (a builder error, or a
875 // 101 to a request that did not ask): answer 500 instead.
876 Err(Error::Http(e)) => {
877 let message = format!("handler error: invalid response: {e}");
878 if conn
879 .respond(&Response::text(500, &message).close())
880 .is_err()
881 {
882 return;
883 }
884 }
885 Err(_) => return,
886 }
887 if conn.is_upgraded() {
888 match (conn.into_upgraded(), upgrade) {
889 (Some(up), Some(hook)) => hook(up),
890 (Some(up), None) => drain_and_close(up.stream),
891 (None, _) => {}
892 }
893 return;
894 }
895 }
896 conn.close();
897}
898
899fn drain_and_close(mut stream: TcpStream) {
900 let _ = lingering_drain(&mut stream);
901}
902
903/// Lingering close (RFC 9112 section 9.6): stops sending, then reads what
904/// the peer is still sending so the close does not become a reset that
905/// discards the response before the peer reads it. Returns the bytes
906/// drained.
907///
908/// The drain is bounded in bytes and in total time, not only per read: a
909/// peer that keeps trickling data must not hold the thread.
910fn lingering_drain(stream: &mut TcpStream) -> usize {
911 if stream.flush().is_err() || stream.shutdown(Shutdown::Write).is_err() {
912 return 0;
913 }
914 let deadline = Instant::now() + DRAIN_TOTAL;
915 let mut scratch = [0u8; 4096];
916 let mut drained = 0;
917 while drained < DRAIN_LIMIT {
918 let left = deadline.saturating_duration_since(Instant::now());
919 if left.is_zero()
920 || stream
921 .set_read_timeout(Some(left.min(DRAIN_READ_TIMEOUT)))
922 .is_err()
923 {
924 break;
925 }
926 match stream.read(&mut scratch) {
927 Ok(0) | Err(_) => break,
928 Ok(n) => drained += n,
929 }
930 }
931 drained
932}
933
934fn response_timed_out() -> Error {
935 Error::Io(io::Error::new(
936 io::ErrorKind::TimedOut,
937 "the response was not written within the response deadline",
938 ))
939}
940
941/// The error for a request that missed its deadline.
942fn request_timed_out() -> Error {
943 Error::Io(io::Error::new(
944 io::ErrorKind::TimedOut,
945 "the request did not arrive within the request timeout",
946 ))
947}
948
949fn is_timeout(e: &io::Error) -> bool {
950 // Unix reports an expired socket timeout as WouldBlock, Windows as
951 // TimedOut.
952 matches!(
953 e.kind(),
954 io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock
955 )
956}
957
958/// One request read by [`Connection::next_request`]: its head and its
959/// complete body.
960///
961/// # Examples
962///
963/// See [`Connection`].
964pub struct Incoming<'a> {
965 head: RequestHead<'a>,
966 body: &'a [u8],
967}
968
969/// The body prints as its length, as in [`Connection`] and
970/// [`ClientResponse`].
971impl fmt::Debug for Incoming<'_> {
972 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
973 f.debug_struct("Incoming")
974 .field("head", &self.head)
975 .field("body", &format_args!("{} bytes", self.body.len()))
976 .finish()
977 }
978}
979
980impl<'a> Incoming<'a> {
981 /// The request head.
982 ///
983 /// # Examples
984 ///
985 /// See [`Connection`].
986 #[must_use]
987 pub fn head(&self) -> RequestHead<'a> {
988 self.head
989 }
990
991 /// The complete request body (empty when there is none).
992 ///
993 /// # Examples
994 ///
995 /// See [`Connection`].
996 #[must_use]
997 pub fn body(&self) -> &'a [u8] {
998 self.body
999 }
1000}
1001
1002/// A blocking server connection: [`ServerConn`] driven over a `TcpStream`.
1003///
1004/// Use it for your own accept loop, or to keep the socket after an
1005/// upgrade with [`into_upgraded`](Self::into_upgraded).
1006///
1007/// # Examples
1008///
1009/// ```
1010/// use std::net::{TcpListener, TcpStream};
1011/// use std::io::{Read, Write};
1012/// use http_net::{blocking::Connection, Response};
1013///
1014/// let listener = TcpListener::bind("127.0.0.1:0")?;
1015/// let addr = listener.local_addr()?;
1016/// let client = std::thread::spawn(move || -> std::io::Result<Vec<u8>> {
1017/// let mut s = TcpStream::connect(addr)?;
1018/// s.write_all(b"POST /sum HTTP/1.1\r\nHost: x\r\nContent-Length: 3\r\nConnection: close\r\n\r\n1 2")?;
1019/// let mut reply = Vec::new();
1020/// s.read_to_end(&mut reply)?;
1021/// Ok(reply)
1022/// });
1023///
1024/// let (stream, _) = listener.accept()?;
1025/// let mut conn = Connection::new(stream);
1026/// while let Some(req) = conn.next_request()? {
1027/// let sum: u32 = std::str::from_utf8(req.body())?.split(' ').filter_map(|n| n.parse::<u32>().ok()).sum();
1028/// let response = Response::text(200, &sum.to_string());
1029/// conn.respond(&response)?;
1030/// }
1031/// conn.close();
1032/// let reply = client.join().unwrap()?;
1033/// assert!(reply.ends_with(b"\r\n\r\n3"));
1034/// # Ok::<(), Box<dyn std::error::Error>>(())
1035/// ```
1036pub struct Connection {
1037 stream: TcpStream,
1038 conn: ServerConn,
1039 body: Vec<u8>,
1040 out: Vec<u8>,
1041 /// The socket's own read timeout, restored once a request deadline no
1042 /// longer applies.
1043 read_timeout: Option<Duration>,
1044 request_timeout: Option<Duration>,
1045 /// When the request being read must be complete.
1046 deadline: Option<Instant>,
1047 /// Whether the socket's read timeout is currently shortened to the
1048 /// deadline.
1049 shortened: bool,
1050 /// The socket's own write timeout, restored after a response deadline
1051 /// shortened it.
1052 write_timeout: Option<Duration>,
1053 response_deadline: Option<Duration>,
1054 /// When the response being written must be complete.
1055 write_deadline: Option<Instant>,
1056 write_shortened: bool,
1057 /// `Server` answers expectations other than `100-continue` with 417
1058 /// before the body is read; a bare `Connection` leaves them to the
1059 /// caller.
1060 refuse_unknown_expectations: bool,
1061}
1062
1063/// The buffers print as lengths only: they hold the last request body and
1064/// the last serialized response, which may carry credentials.
1065impl fmt::Debug for Connection {
1066 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1067 f.debug_struct("Connection")
1068 .field("stream", &self.stream)
1069 .field("conn", &self.conn)
1070 .field("body_len", &self.body.len())
1071 .field("out_len", &self.out.len())
1072 .field("read_timeout", &self.read_timeout)
1073 .field("request_timeout", &self.request_timeout)
1074 .field("write_timeout", &self.write_timeout)
1075 .field("response_deadline", &self.response_deadline)
1076 .finish_non_exhaustive()
1077 }
1078}
1079
1080impl Connection {
1081 /// Wraps an accepted socket, with the default [`Limits`]. Set its
1082 /// timeouts first if you want them: the read timeout set on `stream` is
1083 /// the idle timeout, and
1084 /// [`with_request_timeout`](Self::with_request_timeout) adds a deadline
1085 /// for each request as a whole.
1086 ///
1087 /// # Examples
1088 ///
1089 /// See [`Connection`].
1090 #[must_use]
1091 pub fn new(stream: TcpStream) -> Self {
1092 let read_timeout = stream.read_timeout().ok().flatten();
1093 let write_timeout = stream.write_timeout().ok().flatten();
1094 Self {
1095 stream,
1096 conn: ServerConn::new(),
1097 body: Vec::new(),
1098 out: Vec::new(),
1099 read_timeout,
1100 request_timeout: None,
1101 deadline: None,
1102 shortened: false,
1103 write_timeout,
1104 response_deadline: None,
1105 write_deadline: None,
1106 write_shortened: false,
1107 refuse_unknown_expectations: false,
1108 }
1109 }
1110
1111 /// Sets a deadline for writing each response, from its first byte to
1112 /// its last, a streamed body included (see
1113 /// [`ServerConfig::with_response_deadline`]). When it passes, the write
1114 /// fails with an [`Error::Io`] of kind `TimedOut`; close the connection
1115 /// then (the response cannot be finished). `None` (the default for a
1116 /// bare `Connection`) leaves only the socket's own write timeout.
1117 ///
1118 /// # Examples
1119 ///
1120 /// ```
1121 /// use std::time::Duration;
1122 /// # fn demo(stream: std::net::TcpStream) {
1123 /// let conn = http_net::blocking::Connection::new(stream)
1124 /// .with_response_deadline(Duration::from_secs(60));
1125 /// # let _ = conn;
1126 /// # }
1127 /// ```
1128 #[must_use]
1129 pub fn with_response_deadline(mut self, deadline: impl Into<Option<Duration>>) -> Self {
1130 self.response_deadline = deadline.into();
1131 self
1132 }
1133
1134 /// Sets the message limits. Call it before the first
1135 /// [`next_request`](Self::next_request): it starts the connection's
1136 /// state again.
1137 ///
1138 /// # Examples
1139 ///
1140 /// ```
1141 /// # fn demo(stream: std::net::TcpStream) {
1142 /// use http_net::{Limits, blocking::Connection};
1143 ///
1144 /// let conn = Connection::new(stream).with_limits(Limits::new().with_max_body(64 * 1024));
1145 /// # let _ = conn;
1146 /// # }
1147 /// ```
1148 #[must_use]
1149 pub fn with_limits(mut self, limits: Limits) -> Self {
1150 self.conn = ServerConn::with_limits(limits);
1151 self
1152 }
1153
1154 /// Sets a deadline for each request: from the moment its first byte is
1155 /// seen to the end of its body (see
1156 /// [`ServerConfig::with_request_timeout`]). When it passes,
1157 /// [`next_request`](Self::next_request) fails with an [`Error::Io`] of
1158 /// kind `TimedOut`. `None` (the default for a bare `Connection`) leaves
1159 /// only the socket's own read timeout.
1160 ///
1161 /// # Examples
1162 ///
1163 /// ```
1164 /// use std::time::Duration;
1165 /// # fn demo(stream: std::net::TcpStream) {
1166 /// let conn = http_net::blocking::Connection::new(stream)
1167 /// .with_request_timeout(Duration::from_secs(10));
1168 /// # let _ = conn;
1169 /// # }
1170 /// ```
1171 #[must_use]
1172 pub fn with_request_timeout(mut self, timeout: impl Into<Option<Duration>>) -> Self {
1173 self.request_timeout = timeout.into();
1174 self
1175 }
1176
1177 /// Whether part of a request has arrived and the rest is outstanding.
1178 fn request_in_progress(&self) -> bool {
1179 self.conn.request().is_some() || !self.conn.remaining_input().is_empty()
1180 }
1181
1182 /// Answers a request that did not arrive in time with `408`, unless a
1183 /// response is already on its way.
1184 fn send_request_timeout(&mut self) -> Result<(), Error> {
1185 if self.conn.response_started() {
1186 return Err(Error::Http(HttpError::InvalidState(
1187 "a response was already started",
1188 )));
1189 }
1190 const BODY: &[u8] = b"request timed out";
1191 self.out.clear();
1192 self.out.extend_from_slice(
1193 b"HTTP/1.1 408 Request Timeout\r\ncontent-type: text/plain; charset=utf-8\r\n\
1194 content-length: ",
1195 );
1196 self.out
1197 .extend_from_slice(BODY.len().to_string().as_bytes());
1198 self.out
1199 .extend_from_slice(b"\r\nconnection: close\r\ndate: ");
1200 self.out.extend_from_slice(now_date().as_bytes());
1201 self.out.extend_from_slice(b"\r\n\r\n");
1202 // An answer to HEAD carries no content (RFC 9110 section 9.3.2).
1203 if !self.conn.request_line_is_head() {
1204 self.out.extend_from_slice(BODY);
1205 }
1206 self.flush_out()
1207 }
1208
1209 /// Reads into the parser's buffer, under the request deadline if one
1210 /// is running.
1211 fn fill(&mut self) -> Result<(), Error> {
1212 if let Some(limit) = self.request_timeout {
1213 if self.deadline.is_none() && self.request_in_progress() {
1214 self.deadline = Some(Instant::now() + limit);
1215 }
1216 }
1217 // Whether this read's timeout is the time left before the deadline,
1218 // so a timeout means the deadline passed.
1219 let mut at_deadline = false;
1220 match self.deadline {
1221 Some(deadline) => {
1222 let left = deadline.saturating_duration_since(Instant::now());
1223 if left.is_zero() {
1224 return Err(request_timed_out());
1225 }
1226 let wait = self.read_timeout.map_or(left, |t| t.min(left));
1227 at_deadline = wait == left;
1228 self.stream.set_read_timeout(Some(wait))?;
1229 self.shortened = true;
1230 }
1231 None if self.shortened => {
1232 self.stream.set_read_timeout(self.read_timeout)?;
1233 self.shortened = false;
1234 }
1235 None => {}
1236 }
1237 let spare = self.conn.read_buf();
1238 if spare.is_empty() {
1239 return Err(Error::Http(HttpError::InvalidState(
1240 "input buffer full while the parser needs input",
1241 )));
1242 }
1243 let n = loop {
1244 match self.stream.read(spare) {
1245 Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
1246 // Unix reports the expired socket timeout as `WouldBlock`;
1247 // the deadline is reported as `TimedOut` on every platform.
1248 Err(e) if at_deadline && is_timeout(&e) => return Err(request_timed_out()),
1249 other => break other?,
1250 }
1251 };
1252 if n == 0 {
1253 self.conn.feed_eof();
1254 } else {
1255 self.conn.commit(n);
1256 }
1257 Ok(())
1258 }
1259
1260 /// Reads the next complete request. `Ok(None)` means the connection is
1261 /// finished (the client closed between requests, the previous exchange
1262 /// ended with `connection: close`, or the connection was upgraded).
1263 ///
1264 /// A request that carries `Expect: 100-continue` is answered with
1265 /// `100 Continue` before its body is read. Other expectations are left
1266 /// to the caller (see [`RequestHead::has_unknown_expectation`]);
1267 /// [`Server`] answers them with 417.
1268 ///
1269 /// # Errors
1270 ///
1271 /// [`Error::Http`] for a request this crate refuses (answer it with its
1272 /// [`HttpError::status`] and close), [`Error::Io`] for socket failures
1273 /// and timeouts (including the request deadline, as `TimedOut`), and
1274 /// [`Error::Http`] with [`HttpError::InvalidState`] if the previous
1275 /// request has not been answered.
1276 ///
1277 /// # Examples
1278 ///
1279 /// See [`Connection`].
1280 pub fn next_request(&mut self) -> Result<Option<Incoming<'_>>, Error> {
1281 self.body.clear();
1282 self.deadline = None;
1283 loop {
1284 match self.conn.poll()? {
1285 ServerEvent::Request(head) => {
1286 // The whole body is read before the caller sees the
1287 // request, so the expectation is answered here (RFC 9110
1288 // section 10.1.1). A body over the limit was already
1289 // refused from its Content-Length.
1290 let unknown = head.has_unknown_expectation();
1291 let expects_continue = head.expects_continue();
1292 if self.refuse_unknown_expectations && unknown {
1293 // An expectation this server cannot meet: 417, the
1294 // body left unread, so the connection closes after.
1295 let refusal =
1296 Response::text(417, "expectation not supported; send without Expect")
1297 .close();
1298 self.respond(&refusal)?;
1299 return Ok(None);
1300 }
1301 if expects_continue {
1302 self.out.clear();
1303 self.conn.send_continue(&mut self.out)?;
1304 self.flush_out()?;
1305 }
1306 }
1307 ServerEvent::Body(chunk) => self.body.extend_from_slice(chunk),
1308 ServerEvent::RequestEnd => break,
1309 ServerEvent::NeedInput => self.fill()?,
1310 ServerEvent::AwaitingResponse => {
1311 return Err(Error::Http(HttpError::InvalidState(
1312 "respond to the previous request first",
1313 )));
1314 }
1315 _ => return Ok(None),
1316 }
1317 }
1318 match self.conn.request() {
1319 Some(head) => Ok(Some(Incoming {
1320 head,
1321 body: &self.body,
1322 })),
1323 None => Ok(None),
1324 }
1325 }
1326
1327 /// Writes `response` to the socket. A streamed response continues with
1328 /// [`send_body`](Self::send_body) and [`end_body`](Self::end_body).
1329 ///
1330 /// # Errors
1331 ///
1332 /// [`Error::Http`] when the response is invalid or out of order (see
1333 /// [`ServerConn::respond`]); [`Error::Io`] when the write fails.
1334 ///
1335 /// # Examples
1336 ///
1337 /// See [`Connection`].
1338 pub fn respond(&mut self, response: &Response) -> Result<(), Error> {
1339 self.out.clear();
1340 let date = now_date();
1341 // A large full body goes out after the head in one vectored write
1342 // instead of being copied into the output buffer.
1343 let tail = match response.body_bytes() {
1344 Some(body) if body.len() > VECTORED_BODY => {
1345 let plan = self.conn.respond_head_dated(
1346 response,
1347 Some(&date.as_bytes()[..]),
1348 &mut self.out,
1349 )?;
1350 if plan == BodyPlan::Raw { body } else { &[][..] }
1351 }
1352 _ => {
1353 self.conn
1354 .respond_with_date(response, &date, &mut self.out)?;
1355 &[][..]
1356 }
1357 };
1358 self.write_deadline = self.response_deadline.map(|d| Instant::now() + d);
1359 self.flush_with(tail)
1360 }
1361
1362 /// Writes an interim response (for example `103 Early Hints`) before
1363 /// the final one, through [`ServerConn::send_informational`].
1364 ///
1365 /// # Errors
1366 ///
1367 /// As [`ServerConn::send_informational`], plus [`Error::Io`].
1368 ///
1369 /// # Examples
1370 ///
1371 /// ```
1372 /// # fn demo(conn: &mut http_net::blocking::Connection) -> Result<(), http_net::blocking::Error> {
1373 /// use http_net::Response;
1374 ///
1375 /// conn.send_informational(&Response::new(103).header("link", "</app.css>; rel=preload; as=style"))?;
1376 /// conn.respond(&Response::text(200, "page"))?;
1377 /// # Ok(()) }
1378 /// ```
1379 pub fn send_informational(&mut self, response: &Response) -> Result<(), Error> {
1380 self.out.clear();
1381 self.conn.send_informational(response, &mut self.out)?;
1382 self.flush_out()
1383 }
1384
1385 /// Writes body bytes of a streamed response.
1386 ///
1387 /// # Errors
1388 ///
1389 /// As [`ServerConn::send_body`], plus [`Error::Io`].
1390 ///
1391 /// # Examples
1392 ///
1393 /// ```
1394 /// # fn demo(conn: &mut http_net::blocking::Connection) -> Result<(), http_net::blocking::Error> {
1395 /// conn.respond(&http_net::Response::new(200).chunked())?;
1396 /// conn.send_body(b"first")?;
1397 /// conn.end_body()?;
1398 /// # Ok(()) }
1399 /// ```
1400 pub fn send_body(&mut self, data: &[u8]) -> Result<(), Error> {
1401 self.out.clear();
1402 self.conn.send_body(data, &mut self.out)?;
1403 self.flush_out()
1404 }
1405
1406 /// Ends a streamed response.
1407 ///
1408 /// # Errors
1409 ///
1410 /// As [`ServerConn::end_body`], plus [`Error::Io`].
1411 ///
1412 /// # Examples
1413 ///
1414 /// See [`send_body`](Self::send_body).
1415 pub fn end_body(&mut self) -> Result<(), Error> {
1416 self.out.clear();
1417 self.conn.end_body(&mut self.out)?;
1418 self.flush_out()
1419 }
1420
1421 /// Writes `out`. While a response deadline runs, each write waits at
1422 /// most the time left (and never longer than the socket's own write
1423 /// timeout); the deadline ends with the response.
1424 fn flush_out(&mut self) -> Result<(), Error> {
1425 self.flush_with(&[])
1426 }
1427
1428 /// Writes the serialized bytes in `out` and then `tail` (a full body
1429 /// sent as it is, not copied into `out`), with vectored writes while
1430 /// both remain.
1431 fn flush_with(&mut self, tail: &[u8]) -> Result<(), Error> {
1432 let head_len = self.out.len();
1433 let total = head_len + tail.len();
1434 let mut written = 0;
1435 while written < total {
1436 if let Some(deadline) = self.write_deadline {
1437 let left = deadline.saturating_duration_since(Instant::now());
1438 if left.is_zero() {
1439 return Err(response_timed_out());
1440 }
1441 let wait = self.write_timeout.map_or(left, |t| t.min(left));
1442 self.stream.set_write_timeout(Some(wait))?;
1443 self.write_shortened = true;
1444 }
1445 let result = if written >= head_len {
1446 self.stream.write(&tail[written - head_len..])
1447 } else if tail.is_empty() {
1448 self.stream.write(&self.out[written..])
1449 } else {
1450 let parts = [IoSlice::new(&self.out[written..]), IoSlice::new(tail)];
1451 self.stream.write_vectored(&parts)
1452 };
1453 match result {
1454 Ok(0) => return Err(Error::Io(io::ErrorKind::WriteZero.into())),
1455 Ok(n) => written += n,
1456 Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
1457 Err(e)
1458 if is_timeout(&e)
1459 && self.write_deadline.is_some_and(|d| Instant::now() >= d) =>
1460 {
1461 return Err(response_timed_out());
1462 }
1463 Err(e) => return Err(Error::Io(e)),
1464 }
1465 }
1466 if self.conn.progress() != Progress::WritingBody {
1467 self.write_deadline = None;
1468 if self.write_shortened {
1469 self.stream.set_write_timeout(self.write_timeout)?;
1470 self.write_shortened = false;
1471 }
1472 }
1473 if self.out.capacity() > OUT_RETAIN {
1474 self.out = Vec::new();
1475 }
1476 Ok(())
1477 }
1478
1479 /// Whether a `101` (or a 2xx to `CONNECT`) was sent.
1480 ///
1481 /// # Examples
1482 ///
1483 /// See [`into_upgraded`](Self::into_upgraded).
1484 #[must_use]
1485 pub fn is_upgraded(&self) -> bool {
1486 self.conn.is_upgraded()
1487 }
1488
1489 /// The socket and the bytes of the new protocol, after an upgrade;
1490 /// `None` if the connection was not upgraded. The socket's read timeout
1491 /// is the one it had when the `Connection` was created (a request
1492 /// deadline may have shortened it while the request was read).
1493 ///
1494 /// # Examples
1495 ///
1496 /// ```
1497 /// # fn demo(mut conn: http_net::blocking::Connection) {
1498 /// if conn.is_upgraded() {
1499 /// let up = conn.into_upgraded().unwrap();
1500 /// // speak the new protocol on up.stream, starting with up.leftover
1501 /// # let _ = up;
1502 /// }
1503 /// # }
1504 /// ```
1505 #[must_use]
1506 pub fn into_upgraded(self) -> Option<Upgraded> {
1507 if !self.is_upgraded() {
1508 return None;
1509 }
1510 let target = self
1511 .conn
1512 .request()
1513 .map(|r| r.target().to_string())
1514 .unwrap_or_default();
1515 if self.shortened {
1516 // Best effort: the new protocol must not inherit what was left
1517 // of the request deadline. Setting a timeout this socket has
1518 // already accepted does not fail in practice, and the hand-off
1519 // is more useful than refusing it over one.
1520 let _ = self.stream.set_read_timeout(self.read_timeout);
1521 }
1522 Some(Upgraded {
1523 leftover: self.conn.remaining_input().to_vec(),
1524 target,
1525 stream: self.stream,
1526 })
1527 }
1528
1529 /// Closes the connection gracefully: stops sending, briefly drains what
1530 /// the client is still sending, and drops the socket.
1531 ///
1532 /// # Examples
1533 ///
1534 /// See [`Connection`].
1535 pub fn close(self) {
1536 drain_and_close(self.stream);
1537 }
1538}
1539
1540/// A response fetched by [`get`], [`post`], [`Client::get`], or
1541/// [`Client::request`], fully read.
1542///
1543/// # Examples
1544///
1545/// See [`Server`].
1546#[derive(Clone, PartialEq, Eq)]
1547pub struct ClientResponse {
1548 status: u16,
1549 headers: Vec<(String, Vec<u8>)>,
1550 body: Vec<u8>,
1551}
1552
1553/// Shows status, fields, and body size; the values of credential fields
1554/// (`set-cookie` above all) are replaced by `<redacted N bytes>`.
1555impl fmt::Debug for ClientResponse {
1556 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1557 struct Fields<'a>(&'a [(String, Vec<u8>)]);
1558 impl fmt::Debug for Fields<'_> {
1559 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1560 f.debug_list()
1561 .entries(self.0.iter().map(|(name, value)| {
1562 (
1563 name.as_str(),
1564 FieldValue {
1565 name: name.as_bytes(),
1566 value,
1567 },
1568 )
1569 }))
1570 .finish()
1571 }
1572 }
1573 f.debug_struct("ClientResponse")
1574 .field("status", &self.status)
1575 .field("headers", &Fields(&self.headers))
1576 .field("body", &format_args!("{} bytes", self.body.len()))
1577 .finish()
1578 }
1579}
1580
1581impl ClientResponse {
1582 /// The status code.
1583 ///
1584 /// # Examples
1585 ///
1586 /// See [`Server`].
1587 #[must_use]
1588 pub fn status(&self) -> u16 {
1589 self.status
1590 }
1591
1592 /// The fields in arrival order.
1593 ///
1594 /// # Examples
1595 ///
1596 /// Not run: it needs a server on port 8080.
1597 ///
1598 /// ```no_run
1599 /// let resp = http_net::blocking::get("http://127.0.0.1:8080/")?;
1600 /// for (name, value) in resp.headers() {
1601 /// let _ = (name, value);
1602 /// }
1603 /// # Ok::<(), http_net::blocking::Error>(())
1604 /// ```
1605 pub fn headers(&self) -> impl Iterator<Item = (&str, &[u8])> {
1606 self.headers.iter().map(|(n, v)| (n.as_str(), v.as_slice()))
1607 }
1608
1609 /// The first field named `name` (ASCII case-insensitive).
1610 ///
1611 /// # Examples
1612 ///
1613 /// Not run: it needs a server on port 8080.
1614 ///
1615 /// ```no_run
1616 /// let resp = http_net::blocking::get("http://127.0.0.1:8080/")?;
1617 /// let _ = resp.header("content-type");
1618 /// # Ok::<(), http_net::blocking::Error>(())
1619 /// ```
1620 #[must_use]
1621 pub fn header(&self, name: &str) -> Option<&[u8]> {
1622 self.headers
1623 .iter()
1624 .find(|(n, _)| n.eq_ignore_ascii_case(name))
1625 .map(|(_, v)| v.as_slice())
1626 }
1627
1628 /// The body.
1629 ///
1630 /// # Examples
1631 ///
1632 /// See [`Server`].
1633 #[must_use]
1634 pub fn body(&self) -> &[u8] {
1635 &self.body
1636 }
1637
1638 /// The body, if it is UTF-8.
1639 ///
1640 /// # Examples
1641 ///
1642 /// See [`Server`].
1643 #[must_use]
1644 pub fn text(&self) -> Option<&str> {
1645 core::str::from_utf8(&self.body).ok()
1646 }
1647
1648 /// Takes the body.
1649 ///
1650 /// # Examples
1651 ///
1652 /// Not run: it needs a server on port 8080.
1653 ///
1654 /// ```no_run
1655 /// let bytes = http_net::blocking::get("http://127.0.0.1:8080/")?.into_body();
1656 /// # let _ = bytes;
1657 /// # Ok::<(), http_net::blocking::Error>(())
1658 /// ```
1659 #[must_use]
1660 pub fn into_body(self) -> Vec<u8> {
1661 self.body
1662 }
1663}
1664
1665/// Fetches `url` with `GET` using the default [`Client`].
1666///
1667/// # Errors
1668///
1669/// [`Error::InvalidUrl`] for anything but `http://host[:port][/path[?query]]`
1670/// (a `#fragment` is dropped),
1671/// [`Error::Io`] for connection failures and timeouts, [`Error::Http`] for
1672/// a response this crate refuses (including one over the body limit).
1673///
1674/// # Examples
1675///
1676/// See [`Server`].
1677pub fn get(url: &str) -> Result<ClientResponse, Error> {
1678 Client::new().get(url)
1679}
1680
1681/// Sends `body` to `url` with `POST` and `content-type: content_type`,
1682/// using the default [`Client`].
1683///
1684/// # Errors
1685///
1686/// As [`get`], plus [`Error::Http`] for a content type that is not a valid
1687/// field value.
1688///
1689/// # Examples
1690///
1691/// ```
1692/// use http_net::{blocking, Response};
1693///
1694/// let server = blocking::Server::bind("127.0.0.1:0")?;
1695/// let addr = server.local_addr();
1696/// let stop = server.shutdown_handle();
1697/// let t = std::thread::spawn(move || server.serve(|_, body| Response::text(200, &body.len().to_string())));
1698///
1699/// let resp = blocking::post(&format!("http://{addr}/notes"), "text/plain", b"hello")?;
1700/// assert_eq!(resp.text(), Some("5"));
1701///
1702/// stop.shutdown();
1703/// t.join().unwrap()?;
1704/// # Ok::<(), Box<dyn std::error::Error>>(())
1705/// ```
1706pub fn post(url: &str, content_type: &str, body: &[u8]) -> Result<ClientResponse, Error> {
1707 let request = Request::post("/")
1708 .header("content-type", content_type)
1709 .body(body.to_vec());
1710 Client::new().request(url, request)
1711}
1712
1713/// Binds `addr` and serves `handler` with the default [`ServerConfig`]
1714/// until the process ends: the shortest way to run a server. Use
1715/// [`Server`] for a shutdown handle, settings, or an upgrade hook.
1716///
1717/// # Errors
1718///
1719/// The bind error, or a persistent accept failure (see [`Server::serve`]).
1720///
1721/// # Examples
1722///
1723/// Not run: it serves until the process ends.
1724///
1725/// ```no_run
1726/// use http_net::{blocking, Response};
1727///
1728/// blocking::serve("127.0.0.1:8080", |req, _body| Response::text(200, req.path()))?;
1729/// # Ok::<(), std::io::Error>(())
1730/// ```
1731pub fn serve<H>(addr: impl ToSocketAddrs, handler: H) -> io::Result<()>
1732where
1733 H: Fn(&RequestHead<'_>, &[u8]) -> Response + Send + Sync + 'static,
1734{
1735 Server::bind(addr)?.serve(handler)
1736}
1737
1738/// A blocking HTTP/1.1 client: one connection per request.
1739///
1740/// | Setting | Default |
1741/// |---|---|
1742/// | limits | [`Limits::new`] with a 16 MiB body |
1743/// | connect, read, and write timeout | 30 s each |
1744/// | total deadline for one exchange (connect, write, read) | none |
1745///
1746/// # Examples
1747///
1748/// Not run: it needs a server on port 8080.
1749///
1750/// ```no_run
1751/// use std::time::Duration;
1752/// use http_net::{blocking::Client, Limits};
1753///
1754/// let client = Client::new()
1755/// .with_limits(Limits::new().with_max_body(64 << 20))
1756/// .with_timeout(Duration::from_secs(5));
1757/// let resp = client.get("http://127.0.0.1:8080/big")?;
1758/// # let _ = resp;
1759/// # Ok::<(), http_net::blocking::Error>(())
1760/// ```
1761#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1762pub struct Client {
1763 limits: Limits,
1764 timeout: Duration,
1765 deadline: Option<Duration>,
1766}
1767
1768impl Default for Client {
1769 fn default() -> Self {
1770 Self::new()
1771 }
1772}
1773
1774impl Client {
1775 /// The defaults (see the table on [`Client`]).
1776 ///
1777 /// # Examples
1778 ///
1779 /// ```
1780 /// let _ = http_net::blocking::Client::new();
1781 /// ```
1782 #[must_use]
1783 pub const fn new() -> Self {
1784 Self {
1785 limits: Limits::new().with_max_body(16 * 1024 * 1024),
1786 timeout: Duration::from_secs(30),
1787 deadline: None,
1788 }
1789 }
1790
1791 /// Sets the response limits.
1792 ///
1793 /// # Examples
1794 ///
1795 /// ```
1796 /// let _ = http_net::blocking::Client::new().with_limits(http_net::Limits::new());
1797 /// ```
1798 #[must_use]
1799 pub const fn with_limits(mut self, limits: Limits) -> Self {
1800 self.limits = limits;
1801 self
1802 }
1803
1804 /// Sets the connect, read, and write timeout (zero is raised to 1 ms).
1805 ///
1806 /// # Examples
1807 ///
1808 /// ```
1809 /// let _ = http_net::blocking::Client::new().with_timeout(std::time::Duration::from_secs(2));
1810 /// ```
1811 #[must_use]
1812 pub const fn with_timeout(mut self, timeout: Duration) -> Self {
1813 self.timeout = if timeout.is_zero() {
1814 Duration::from_millis(1)
1815 } else {
1816 timeout
1817 };
1818 self
1819 }
1820
1821 /// Sets a total deadline for one exchange: connecting, writing the
1822 /// request, and reading the whole response. The per-operation timeout
1823 /// of [`with_timeout`](Self::with_timeout) cannot stop a server that
1824 /// sends one byte just inside it; this deadline can. Name resolution is
1825 /// not bounded: `std` offers no timeout for it. Pass a `Duration`, or
1826 /// `None` (the default) for no deadline.
1827 ///
1828 /// # Examples
1829 ///
1830 /// ```
1831 /// use std::time::Duration;
1832 /// let _ = http_net::blocking::Client::new().with_deadline(Duration::from_secs(10));
1833 /// ```
1834 #[must_use]
1835 pub fn with_deadline(mut self, deadline: impl Into<Option<Duration>>) -> Self {
1836 self.deadline = deadline.into();
1837 self
1838 }
1839
1840 /// Fetches `url` with `GET`.
1841 ///
1842 /// # Errors
1843 ///
1844 /// As [`get`].
1845 ///
1846 /// # Examples
1847 ///
1848 /// See [`Client`].
1849 pub fn get(&self, url: &str) -> Result<ClientResponse, Error> {
1850 self.request(url, Request::get("/"))
1851 }
1852
1853 /// Sends `request` to the `http://` URL `url` and reads the response.
1854 /// The URL gives the authority (written as `host`) and the target, which
1855 /// replaces the target `request` was built with; the method, fields,
1856 /// and body come from `request`. The request is sent with
1857 /// `connection: close` on a connection of its own.
1858 ///
1859 /// # Errors
1860 ///
1861 /// As [`get`]; [`Error::Http`] with the builder's first error;
1862 /// [`HttpError::InvalidHost`] when `request` already has a `host` (the
1863 /// URL supplies it); [`HttpError::InvalidState`] for a streamed body
1864 /// (`chunked` or `content_length`: this client sends full bodies) or an
1865 /// upgrade request (it cannot hand the connection over; use
1866 /// [`ClientConn`]). A [`Request::expect_continue`] request with its full
1867 /// body fails with [`Error::Http`] of [`HttpError::InvalidState`] (the
1868 /// expectation needs a streamed body).
1869 ///
1870 /// # Examples
1871 ///
1872 /// ```
1873 /// use http_net::{blocking::{self, Client}, Request, Response};
1874 ///
1875 /// let server = blocking::Server::bind("127.0.0.1:0")?;
1876 /// let addr = server.local_addr();
1877 /// let stop = server.shutdown_handle();
1878 /// let t = std::thread::spawn(move || {
1879 /// server.serve(|req, body| Response::text(200, &format!("{} {} {}", req.method_str(), req.path(), body.len())))
1880 /// });
1881 ///
1882 /// let put = Request::put("/").header("content-type", "application/json").body(&b"{}"[..]);
1883 /// let resp = Client::new().request(&format!("http://{addr}/items/7"), put)?;
1884 /// assert_eq!(resp.text(), Some("PUT /items/7 2"));
1885 ///
1886 /// stop.shutdown();
1887 /// t.join().unwrap()?;
1888 /// # Ok::<(), Box<dyn std::error::Error>>(())
1889 /// ```
1890 pub fn request(&self, url: &str, request: Request) -> Result<ClientResponse, Error> {
1891 let url = Url::parse(url)?;
1892 let request = retarget(&request, url.target, url.authority)?;
1893 let deadline = self.deadline.map(|d| Instant::now() + d);
1894 let addrs = (url.host, url.port).to_socket_addrs()?;
1895 let mut stream = connect_any(addrs, self.timeout, deadline)?;
1896 let mut conn = ClientConn::with_limits(self.limits);
1897 let mut out = Vec::new();
1898 conn.send_request(&request, &mut out)?;
1899 let mut io = Timed {
1900 stream: &mut stream,
1901 timeout: self.timeout,
1902 deadline,
1903 };
1904 io.write_all(&out)?;
1905 read_response(&mut io, &mut conn)
1906 }
1907}
1908
1909/// Rebuilds `request` for a URL: the URL's target, `host` from its
1910/// authority first, then the request's own fields, body, and flags, and
1911/// always `connection: close` (one connection per exchange).
1912fn retarget(request: &Request, target: &str, authority: &str) -> Result<Request, Error> {
1913 if let Some(e) = request.error() {
1914 return Err(Error::Http(e));
1915 }
1916 if request.has_host {
1917 return Err(Error::Http(HttpError::InvalidHost));
1918 }
1919 if request.upgrade {
1920 return Err(Error::Http(HttpError::InvalidState(
1921 "the blocking client cannot hand over an upgraded connection; use ClientConn",
1922 )));
1923 }
1924 let mut rebuilt = Request::new(request.method(), target).header("host", authority);
1925 for (name, value) in serialized_fields(request.fields()) {
1926 let name = core::str::from_utf8(name).unwrap_or("");
1927 if request.expect_continue
1928 && name.eq_ignore_ascii_case("expect")
1929 && value.eq_ignore_ascii_case(b"100-continue")
1930 {
1931 // Added again below by its builder method.
1932 continue;
1933 }
1934 rebuilt = rebuilt.header(name, value);
1935 }
1936 if request.expect_continue {
1937 rebuilt = rebuilt.expect_continue();
1938 }
1939 rebuilt = match &request.body {
1940 OutBody::Full(body) => rebuilt.body(body.clone()),
1941 OutBody::Length(_) | OutBody::Chunked => {
1942 return Err(Error::Http(HttpError::InvalidState(
1943 "the blocking client sends full bodies only; use ClientConn to stream",
1944 )));
1945 }
1946 };
1947 let rebuilt = rebuilt.close();
1948 match rebuilt.error() {
1949 Some(e) => Err(Error::Http(e)),
1950 None => Ok(rebuilt),
1951 }
1952}
1953
1954/// Connects to the first address that accepts, each attempt bounded by
1955/// `timeout` and by what is left before `deadline`.
1956fn connect_any(
1957 addrs: impl IntoIterator<Item = SocketAddr>,
1958 timeout: Duration,
1959 deadline: Option<Instant>,
1960) -> Result<TcpStream, Error> {
1961 let stream = first_connected(addrs, timeout, deadline, TcpStream::connect_timeout)?;
1962 stream.set_read_timeout(Some(timeout))?;
1963 stream.set_write_timeout(Some(timeout))?;
1964 stream.set_nodelay(true)?;
1965 Ok(stream)
1966}
1967
1968/// Tries each address in turn with `connect`, each attempt waiting at most
1969/// `timeout` and what is left of `deadline`; the first success wins, and
1970/// the last failure is the error. The connect function is a parameter so
1971/// the fallback logic is tested without sockets.
1972fn first_connected<S>(
1973 addrs: impl IntoIterator<Item = SocketAddr>,
1974 timeout: Duration,
1975 deadline: Option<Instant>,
1976 mut connect: impl FnMut(&SocketAddr, Duration) -> io::Result<S>,
1977) -> Result<S, Error> {
1978 let mut last = None;
1979 for addr in addrs {
1980 let wait = match deadline {
1981 Some(d) => {
1982 let left = d.saturating_duration_since(Instant::now());
1983 if left.is_zero() {
1984 return Err(exchange_timed_out());
1985 }
1986 left.min(timeout)
1987 }
1988 None => timeout,
1989 };
1990 match connect(&addr, wait) {
1991 Ok(stream) => return Ok(stream),
1992 Err(e) => last = Some(e),
1993 }
1994 }
1995 Err(Error::Io(last.unwrap_or_else(|| {
1996 io::Error::new(io::ErrorKind::NotFound, "the host resolved to no address")
1997 })))
1998}
1999
2000fn exchange_timed_out() -> Error {
2001 Error::Io(io::Error::new(
2002 io::ErrorKind::TimedOut,
2003 "the exchange did not finish within the client deadline",
2004 ))
2005}
2006
2007/// A client socket whose reads and writes stop at a total deadline: each
2008/// operation waits at most the time left, and never longer than the
2009/// per-operation timeout.
2010struct Timed<'a> {
2011 stream: &'a mut TcpStream,
2012 timeout: Duration,
2013 deadline: Option<Instant>,
2014}
2015
2016impl Timed<'_> {
2017 /// Sets the socket timeouts for the next operation.
2018 fn arm(&mut self) -> Result<(), Error> {
2019 if let Some(d) = self.deadline {
2020 let left = d.saturating_duration_since(Instant::now());
2021 if left.is_zero() {
2022 return Err(exchange_timed_out());
2023 }
2024 let wait = left.min(self.timeout);
2025 self.stream.set_read_timeout(Some(wait))?;
2026 self.stream.set_write_timeout(Some(wait))?;
2027 }
2028 Ok(())
2029 }
2030
2031 /// Maps a timeout that ran into the deadline to the deadline's error.
2032 fn check(&self, e: io::Error) -> Error {
2033 if is_timeout(&e) && self.deadline.is_some_and(|d| Instant::now() >= d) {
2034 exchange_timed_out()
2035 } else {
2036 Error::Io(e)
2037 }
2038 }
2039
2040 fn write_all(&mut self, mut data: &[u8]) -> Result<(), Error> {
2041 while !data.is_empty() {
2042 self.arm()?;
2043 match self.stream.write(data) {
2044 Ok(0) => return Err(Error::Io(io::ErrorKind::WriteZero.into())),
2045 Ok(n) => data = &data[n..],
2046 Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
2047 Err(e) => return Err(self.check(e)),
2048 }
2049 }
2050 Ok(())
2051 }
2052
2053 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
2054 loop {
2055 self.arm()?;
2056 match self.stream.read(buf) {
2057 Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
2058 Err(e) => return Err(self.check(e)),
2059 Ok(n) => return Ok(n),
2060 }
2061 }
2062 }
2063}
2064
2065fn read_response(stream: &mut Timed<'_>, conn: &mut ClientConn) -> Result<ClientResponse, Error> {
2066 let mut response = ClientResponse {
2067 status: 0,
2068 headers: Vec::new(),
2069 body: Vec::new(),
2070 };
2071 loop {
2072 match conn.poll()? {
2073 ClientEvent::Response(head) => {
2074 response.status = head.status();
2075 response.headers = head
2076 .headers()
2077 .map(|(n, v)| (n.to_string(), v.to_vec()))
2078 .collect();
2079 }
2080 ClientEvent::Body(chunk) => response.body.extend_from_slice(chunk),
2081 ClientEvent::ResponseEnd => return Ok(response),
2082 ClientEvent::NeedInput => {
2083 let spare = conn.read_buf();
2084 if spare.is_empty() {
2085 return Err(Error::Http(HttpError::InvalidState(
2086 "input buffer full while the parser needs input",
2087 )));
2088 }
2089 let n = stream.read(spare)?;
2090 if n == 0 {
2091 conn.feed_eof();
2092 } else {
2093 conn.commit(n);
2094 }
2095 }
2096 _ => {
2097 return Err(Error::Http(HttpError::InvalidState(
2098 "the connection ended without a complete response",
2099 )));
2100 }
2101 }
2102 }
2103}
2104
2105/// The parts of an `http://` URL needed to send a request.
2106#[derive(Debug, PartialEq, Eq)]
2107struct Url<'a> {
2108 /// `host[:port]` as written, for the Host header.
2109 authority: &'a str,
2110 /// The host for name resolution (brackets removed from IPv6 literals).
2111 host: &'a str,
2112 port: u16,
2113 /// Path and query; `/` when the URL has no path.
2114 target: &'a str,
2115}
2116
2117impl<'a> Url<'a> {
2118 fn parse(url: &'a str) -> Result<Self, Error> {
2119 let scheme_end = url.find("://").ok_or(Error::InvalidUrl("missing scheme"))?;
2120 if !url[..scheme_end].eq_ignore_ascii_case("http") {
2121 return Err(Error::InvalidUrl(
2122 "only http:// is supported (no TLS in this crate)",
2123 ));
2124 }
2125 let rest = &url[scheme_end + 3..];
2126 // The fragment is never sent.
2127 let rest = rest.split_once('#').map_or(rest, |(r, _)| r);
2128 let auth_end = rest.find(['/', '?']).unwrap_or(rest.len());
2129 let authority = &rest[..auth_end];
2130 let target = match &rest[auth_end..] {
2131 "" => "/",
2132 t if t.starts_with('?') => {
2133 return Err(Error::InvalidUrl("a query needs a path, for example /?q"));
2134 }
2135 t => t,
2136 };
2137 if authority.is_empty() {
2138 return Err(Error::InvalidUrl("missing host"));
2139 }
2140 if authority.contains('@') {
2141 return Err(Error::InvalidUrl(
2142 "credentials in the URL are not supported",
2143 ));
2144 }
2145 let (host, port) = if let Some(v6) = authority.strip_prefix('[') {
2146 let (inside, after) = v6.split_once(']').ok_or(Error::InvalidUrl("unclosed ["))?;
2147 let port = match after {
2148 "" => None,
2149 p => Some(
2150 p.strip_prefix(':')
2151 .ok_or(Error::InvalidUrl("junk after ]"))?,
2152 ),
2153 };
2154 (inside, port)
2155 } else {
2156 match authority.rsplit_once(':') {
2157 Some((h, p)) => (h, Some(p)),
2158 None => (authority, None),
2159 }
2160 };
2161 let port = match port {
2162 None => 80,
2163 Some(p) => p.parse().map_err(|_| Error::InvalidUrl("bad port"))?,
2164 };
2165 if host.is_empty() {
2166 return Err(Error::InvalidUrl("missing host"));
2167 }
2168 Ok(Self {
2169 authority,
2170 host,
2171 port,
2172 target,
2173 })
2174 }
2175}
2176
2177thread_local! {
2178 /// One date cache per thread: each connection thread formats `date` at
2179 /// most once per second, and nothing is shared between threads.
2180 static DATE: Cell<DateCache> = const { Cell::new(DateCache::new()) };
2181}
2182
2183/// The current time as a `Date` value, from a per-thread
2184/// [`DateCache`]: the system clock is read on every call, the value is
2185/// reformatted only when the second changes. [`Connection::respond`] and
2186/// [`Server`] write it on every response that did not set its own `date`.
2187///
2188/// # Examples
2189///
2190/// ```
2191/// let date = http_net::blocking::now_date();
2192/// assert_eq!(date.as_bytes().len(), 29);
2193/// assert!(date.as_str().ends_with(" GMT"));
2194/// ```
2195#[must_use]
2196pub fn now_date() -> HttpDate {
2197 let secs = SystemTime::now()
2198 .duration_since(UNIX_EPOCH)
2199 .map_or(0, |d| d.as_secs());
2200 DATE.with(|cell| {
2201 let mut cache = cell.get();
2202 let date = *cache.update(secs);
2203 cell.set(cache);
2204 date
2205 })
2206}
2207
2208#[cfg(test)]
2209mod tests {
2210 use super::*;
2211
2212 /// T-41: a listener whose accept keeps failing never spins a core (every
2213 /// failure waits) and the loop gives up only after 1,000 failures in a
2214 /// row; a success in between starts the count again.
2215 #[test]
2216 fn test_accept_errors_back_off_and_end_after_the_limit() {
2217 let error = || io::Error::from(io::ErrorKind::ConnectionAborted);
2218 let mut backoff = AcceptBackoff::default();
2219 for _ in 0..AcceptBackoff::LIMIT {
2220 let wait = backoff.failure(error()).expect("still tolerated");
2221 assert!(wait >= Duration::from_millis(10), "a failure must wait");
2222 }
2223 let last = backoff.failure(error()).expect_err("the limit is reached");
2224 assert_eq!(last.kind(), io::ErrorKind::ConnectionAborted);
2225
2226 let mut backoff = AcceptBackoff::default();
2227 for _ in 0..3 {
2228 for _ in 0..AcceptBackoff::LIMIT {
2229 assert!(backoff.failure(error()).is_ok());
2230 }
2231 backoff.success();
2232 }
2233 assert!(
2234 backoff.failure(error()).is_ok(),
2235 "a success resets the count"
2236 );
2237 }
2238
2239 /// T-40, byte cap: a peer that keeps sending as fast as it can is
2240 /// drained by at most `DRAIN_LIMIT` bytes (plus the last read), then
2241 /// the drain stops though the peer has neither stopped nor closed. The
2242 /// socket tests in `tests/localhost.rs` show the slot is freed; this
2243 /// one shows which cap freed it.
2244 #[test]
2245 fn test_lingering_drain_stops_at_the_byte_cap() {
2246 let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
2247 let mut client = TcpStream::connect(listener.local_addr().unwrap()).unwrap();
2248 let (mut server, _) = listener.accept().unwrap();
2249 let flood = thread::spawn(move || {
2250 // Ends when the server closes its side; the error is expected.
2251 let _ = client.write_all(&vec![b'x'; 16 * DRAIN_LIMIT]);
2252 client
2253 });
2254 let started = Instant::now();
2255 let drained = lingering_drain(&mut server);
2256 let took = started.elapsed();
2257 drop(server);
2258 drop(flood.join().unwrap());
2259 assert!(
2260 (DRAIN_LIMIT..DRAIN_LIMIT + 4096).contains(&drained),
2261 "drained {drained} bytes"
2262 );
2263 assert!(took < DRAIN_TOTAL, "the byte cap ended it, after {took:?}");
2264 }
2265
2266 #[test]
2267 fn test_time_setters_take_a_duration_an_option_or_none() {
2268 let five = Duration::from_secs(5);
2269 let c = ServerConfig::new()
2270 .with_read_timeout(five)
2271 .with_request_timeout(Some(five))
2272 .with_write_timeout(None)
2273 .with_response_deadline(five)
2274 .with_max_requests_per_connection(0);
2275 assert_eq!(c.read_timeout(), Some(five));
2276 assert_eq!(c.request_timeout(), Some(five));
2277 assert_eq!(c.write_timeout(), None);
2278 assert_eq!(c.response_deadline(), Some(five));
2279 assert_eq!(c.max_requests_per_connection(), Some(1));
2280 let c = c.with_max_requests_per_connection(None);
2281 assert_eq!(c.max_requests_per_connection(), None);
2282 assert_eq!(Client::new().with_deadline(five).deadline, Some(five));
2283 assert_eq!(Client::new().with_deadline(None).deadline, None);
2284 }
2285
2286 #[test]
2287 fn test_now_date_is_the_current_second() {
2288 let before = SystemTime::now()
2289 .duration_since(UNIX_EPOCH)
2290 .map_or(0, |d| d.as_secs());
2291 let shown = now_date();
2292 let after = SystemTime::now()
2293 .duration_since(UNIX_EPOCH)
2294 .map_or(0, |d| d.as_secs());
2295 assert!(
2296 shown == HttpDate::from_unix_seconds(before)
2297 || shown == HttpDate::from_unix_seconds(after),
2298 "{shown}"
2299 );
2300 // The same second twice comes from the cache and is equal.
2301 assert_eq!(now_date().as_bytes().len(), 29);
2302 }
2303
2304 /// E-198: a name that resolves to several addresses is tried in order;
2305 /// an address that refuses the connection does not end the attempt. The
2306 /// fallback is tested with a scripted connect, so no port has to stay
2307 /// closed (a freed ephemeral port can be taken again by another test or
2308 /// process, which made a socket version of this test flaky).
2309 #[test]
2310 fn test_first_connected_refused_first_address_tries_the_next() {
2311 let a: SocketAddr = "127.0.0.1:1".parse().unwrap();
2312 let b: SocketAddr = "127.0.0.1:2".parse().unwrap();
2313 let mut tried = Vec::new();
2314 let got = first_connected([a, b], Duration::from_secs(5), None, |addr, _| {
2315 tried.push(*addr);
2316 if *addr == a {
2317 Err(io::Error::from(io::ErrorKind::ConnectionRefused))
2318 } else {
2319 Ok(*addr)
2320 }
2321 });
2322 assert_eq!(got.unwrap(), b);
2323 assert_eq!(tried, [a, b]);
2324
2325 let err = first_connected([a, b], Duration::from_secs(5), None, |addr, _| {
2326 Err::<(), _>(io::Error::new(
2327 io::ErrorKind::ConnectionRefused,
2328 addr.to_string(),
2329 ))
2330 })
2331 .unwrap_err();
2332 assert!(
2333 matches!(&err, Error::Io(e) if e.to_string() == b.to_string()),
2334 "the last failure is reported: {err}"
2335 );
2336 let err = first_connected(
2337 Vec::<SocketAddr>::new(),
2338 Duration::from_secs(5),
2339 None,
2340 |_, _| Ok(()),
2341 )
2342 .unwrap_err();
2343 assert!(
2344 matches!(&err, Error::Io(e) if e.kind() == io::ErrorKind::NotFound),
2345 "{err}"
2346 );
2347 }
2348
2349 /// Each attempt waits at most the timeout and what is left of the
2350 /// deadline.
2351 #[test]
2352 fn test_first_connected_each_wait_is_capped_by_the_deadline() {
2353 let a: SocketAddr = "127.0.0.1:1".parse().unwrap();
2354 let mut waits = Vec::new();
2355 let deadline = Instant::now() + Duration::from_secs(60);
2356 let _ = first_connected([a, a], Duration::from_secs(5), Some(deadline), |_, wait| {
2357 waits.push(wait);
2358 Err::<(), _>(io::Error::from(io::ErrorKind::ConnectionRefused))
2359 });
2360 assert_eq!(waits, [Duration::from_secs(5), Duration::from_secs(5)]);
2361 waits.clear();
2362 let soon = Instant::now() + Duration::from_secs(2);
2363 let _ = first_connected([a], Duration::from_secs(5), Some(soon), |_, wait| {
2364 waits.push(wait);
2365 Err::<(), _>(io::Error::from(io::ErrorKind::ConnectionRefused))
2366 });
2367 assert!(waits[0] <= Duration::from_secs(2), "{waits:?}");
2368 }
2369
2370 /// The socket path: a live listener is reached and the stream gets its
2371 /// timeouts.
2372 #[test]
2373 fn test_connect_any_reaches_a_listener() {
2374 let open = TcpListener::bind("127.0.0.1:0").unwrap();
2375 let good = open.local_addr().unwrap();
2376 let stream = connect_any([good], Duration::from_secs(5), None).unwrap();
2377 assert_eq!(stream.peer_addr().unwrap(), good);
2378 assert_eq!(stream.read_timeout().unwrap(), Some(Duration::from_secs(5)));
2379 }
2380
2381 #[test]
2382 fn test_connect_any_past_the_deadline_times_out() {
2383 let open = TcpListener::bind("127.0.0.1:0").unwrap();
2384 let good = open.local_addr().unwrap();
2385 let err = connect_any([good], Duration::from_secs(5), Some(Instant::now())).unwrap_err();
2386 assert!(
2387 matches!(&err, Error::Io(e) if e.kind() == io::ErrorKind::TimedOut),
2388 "{err}"
2389 );
2390 }
2391
2392 #[test]
2393 fn test_client_request_with_host_is_refused() {
2394 let req = Request::get("/").header("host", "a");
2395 let err = Client::new()
2396 .request("http://127.0.0.1:1/", req)
2397 .unwrap_err();
2398 assert!(matches!(err, Error::Http(HttpError::InvalidHost)), "{err}");
2399 }
2400
2401 #[test]
2402 fn test_client_request_streamed_body_is_refused() {
2403 for req in [
2404 Request::post("/").chunked(),
2405 Request::put("/").content_length(3),
2406 ] {
2407 let err = Client::new()
2408 .request("http://127.0.0.1:1/", req)
2409 .unwrap_err();
2410 assert!(
2411 matches!(err, Error::Http(HttpError::InvalidState(_))),
2412 "{err}"
2413 );
2414 }
2415 }
2416
2417 #[test]
2418 fn test_retarget_keeps_method_fields_body_and_flags() {
2419 let original = Request::new("PATCH", "/ignored")
2420 .header("x-a", "1")
2421 .header("content-type", "text/plain")
2422 .body(&b"xyz"[..]);
2423 let r = retarget(&original, "/real?q", "example.com:8080").unwrap();
2424 assert_eq!(r.method(), "PATCH");
2425 assert_eq!(r.target(), "/real?q");
2426 assert_eq!(r.header_value("host"), Some(&b"example.com:8080"[..]));
2427 assert_eq!(r.header_value("x-a"), Some(&b"1"[..]));
2428 assert_eq!(r.body_bytes(), Some(&b"xyz"[..]));
2429 let mut out = Vec::new();
2430 ClientConn::new().send_request(&r, &mut out).unwrap();
2431 let text = String::from_utf8(out).unwrap();
2432 assert!(
2433 text.starts_with("PATCH /real?q HTTP/1.1\r\nhost: example.com:8080\r\nx-a: 1\r\n"),
2434 "{text}"
2435 );
2436 assert!(text.contains("connection: close\r\n"), "{text}");
2437 assert!(text.ends_with("\r\n\r\nxyz"), "{text}");
2438
2439 // The blocking client reads one response to its end, so it cannot
2440 // hand over an upgraded connection.
2441 let up = Request::get("/").upgrade("websocket");
2442 assert!(matches!(
2443 retarget(&up, "/", "a"),
2444 Err(Error::Http(HttpError::InvalidState(_)))
2445 ));
2446 // A builder error surfaces first.
2447 let bad = Request::get("/").header("bad name", "x");
2448 assert!(matches!(
2449 retarget(&bad, "/", "a"),
2450 Err(Error::Http(HttpError::InvalidHeaderName))
2451 ));
2452 }
2453
2454 #[test]
2455 fn test_url_parsing() {
2456 let u = Url::parse("http://127.0.0.1:8080/a/b?c=d#frag").unwrap();
2457 assert_eq!(
2458 u,
2459 Url {
2460 authority: "127.0.0.1:8080",
2461 host: "127.0.0.1",
2462 port: 8080,
2463 target: "/a/b?c=d"
2464 }
2465 );
2466 let u = Url::parse("HTTP://[::1]/").unwrap();
2467 assert_eq!((u.host, u.port, u.authority), ("::1", 80, "[::1]"));
2468 assert_eq!(Url::parse("http://example.com").unwrap().target, "/");
2469 for bad in [
2470 "example.com",
2471 "https://x/",
2472 "http:///x",
2473 "http://u:p@x/",
2474 "http://x:99999/",
2475 "http://[::1/",
2476 "http://[::1]x/",
2477 "http://x?q",
2478 "http://:80/",
2479 ] {
2480 assert!(
2481 matches!(Url::parse(bad), Err(Error::InvalidUrl(_))),
2482 "{bad}"
2483 );
2484 }
2485 }
2486
2487 #[test]
2488 fn test_error_display_and_source() {
2489 use std::error::Error as _;
2490 let e = Error::from(HttpError::BareCr);
2491 assert!(e.to_string().starts_with("HTTP error"));
2492 assert!(e.source().is_some());
2493 let e = Error::from(io::Error::other("x"));
2494 assert!(e.source().is_some());
2495 assert!(Error::InvalidUrl("y").source().is_none());
2496 }
2497}