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