Skip to main content

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