Skip to main content

giong_http/
server.rs

1//! The accept loop and the per-connection state machine.
2
3use std::cell::RefCell;
4use std::future::{poll_fn, Future};
5use std::io;
6use std::mem;
7use std::net::Shutdown;
8use std::ops::Deref;
9use std::pin::pin;
10use std::rc::Rc;
11use std::task::Poll;
12use std::time::{Duration, Instant};
13
14use giong::net::{TcpListener, TcpStream, UnixListener, UnixStream};
15use giong::time::{sleep, timeout};
16
17use crate::chunked::{Decoder, Progress};
18use crate::parse::{find_head_end, parse_head};
19use crate::request::{BodyBytes, Request};
20use crate::response::Response;
21
22/// Responses to pipelined requests are sent together, up to this many bytes.
23const FLUSH_AT: usize = 64 * 1024;
24/// After an error response, how long the connection keeps discarding input so
25/// that the client can read the response instead of getting a reset.
26const ERROR_LINGER: Duration = Duration::from_secs(1);
27
28thread_local! {
29    /// Buffers recycled between the connections of one worker. A connection
30    /// holds none while it is idle, so keep-alive connections cost little.
31    static BUFFERS: RefCell<Vec<Vec<u8>>> = const { RefCell::new(Vec::new()) };
32}
33
34fn take_buffer() -> Vec<u8> {
35    BUFFERS
36        .with(|pool| pool.borrow_mut().pop())
37        .unwrap_or_else(|| Vec::with_capacity(4 * 1024))
38}
39
40fn give_buffer(mut buf: Vec<u8>) {
41    buf.clear();
42    if buf.capacity() == 0 || buf.capacity() > 256 * 1024 {
43        return;
44    }
45    BUFFERS.with(|pool| {
46        let mut pool = pool.borrow_mut();
47        if pool.len() < 1024 {
48            pool.push(buf);
49        }
50    });
51}
52
53/// A byte stream that HTTP can be served over: a [`TcpStream`], or a TLS
54/// stream with the `tls` feature.
55///
56/// The methods follow [`TcpStream`]: buffers are passed by value and handed
57/// back, and `recv` must be cancel safe (dropping its future loses no data),
58/// because the server wraps it in timeouts.
59pub trait Transport: 'static {
60    /// What `recv` returns; released before the server awaits anything else.
61    type Chunk: Deref<Target = [u8]>;
62
63    /// Receives the next piece of data. Empty means end of stream.
64    fn recv(&self) -> impl Future<Output = io::Result<Self::Chunk>>;
65
66    /// Sends all of `buf` and hands it back.
67    fn write_all(&self, buf: Vec<u8>) -> impl Future<Output = (io::Result<()>, Vec<u8>)>;
68
69    /// Closes the sending direction, so the peer sees the end of the stream
70    /// while the server can still read what it sends.
71    fn close_write(&self) -> impl Future<Output = ()>;
72}
73
74impl Transport for TcpStream {
75    type Chunk = giong::RecvBuf;
76
77    fn recv(&self) -> impl Future<Output = io::Result<Self::Chunk>> {
78        TcpStream::recv(self)
79    }
80
81    fn write_all(&self, buf: Vec<u8>) -> impl Future<Output = (io::Result<()>, Vec<u8>)> {
82        TcpStream::write_all(self, buf)
83    }
84
85    async fn close_write(&self) {
86        let _ = self.shutdown(Shutdown::Write);
87    }
88}
89
90impl Transport for UnixStream {
91    type Chunk = giong::RecvBuf;
92
93    fn recv(&self) -> impl Future<Output = io::Result<Self::Chunk>> {
94        UnixStream::recv(self)
95    }
96
97    fn write_all(&self, buf: Vec<u8>) -> impl Future<Output = (io::Result<()>, Vec<u8>)> {
98        UnixStream::write_all(self, buf)
99    }
100
101    async fn close_write(&self) {
102        let _ = self.shutdown(Shutdown::Write);
103    }
104}
105
106#[cfg(feature = "tls")]
107impl Transport for giong_tls::TlsStream {
108    type Chunk = Vec<u8>;
109
110    fn recv(&self) -> impl Future<Output = io::Result<Self::Chunk>> {
111        giong_tls::TlsStream::recv(self)
112    }
113
114    fn write_all(&self, buf: Vec<u8>) -> impl Future<Output = (io::Result<()>, Vec<u8>)> {
115        giong_tls::TlsStream::write_all(self, buf)
116    }
117
118    async fn close_write(&self) {
119        let _ = self.shutdown().await;
120    }
121}
122
123#[derive(Clone, Copy, Debug)]
124struct Config {
125    idle_timeout: Duration,
126    request_timeout: Duration,
127    write_timeout: Duration,
128    max_head_size: usize,
129    max_body_size: usize,
130    shutdown_linger: Duration,
131}
132
133/// An HTTP/1.1 server. Configure it, then call [`serve`](Server::serve) from
134/// each worker of a giong runtime.
135///
136/// ```no_run
137/// use std::time::Duration;
138/// use giong::net::TcpListener;
139/// use giong_http::{Request, Response, Server};
140///
141/// async fn hello(req: Request) -> Response {
142///     match (req.method(), req.path()) {
143///         ("GET", "/") => Response::text("hello"),
144///         _ => Response::new(404),
145///     }
146/// }
147///
148/// fn main() -> std::io::Result<()> {
149///     giong::Builder::new()
150///         .shutdown_on_signals(true)
151///         .shutdown_grace(Duration::from_secs(10))
152///         .build()?
153///         .run(|_worker| async {
154///             let listener = TcpListener::bind("0.0.0.0:8080").expect("bind");
155///             Server::new().serve(listener, hello).await;
156///         })
157/// }
158/// ```
159#[derive(Clone, Debug)]
160pub struct Server {
161    cfg: Config,
162}
163
164impl Default for Server {
165    fn default() -> Self {
166        Self::new()
167    }
168}
169
170impl Server {
171    /// A server with the default limits and timeouts.
172    pub fn new() -> Self {
173        Self {
174            cfg: Config {
175                idle_timeout: Duration::from_secs(60),
176                request_timeout: Duration::from_secs(30),
177                write_timeout: Duration::from_secs(30),
178                max_head_size: 64 * 1024,
179                max_body_size: 1024 * 1024,
180                shutdown_linger: Duration::from_millis(100),
181            },
182        }
183    }
184
185    /// How long a keep-alive connection may sit between requests before it is
186    /// closed (default: 60 s).
187    pub fn idle_timeout(mut self, timeout: Duration) -> Self {
188        self.cfg.idle_timeout = timeout;
189        self
190    }
191
192    /// How long a client may take to send one complete request, counted from
193    /// the moment the server first has to wait for more of it (default: 30 s).
194    /// Slower clients get `408 Request Timeout`.
195    pub fn request_timeout(mut self, timeout: Duration) -> Self {
196        self.cfg.request_timeout = timeout;
197        self
198    }
199
200    /// How long a client may take to accept a batch of responses before the
201    /// connection is dropped (default: 30 s).
202    pub fn write_timeout(mut self, timeout: Duration) -> Self {
203        self.cfg.write_timeout = timeout;
204        self
205    }
206
207    /// Largest accepted request head, in bytes (default: 64 KiB). Larger heads
208    /// get `431 Request Header Fields Too Large`.
209    pub fn max_head_size(mut self, bytes: usize) -> Self {
210        self.cfg.max_head_size = bytes.max(64);
211        self
212    }
213
214    /// Largest accepted request body, in bytes (default: 1 MiB). Larger bodies
215    /// get `413 Content Too Large`.
216    pub fn max_body_size(mut self, bytes: usize) -> Self {
217        self.cfg.max_body_size = bytes;
218        self
219    }
220
221    /// After a shutdown is requested, how long the server keeps picking up
222    /// connections and requests that were already on their way (default:
223    /// 100 ms). Requests in progress are not affected by this: they get the
224    /// runtime's [`shutdown_grace`](giong::Builder::shutdown_grace).
225    pub fn shutdown_linger(mut self, linger: Duration) -> Self {
226        self.cfg.shutdown_linger = linger;
227        self
228    }
229
230    /// Accepts connections on `listener` and answers their requests with
231    /// `handler` until the runtime is asked to shut down.
232    ///
233    /// Each connection runs as its own task on the current worker. When a
234    /// shutdown is requested, the listener stops accepting, idle connections
235    /// are closed, and requests being handled are finished and answered with
236    /// `Connection: close`, within the grace period configured on the runtime.
237    ///
238    /// A handler that panics takes down its connection only.
239    pub async fn serve<H, Fut>(&self, listener: TcpListener, handler: H)
240    where
241        H: Fn(Request) -> Fut + 'static,
242        Fut: Future<Output = Response> + 'static,
243    {
244        let handler = Rc::new(handler);
245        let cfg = self.cfg;
246        let accept = || listener.accept();
247        self.accept_loop(accept, |stream: TcpStream| {
248            let _ = stream.set_nodelay(true);
249            drop(giong::spawn(Conn::new(stream, cfg).run(handler.clone())));
250        })
251        .await;
252    }
253
254    /// Like [`serve`](Self::serve), on a Unix domain socket: the usual way to
255    /// sit behind a reverse proxy on the same machine.
256    ///
257    /// ```no_run
258    /// # use giong::net::UnixListener;
259    /// # use giong_http::{Request, Response, Server};
260    /// # async fn handler(_: Request) -> Response { Response::new(200) }
261    /// # async fn demo() -> std::io::Result<()> {
262    /// let listener = UnixListener::bind("/run/app.sock")?;
263    /// Server::new().serve_unix(listener, handler).await;
264    /// # Ok(())
265    /// # }
266    /// ```
267    pub async fn serve_unix<H, Fut>(&self, listener: UnixListener, handler: H)
268    where
269        H: Fn(Request) -> Fut + 'static,
270        Fut: Future<Output = Response> + 'static,
271    {
272        let handler = Rc::new(handler);
273        let cfg = self.cfg;
274        let accept = || listener.accept();
275        self.accept_loop(accept, |stream: UnixStream| {
276            drop(giong::spawn(Conn::new(stream, cfg).run(handler.clone())));
277        })
278        .await;
279    }
280
281    /// Like [`serve`](Self::serve), over TLS: every accepted connection first
282    /// completes a TLS handshake with `acceptor`.
283    ///
284    /// ```no_run
285    /// # use giong::net::TcpListener;
286    /// # use giong_http::{Request, Response, Server};
287    /// # async fn handler(_: Request) -> Response { Response::new(200) }
288    /// # async fn demo() -> std::io::Result<()> {
289    /// let acceptor = giong_tls::TlsAcceptor::from_pem(
290    ///     &std::fs::read("cert.pem")?,
291    ///     &std::fs::read("key.pem")?,
292    /// )?;
293    /// let listener = TcpListener::bind("0.0.0.0:8443")?;
294    /// Server::new().serve_tls(listener, acceptor, handler).await;
295    /// # Ok(())
296    /// # }
297    /// ```
298    #[cfg(feature = "tls")]
299    pub async fn serve_tls<H, Fut>(
300        &self,
301        listener: TcpListener,
302        acceptor: giong_tls::TlsAcceptor,
303        handler: H,
304    ) where
305        H: Fn(Request) -> Fut + 'static,
306        Fut: Future<Output = Response> + 'static,
307    {
308        let handler = Rc::new(handler);
309        let cfg = self.cfg;
310        let accept = || listener.accept();
311        self.accept_loop(accept, |stream: TcpStream| {
312            let _ = stream.set_nodelay(true);
313            let (acceptor, handler) = (acceptor.clone(), handler.clone());
314            drop(giong::spawn(async move {
315                // A failed handshake (a port scan, a plain-HTTP client, an
316                // unknown protocol version) just ends the connection.
317                if let Ok(tls) = acceptor.accept(stream).await {
318                    Conn::new(tls, cfg).run(handler).await;
319                }
320            }));
321        })
322        .await;
323    }
324
325    /// Accepts until a shutdown is requested, then for a moment longer.
326    async fn accept_loop<S, A>(&self, accept: impl Fn() -> A, spawn: impl Fn(S))
327    where
328        A: Future<Output = io::Result<S>>,
329    {
330        while let Some(accepted) = giong::until_shutdown(accept()).await {
331            match accepted {
332                Ok(stream) => spawn(stream),
333                // For example EMFILE: back off instead of spinning.
334                Err(_) => sleep(Duration::from_millis(50)).await,
335            }
336        }
337        // Connections established just before the shutdown still get served.
338        let deadline = Instant::now() + self.cfg.shutdown_linger;
339        loop {
340            let left = deadline.saturating_duration_since(Instant::now());
341            match timeout(left, accept()).await {
342                Ok(Ok(stream)) => spawn(stream),
343                _ => break,
344            }
345        }
346    }
347
348    /// Serves a single, already established connection until it is closed.
349    /// For servers that run their own accept loop or their own transport.
350    pub async fn serve_connection<T, H, Fut>(&self, stream: T, handler: Rc<H>)
351    where
352        T: Transport,
353        H: Fn(Request) -> Fut + 'static,
354        Fut: Future<Output = Response> + 'static,
355    {
356        Conn::new(stream, self.cfg).run(handler).await;
357    }
358}
359
360/// Why a connection stops reading requests.
361enum End {
362    /// Close without a response: end of stream, idle timeout, I/O error.
363    Close,
364    /// Answer with this error status, then close.
365    Status(u16),
366}
367
368struct Conn<T> {
369    stream: T,
370    cfg: Config,
371    /// Received bytes. Shared with the requests handed to the handler, so it
372    /// is only modified in place once those have been dropped.
373    buf: Rc<Vec<u8>>,
374    /// Where the unparsed data starts in `buf`.
375    pos: usize,
376    /// How much of the unparsed data has been searched for the end of a head.
377    scanned: usize,
378    /// Responses not sent yet.
379    out: Vec<u8>,
380    /// The server is shutting down: answer what arrives, then close.
381    closing: bool,
382    /// Deadline for the request currently being received.
383    deadline: Option<Instant>,
384}
385
386impl<T: Transport> Conn<T> {
387    fn new(stream: T, cfg: Config) -> Self {
388        Self {
389            stream,
390            cfg,
391            buf: Rc::new(Vec::new()),
392            pos: 0,
393            scanned: 0,
394            out: Vec::new(),
395            closing: false,
396            deadline: None,
397        }
398    }
399
400    async fn run<H, Fut>(mut self, handler: Rc<H>)
401    where
402        H: Fn(Request) -> Fut + 'static,
403        Fut: Future<Output = Response> + 'static,
404    {
405        loop {
406            let req = match self.next_request().await {
407                Ok(req) => req,
408                Err(End::Close) => break,
409                Err(End::Status(status)) => {
410                    self.reserve_out();
411                    Response::new(status).write_to(&mut self.out, 1, false, false);
412                    if self.flush().await.is_ok() {
413                        self.lingering_close().await;
414                    }
415                    return;
416                }
417            };
418            let minor = req.head.minor;
419            let head_only = req.method() == "HEAD";
420            let wants_keep_alive = !req.head.close && (minor == 1 || req.head.keep_alive);
421
422            // Poll the handler once before deciding what to do with responses
423            // that are waiting: if it answers at once (the common case), they
424            // all go out in one write; if it has to wait, they go out first.
425            let mut fut = pin!(handler(req));
426            let first = poll_fn(|cx| Poll::Ready(fut.as_mut().poll(cx))).await;
427            let resp = match first {
428                Poll::Ready(resp) => resp,
429                Poll::Pending => {
430                    if self.flush().await.is_err() {
431                        return;
432                    }
433                    fut.await
434                }
435            };
436
437            // Decided after the handler ran: a shutdown may have begun meanwhile.
438            self.closing |= giong::is_shutting_down();
439            let keep_alive = wants_keep_alive && !self.closing;
440            self.reserve_out();
441            resp.write_to(&mut self.out, minor, keep_alive, head_only);
442            if !keep_alive {
443                break;
444            }
445            if self.out.len() >= FLUSH_AT && self.flush().await.is_err() {
446                return;
447            }
448        }
449        if self.flush().await.is_ok() {
450            self.close_write().await;
451        }
452    }
453
454    /// Receives and parses the next request, body included.
455    async fn next_request(&mut self) -> Result<Request, End> {
456        let head = loop {
457            // Empty lines before a request line are ignored (RFC 9112 ยง2.2).
458            while self.buf[self.pos..].starts_with(b"\r\n") {
459                self.pos += 2;
460                self.scanned = 0;
461            }
462            let data = &self.buf[self.pos..];
463            if let Some(end) = find_head_end(data, self.scanned) {
464                if end > self.cfg.max_head_size {
465                    return Err(End::Status(431));
466                }
467                break parse_head(&data[..end]).map_err(End::Status)?;
468            }
469            if data.len() > self.cfg.max_head_size {
470                return Err(End::Status(431));
471            }
472            // The terminator may straddle the next read.
473            self.scanned = data.len().saturating_sub(3);
474            let idle = data.is_empty();
475            self.read_more(idle).await?;
476        };
477
478        let mut interim_sent = false;
479        let (body, total) = if head.chunked {
480            let mut decoder = Decoder::new(self.cfg.max_body_size);
481            loop {
482                let data = &self.buf[self.pos + head.len..];
483                match decoder.feed(data).map_err(End::Status)? {
484                    Progress::Done(used) => {
485                        break (
486                            BodyBytes::Decoded(mem::take(&mut decoder.body)),
487                            head.len + used,
488                        )
489                    }
490                    Progress::NeedMore => {
491                        self.send_continue(&head, &mut interim_sent);
492                        self.read_more(false).await?;
493                    }
494                }
495            }
496        } else {
497            let len = head.content_length.unwrap_or(0);
498            if len > self.cfg.max_body_size as u64 {
499                return Err(End::Status(413));
500            }
501            let len = len as usize;
502            while self.buf.len() - self.pos - head.len < len {
503                self.send_continue(&head, &mut interim_sent);
504                self.read_more(false).await?;
505            }
506            let start = self.pos + head.len;
507            (BodyBytes::InBuffer(start..start + len), head.len + len)
508        };
509
510        let req = Request {
511            buf: self.buf.clone(),
512            start: self.pos,
513            head,
514            body,
515        };
516        self.pos += total;
517        self.scanned = 0;
518        self.deadline = None;
519        Ok(req)
520    }
521
522    /// Answers `Expect: 100-continue` once, before waiting for the body.
523    fn send_continue(&mut self, head: &crate::parse::Head, sent: &mut bool) {
524        if head.expect_continue && head.minor == 1 && !*sent {
525            *sent = true;
526            self.reserve_out();
527            self.out.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
528        }
529    }
530
531    /// Sends pending responses, then waits for more input. `idle` means that
532    /// no part of a request has been received yet.
533    async fn read_more(&mut self, idle: bool) -> Result<(), End> {
534        self.flush().await?;
535        let received = if idle {
536            if self.closing {
537                return Err(End::Close);
538            }
539            self.release_buffers();
540            let recv = timeout(self.cfg.idle_timeout, self.stream.recv());
541            match giong::until_shutdown(recv).await {
542                Some(received) => received,
543                None => {
544                    // Shutting down: a request that was already on its way is
545                    // still answered, then the connection closes.
546                    self.closing = true;
547                    timeout(self.cfg.shutdown_linger, self.stream.recv()).await
548                }
549            }
550        } else {
551            let request_timeout = self.cfg.request_timeout;
552            let deadline = *self
553                .deadline
554                .get_or_insert_with(|| Instant::now() + request_timeout);
555            let left = deadline.saturating_duration_since(Instant::now());
556            match timeout(left, self.stream.recv()).await {
557                Ok(received) => Ok(received),
558                Err(_) => return Err(End::Status(408)),
559            }
560        };
561        match received {
562            Ok(Ok(chunk)) if !chunk.is_empty() => {
563                self.append(&chunk);
564                Ok(())
565            }
566            // Idle for too long, an I/O error, or closed by the peer.
567            _ => Err(End::Close),
568        }
569    }
570
571    /// Adds received bytes to the buffer, dropping what has been consumed.
572    fn append(&mut self, chunk: &[u8]) {
573        match Rc::get_mut(&mut self.buf) {
574            Some(buf) => {
575                if self.pos > 0 {
576                    buf.drain(..self.pos);
577                    self.pos = 0;
578                }
579                if buf.capacity() == 0 {
580                    *buf = take_buffer();
581                }
582                buf.extend_from_slice(chunk);
583            }
584            // A handler kept a request alive: leave its buffer alone.
585            None => {
586                let mut fresh = take_buffer();
587                fresh.extend_from_slice(&self.buf[self.pos..]);
588                fresh.extend_from_slice(chunk);
589                self.buf = Rc::new(fresh);
590                self.pos = 0;
591            }
592        }
593    }
594
595    fn reserve_out(&mut self) {
596        if self.out.capacity() == 0 {
597            self.out = take_buffer();
598        }
599    }
600
601    /// Hands both buffers back to the worker's pool before an idle wait.
602    fn release_buffers(&mut self) {
603        if self.pos == self.buf.len() {
604            match Rc::get_mut(&mut self.buf) {
605                Some(buf) => give_buffer(mem::take(buf)),
606                None => self.buf = Rc::new(Vec::new()),
607            }
608            self.pos = 0;
609        }
610        give_buffer(mem::take(&mut self.out));
611    }
612
613    /// Writes everything in `out`. One send per batch of responses.
614    async fn flush(&mut self) -> Result<(), End> {
615        if self.out.is_empty() {
616            return Ok(());
617        }
618        let out = mem::take(&mut self.out);
619        match timeout(self.cfg.write_timeout, self.stream.write_all(out)).await {
620            Ok((Ok(()), mut out)) => {
621                out.clear();
622                self.out = out;
623                Ok(())
624            }
625            _ => Err(End::Close),
626        }
627    }
628
629    /// Tells the peer that nothing more will be sent: a FIN, and over TLS a
630    /// `close_notify` before it, so that the client can tell a complete
631    /// response from a connection that was cut off.
632    async fn close_write(&mut self) {
633        let _ = timeout(self.cfg.write_timeout, self.stream.close_write()).await;
634    }
635
636    /// Closing a socket that still has unread input makes the kernel send a
637    /// reset, which can destroy the error response before the client reads it.
638    /// So: stop sending, then discard input for a moment.
639    async fn lingering_close(&mut self) {
640        self.close_write().await;
641        let deadline = Instant::now() + ERROR_LINGER;
642        loop {
643            let left = deadline.saturating_duration_since(Instant::now());
644            match timeout(left, self.stream.recv()).await {
645                Ok(Ok(chunk)) if !chunk.is_empty() => {}
646                _ => return,
647            }
648        }
649    }
650}