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