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