Skip to main content

http_net/
server.rs

1//! The server side of an HTTP/1.1 connection, without I/O.
2
3use alloc::vec::Vec;
4
5use crate::{
6    body::{Decoder, Encoder, Step, push_framing},
7    buffer::Buffer,
8    error::HttpError,
9    head::{HeadKind, HeadScanner, Progress, RequestHead, RequestInfo, Version, interpret_request},
10    limits::Limits,
11    message::{OutBody, Response},
12    method::Method,
13    status::reason_phrase,
14    syntax::push_decimal,
15};
16
17/// What a [`ServerConn`] has for the caller after [`poll`](ServerConn::poll).
18///
19/// # Examples
20///
21/// ```
22/// use http_net::{Response, ServerConn, ServerEvent};
23///
24/// let mut conn = ServerConn::new();
25/// let mut out = Vec::new();
26/// let _ = conn.feed(b"POST /echo HTTP/1.1\r\nHost: a\r\nContent-Length: 2\r\n\r\nhi");
27/// let mut body = Vec::new();
28/// loop {
29///     match conn.poll().unwrap() {
30///         ServerEvent::Request(req) => assert_eq!(req.path(), "/echo"),
31///         ServerEvent::Body(chunk) => body.extend_from_slice(chunk),
32///         ServerEvent::RequestEnd => {
33///             conn.respond(&Response::new(200).body(body.clone()), &mut out).unwrap();
34///         }
35///         ServerEvent::NeedInput => break,
36///         other => panic!("{other:?}"),
37///     }
38/// }
39/// assert!(out.ends_with(b"\r\n\r\nhi"));
40/// ```
41#[non_exhaustive]
42#[derive(Debug)]
43pub enum ServerEvent<'a> {
44    /// A request head arrived. Its body (if any) follows as
45    /// [`Body`](ServerEvent::Body) events, then
46    /// [`RequestEnd`](ServerEvent::RequestEnd). A response may be sent from
47    /// this point on; sending it while body bytes are still unread closes
48    /// the connection afterwards (a request without a body stays
49    /// keep-alive). If the head
50    /// [`expects_continue`](RequestHead::expects_continue), answer with
51    /// [`send_continue`](ServerConn::send_continue) or a final response
52    /// before waiting for the body.
53    Request(RequestHead<'a>),
54    /// A run of body bytes, after chunked decoding.
55    Body(&'a [u8]),
56    /// The request is complete. Send the response if it has not been sent.
57    RequestEnd,
58    /// More input is needed: read from the socket, then
59    /// [`feed`](ServerConn::feed) (or [`read_buf`](ServerConn::read_buf) and
60    /// [`commit`](ServerConn::commit)), or [`feed_eof`](ServerConn::feed_eof)
61    /// if the peer closed.
62    NeedInput,
63    /// The request is complete and its response has not been finished yet.
64    /// Pipelined requests wait in the buffer until it is.
65    AwaitingResponse,
66    /// A `101 Switching Protocols` (or a 2xx to `CONNECT`) was sent: the
67    /// connection now belongs to the new protocol. Bytes that already arrived
68    /// for it are in [`remaining_input`](ServerConn::remaining_input).
69    Upgraded,
70    /// The connection is finished: flush any output, then close the socket.
71    Closed,
72}
73
74#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75enum ReqState {
76    Head,
77    Body,
78    Complete,
79    Upgraded,
80    Failed,
81    Closed,
82}
83
84#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85enum RespState {
86    Idle,
87    Streaming(Encoder),
88    Sent,
89}
90
91/// The server side of one HTTP/1.1 connection: a sans-IO state machine.
92///
93/// The connection owns a bounded input buffer. The caller moves bytes
94/// between it and the socket: input in through [`feed`](Self::feed) (or
95/// [`read_buf`](Self::read_buf) + [`commit`](Self::commit) to read straight
96/// into the buffer), events out through [`poll`](Self::poll), responses out
97/// through [`respond`](Self::respond) into a caller-owned `Vec<u8>`.
98///
99/// Requests are handled one at a time, in order. Keep-alive is automatic:
100/// after a response is finished the next request (possibly already buffered,
101/// when the client pipelines) is parsed on the next `poll`. A connection
102/// that must close (the client asked, HTTP/1.0 without keep-alive, the
103/// response was sent before the request body was read, or a parse error)
104/// reports [`ServerEvent::Closed`] once its last response is written.
105///
106/// Steady state allocates nothing: the input buffer and the field index are
107/// reused across requests.
108///
109/// # Examples
110///
111/// ```
112/// use http_net::{Response, ServerConn, ServerEvent};
113///
114/// let mut conn = ServerConn::new();
115/// let mut out = Vec::new();
116/// // Two pipelined requests in one read.
117/// let _ = conn.feed(b"GET /a HTTP/1.1\r\nHost: x\r\n\r\nGET /b HTTP/1.1\r\nHost: x\r\n\r\n");
118/// let mut paths = Vec::new();
119/// loop {
120///     match conn.poll().unwrap() {
121///         ServerEvent::Request(req) => paths.push(req.path().to_string()),
122///         ServerEvent::RequestEnd => conn.respond(&Response::text(200, "ok"), &mut out).unwrap(),
123///         ServerEvent::NeedInput => break,
124///         other => panic!("{other:?}"),
125///     }
126/// }
127/// assert_eq!(paths, ["/a", "/b"]);
128/// ```
129pub struct ServerConn {
130    buf: Buffer,
131    limits: Limits,
132    scanner: HeadScanner,
133    trailers: HeadScanner,
134    decoder: Decoder,
135    info: RequestInfo,
136    state: ReqState,
137    resp: RespState,
138    keep_alive: bool,
139    continue_sent: bool,
140}
141
142impl Default for ServerConn {
143    fn default() -> Self {
144        Self::new()
145    }
146}
147
148impl core::fmt::Debug for ServerConn {
149    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
150        f.debug_struct("ServerConn")
151            .field("state", &self.state)
152            .field("response", &self.resp)
153            .field("buffered", &self.buf.unread().len())
154            .field("limits", &self.limits)
155            .finish()
156    }
157}
158
159impl ServerConn {
160    /// A connection with the default [`Limits`].
161    ///
162    /// # Examples
163    ///
164    /// ```
165    /// let conn = http_net::ServerConn::new();
166    /// assert!(conn.request().is_none());
167    /// ```
168    #[must_use]
169    pub fn new() -> Self {
170        Self::with_limits(Limits::new())
171    }
172
173    /// A connection enforcing `limits`.
174    ///
175    /// # Examples
176    ///
177    /// ```
178    /// use http_net::{HttpError, Limits, ServerConn};
179    ///
180    /// let mut conn = ServerConn::with_limits(Limits::new().with_max_body(4));
181    /// let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\n");
182    /// assert_eq!(conn.poll().unwrap_err(), HttpError::BodyTooLarge);
183    /// ```
184    #[must_use]
185    pub fn with_limits(limits: Limits) -> Self {
186        let mut buf = Buffer::new(limits.buffer_capacity());
187        buf.pin_at_pos();
188        Self {
189            buf,
190            limits,
191            scanner: HeadScanner::new(),
192            trailers: HeadScanner::new(),
193            decoder: Decoder::new(),
194            info: RequestInfo::EMPTY,
195            state: ReqState::Head,
196            resp: RespState::Idle,
197            keep_alive: false,
198            continue_sent: false,
199        }
200    }
201
202    /// The limits this connection enforces.
203    ///
204    /// # Examples
205    ///
206    /// ```
207    /// assert_eq!(http_net::ServerConn::new().limits(), &http_net::Limits::new());
208    /// ```
209    #[must_use]
210    pub fn limits(&self) -> &Limits {
211        &self.limits
212    }
213
214    /// Copies as much of `bytes` into the input buffer as fits and returns
215    /// how many bytes were taken. Fewer than `bytes.len()` means the buffer
216    /// is full: [`poll`](Self::poll) until it asks for input, then feed the
217    /// rest.
218    ///
219    /// # Examples
220    ///
221    /// ```
222    /// let mut conn = http_net::ServerConn::new();
223    /// assert_eq!(conn.feed(b"GET / HTTP/1.1\r\n"), 16);
224    /// ```
225    #[must_use = "bytes beyond the returned count were not taken"]
226    pub fn feed(&mut self, bytes: &[u8]) -> usize {
227        self.buf.feed(bytes)
228    }
229
230    /// Spare space at the end of the input buffer, for reading from a
231    /// socket without an intermediate copy. Follow with
232    /// [`commit`](Self::commit). It is empty only when the buffer is full of
233    /// input the parser has not been asked to process yet; poll first.
234    ///
235    /// # Examples
236    ///
237    /// ```
238    /// let mut conn = http_net::ServerConn::new();
239    /// let spare = conn.read_buf();
240    /// let msg = b"GET / HTTP/1.1\r\nHost: a\r\n\r\n";
241    /// spare[..msg.len()].copy_from_slice(msg);
242    /// conn.commit(msg.len());
243    /// assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::Request(_))));
244    /// ```
245    pub fn read_buf(&mut self) -> &mut [u8] {
246        self.buf.spare()
247    }
248
249    /// Records that `n` bytes were written into [`read_buf`](Self::read_buf).
250    ///
251    /// # Examples
252    ///
253    /// ```
254    /// let mut conn = http_net::ServerConn::new();
255    /// conn.read_buf()[0] = b'G';
256    /// conn.commit(1);
257    /// assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::NeedInput)));
258    /// ```
259    pub fn commit(&mut self, n: usize) {
260        self.buf.commit(n);
261    }
262
263    /// Records that the peer closed its sending side. A connection idle
264    /// between requests then reports [`ServerEvent::Closed`]; one in the
265    /// middle of a request reports [`HttpError::UnexpectedEof`].
266    ///
267    /// # Examples
268    ///
269    /// ```
270    /// let mut conn = http_net::ServerConn::new();
271    /// conn.feed_eof();
272    /// assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::Closed)));
273    /// ```
274    pub fn feed_eof(&mut self) {
275        self.buf.set_eof();
276    }
277
278    /// Advances the parser and reports what happened. Call it until it
279    /// returns [`ServerEvent::NeedInput`], [`ServerEvent::AwaitingResponse`],
280    /// [`ServerEvent::Upgraded`], or [`ServerEvent::Closed`].
281    ///
282    /// # Errors
283    ///
284    /// Any [`HttpError`] parse error. The connection is then finished: send
285    /// one error response (see [`HttpError::status`]) with
286    /// [`respond`](Self::respond), flush, and close.
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// use http_net::{HttpError, ServerConn};
292    ///
293    /// let mut conn = ServerConn::new();
294    /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n folded\r\n\r\n");
295    /// assert_eq!(conn.poll().unwrap_err(), HttpError::ObsFold);
296    /// ```
297    pub fn poll(&mut self) -> Result<ServerEvent<'_>, HttpError> {
298        loop {
299            match self.state {
300                ReqState::Head => return self.poll_head(),
301                ReqState::Body => {
302                    if self.resp == RespState::Sent && !self.decoder.is_done() {
303                        // Answered before the body was read: the rest of the
304                        // body cannot be trusted to frame the next request.
305                        self.state = ReqState::Closed;
306                        return Ok(ServerEvent::Closed);
307                    }
308                    return self.poll_body();
309                }
310                ReqState::Complete => {
311                    if self.resp != RespState::Sent {
312                        return Ok(ServerEvent::AwaitingResponse);
313                    }
314                    if !self.keep_alive {
315                        self.state = ReqState::Closed;
316                        return Ok(ServerEvent::Closed);
317                    }
318                    self.next_exchange();
319                }
320                ReqState::Upgraded => return Ok(ServerEvent::Upgraded),
321                ReqState::Failed | ReqState::Closed => return Ok(ServerEvent::Closed),
322            }
323        }
324    }
325
326    fn poll_head(&mut self) -> Result<ServerEvent<'_>, HttpError> {
327        let start = self.buf.pin();
328        let msg = self.buf.from(start);
329        let progress = self
330            .scanner
331            .advance(msg, &self.limits, HeadKind::Request, true)
332            .map_err(|e| self.fail(e))?;
333        let len = match progress {
334            Progress::Partial if self.buf.is_eof() => {
335                if self.buf.from(start).is_empty() {
336                    self.state = ReqState::Closed;
337                    return Ok(ServerEvent::Closed);
338                }
339                return Err(self.fail(HttpError::UnexpectedEof));
340            }
341            Progress::Partial => return Ok(ServerEvent::NeedInput),
342            Progress::Done(len) => len,
343        };
344        let info = interpret_request(
345            self.buf.from(start),
346            self.scanner.start_line(),
347            &self.scanner.fields,
348            &self.limits,
349        )
350        .map_err(|e| self.fail(e))?;
351        self.buf.consume(len);
352        self.buf.extend_pin_to_pos();
353        self.info = info;
354        self.keep_alive = info.keep_alive;
355        self.decoder.start(info.framing);
356        self.state = ReqState::Body;
357        Ok(ServerEvent::Request(self.view()))
358    }
359
360    fn poll_body(&mut self) -> Result<ServerEvent<'_>, HttpError> {
361        let mut framing_bytes = 0;
362        let step = self.decoder.step(
363            self.buf.unread(),
364            self.buf.is_eof(),
365            &self.limits,
366            &mut self.trailers,
367            &mut framing_bytes,
368        );
369        self.buf.consume(framing_bytes);
370        match step.map_err(|e| self.fail(e))? {
371            Step::Data(n) => {
372                let start = self.buf.pos();
373                self.buf.consume(n);
374                Ok(ServerEvent::Body(self.buf.range(start, start + n)))
375            }
376            Step::Done => {
377                self.state = ReqState::Complete;
378                Ok(ServerEvent::RequestEnd)
379            }
380            Step::NeedMore => Ok(ServerEvent::NeedInput),
381        }
382    }
383
384    fn fail(&mut self, e: HttpError) -> HttpError {
385        self.state = ReqState::Failed;
386        self.keep_alive = false;
387        e
388    }
389
390    fn next_exchange(&mut self) {
391        self.buf.unpin();
392        self.buf.pin_at_pos();
393        self.scanner.reset();
394        self.resp = RespState::Idle;
395        self.info = RequestInfo::EMPTY;
396        self.continue_sent = false;
397        self.state = ReqState::Head;
398    }
399
400    /// Whether a response to the current request has been started.
401    #[cfg(feature = "std")]
402    pub(crate) fn response_started(&self) -> bool {
403        self.resp != RespState::Idle
404    }
405
406    /// Whether the current request's body has been read to its end: the
407    /// exchange is complete, or the request has no body at all (a response
408    /// given at [`ServerEvent::Request`] then leaves nothing unread).
409    fn body_read(&self) -> bool {
410        self.state == ReqState::Complete || (self.state == ReqState::Body && self.decoder.is_done())
411    }
412
413    fn view(&self) -> RequestHead<'_> {
414        RequestHead::new(
415            self.buf.from(self.buf.pin()),
416            &self.scanner.fields,
417            &self.info,
418        )
419    }
420
421    /// The current request's head, from its arrival until the next request
422    /// begins (still available after an upgrade).
423    ///
424    /// # Examples
425    ///
426    /// ```
427    /// use http_net::{ServerConn, ServerEvent};
428    ///
429    /// let mut conn = ServerConn::new();
430    /// let _ = conn.feed(b"PUT /f HTTP/1.1\r\nHost: a\r\nContent-Length: 1\r\n\r\nz");
431    /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
432    /// assert_eq!(conn.request().unwrap().path(), "/f");
433    /// ```
434    #[must_use]
435    pub fn request(&self) -> Option<RequestHead<'_>> {
436        match self.state {
437            ReqState::Body | ReqState::Complete | ReqState::Upgraded => Some(self.view()),
438            _ => None,
439        }
440    }
441
442    /// Whether a `101 Switching Protocols` (or a 2xx to `CONNECT`) was sent
443    /// and the connection now belongs to another protocol.
444    ///
445    /// # Examples
446    ///
447    /// ```
448    /// assert!(!http_net::ServerConn::new().is_upgraded());
449    /// ```
450    #[must_use]
451    pub fn is_upgraded(&self) -> bool {
452        self.state == ReqState::Upgraded
453    }
454
455    /// Input that arrived after the last message this connection parsed:
456    /// after [`ServerEvent::Upgraded`], the first bytes of the new protocol.
457    ///
458    /// # Examples
459    ///
460    /// ```
461    /// use http_net::{Response, ServerConn, ServerEvent};
462    ///
463    /// let mut conn = ServerConn::new();
464    /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\nConnection: upgrade\r\nUpgrade: x\r\n\r\n\x81\x00");
465    /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Request(_)));
466    /// assert!(matches!(conn.poll().unwrap(), ServerEvent::RequestEnd));
467    /// conn.respond(&Response::switching_protocols("x"), &mut Vec::new()).unwrap();
468    /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Upgraded));
469    /// assert_eq!(conn.remaining_input(), b"\x81\x00");
470    /// ```
471    #[must_use]
472    pub fn remaining_input(&self) -> &[u8] {
473        self.buf.unread()
474    }
475
476    /// Writes `response` for the current request into `out`.
477    ///
478    /// With a full body the response is complete. With a streamed body
479    /// ([`Response::chunked`], [`Response::content_length`]) follow with
480    /// [`send_body`](Self::send_body) and [`end_body`](Self::end_body).
481    /// After a parse error, one response may still be sent; it is marked
482    /// `connection: close`.
483    ///
484    /// # Errors
485    ///
486    /// - the first error recorded by the [`Response`] builder;
487    /// - [`HttpError::InvalidStatus`] for a status outside `100..=599`, or a
488    ///   1xx other than 101;
489    /// - [`HttpError::BodyNotAllowed`] for a body on 1xx, 204, 304, 101, or a
490    ///   2xx to `CONNECT`;
491    /// - [`HttpError::UpgradeNotOffered`] for a 101 whose protocol the
492    ///   request's `Upgrade` field did not offer;
493    /// - [`HttpError::InvalidState`] when there is no request to answer, a
494    ///   response was already started, or a 101 does not answer a complete
495    ///   upgrade request.
496    ///
497    /// # Examples
498    ///
499    /// ```
500    /// use http_net::{Response, ServerConn, ServerEvent};
501    ///
502    /// let mut conn = ServerConn::new();
503    /// let _ = conn.feed(b"HEAD / HTTP/1.1\r\nHost: a\r\n\r\n");
504    /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
505    /// let mut out = Vec::new();
506    /// conn.respond(&Response::text(200, "hello"), &mut out).unwrap();
507    /// // HEAD: the length is announced, the body is not sent.
508    /// assert!(out.windows(17).any(|w| w == b"content-length: 5"));
509    /// assert!(out.ends_with(b"\r\n\r\n"));
510    /// ```
511    pub fn respond(&mut self, response: &Response, out: &mut Vec<u8>) -> Result<(), HttpError> {
512        self.respond_dated(response, None, out)
513    }
514
515    pub(crate) fn respond_dated(
516        &mut self,
517        response: &Response,
518        date: Option<&[u8]>,
519        out: &mut Vec<u8>,
520    ) -> Result<(), HttpError> {
521        if let Some(e) = response.error() {
522            return Err(e);
523        }
524        let failed = self.state == ReqState::Failed;
525        match self.state {
526            ReqState::Body | ReqState::Complete | ReqState::Failed => {}
527            ReqState::Head => return Err(HttpError::InvalidState("no request to respond to")),
528            ReqState::Upgraded | ReqState::Closed => {
529                return Err(HttpError::InvalidState(
530                    "the connection is closed or upgraded",
531                ));
532            }
533        }
534        if self.resp != RespState::Idle {
535            return Err(HttpError::InvalidState("a response was already started"));
536        }
537        let status = response.status();
538        if !(100..=599).contains(&status) || ((100..200).contains(&status) && status != 101) {
539            return Err(HttpError::InvalidStatus);
540        }
541        let (method, version) = if failed {
542            (Method::Get, Version::Http11)
543        } else {
544            (self.info.method, self.info.version)
545        };
546        let bodiless = (100..200).contains(&status) || status == 204 || status == 304;
547        let tunnel = status == 101 || (method == Method::Connect && (200..300).contains(&status));
548        if bodiless || tunnel {
549            let empty = matches!(&response.body, OutBody::Full(b) if b.is_empty());
550            if !empty {
551                return Err(HttpError::BodyNotAllowed);
552            }
553        }
554        if tunnel {
555            let complete_upgrade =
556                self.body_read() && (self.info.upgrade || method == Method::Connect);
557            if !complete_upgrade || (status == 101 && !response.upgrade) || failed {
558                return Err(HttpError::InvalidState(
559                    "101 (or 2xx to CONNECT) must answer a complete upgrade request; \
560                     build it with Response::switching_protocols",
561                ));
562            }
563            // RFC 9110 section 7.8: never switch to a protocol the client
564            // did not offer.
565            if status == 101
566                && !response
567                    .upgrade_protocol()
568                    .is_some_and(|p| self.view().offers(p))
569            {
570                return Err(HttpError::UpgradeNotOffered);
571            }
572        }
573
574        let mut close = failed || response.close || !self.keep_alive || !self.body_read();
575        let head_only = method == Method::Head || bodiless || tunnel;
576        let (mut encoder, declared) = match &response.body {
577            OutBody::Full(b) => (
578                Encoder::Length {
579                    remaining: b.len() as u64,
580                },
581                Some(b.len() as u64),
582            ),
583            OutBody::Length(n) => (Encoder::Length { remaining: *n }, Some(*n)),
584            OutBody::Chunked if version == Version::Http10 => {
585                close = true;
586                (Encoder::CloseDelimited, None)
587            }
588            OutBody::Chunked => (Encoder::Chunked, None),
589        };
590
591        out.extend_from_slice(b"HTTP/1.1 ");
592        push_decimal(out, u64::from(status));
593        out.push(b' ');
594        out.extend_from_slice(reason_phrase(status).as_bytes());
595        out.extend_from_slice(b"\r\n");
596        if !(bodiless || tunnel) {
597            push_framing(out, encoder, declared);
598        }
599        if tunnel {
600            close = false;
601        } else if close {
602            out.extend_from_slice(b"connection: close\r\n");
603        } else if version == Version::Http10 {
604            out.extend_from_slice(b"connection: keep-alive\r\n");
605        }
606        if let Some(date) = date.filter(|_| !response.has_date) {
607            out.extend_from_slice(b"date: ");
608            out.extend_from_slice(date);
609            out.extend_from_slice(b"\r\n");
610        }
611        out.extend_from_slice(response.fields());
612        out.extend_from_slice(b"\r\n");
613
614        if head_only {
615            encoder = Encoder::Discard;
616        }
617        self.keep_alive = !close;
618        match &response.body {
619            OutBody::Full(b) => {
620                encoder.write(b, out)?;
621                self.resp = RespState::Sent;
622            }
623            _ => self.resp = RespState::Streaming(encoder),
624        }
625        if tunnel {
626            self.state = ReqState::Upgraded;
627        } else if failed {
628            self.state = ReqState::Closed;
629        }
630        Ok(())
631    }
632
633    /// Writes `HTTP/1.1 100 Continue` into `out`: the answer to
634    /// [`RequestHead::expects_continue`](crate::RequestHead::expects_continue)
635    /// that tells the client to send the body.
636    ///
637    /// RFC 9110 section 10.1.1 requires a server that receives
638    /// `Expect: 100-continue` to send either this or a final response before
639    /// waiting for the body; clients otherwise stall (curl for one second,
640    /// some indefinitely). Call it after [`ServerEvent::Request`], once the
641    /// head has been judged acceptable.
642    ///
643    /// # Errors
644    ///
645    /// [`HttpError::InvalidState`] unless the current request is HTTP/1.1,
646    /// its body has not been read yet, no response has been started, and
647    /// `100 Continue` has not already been sent for it. RFC 9110 section
648    /// 15.2 forbids any 1xx to an HTTP/1.0 client.
649    ///
650    /// # Examples
651    ///
652    /// ```
653    /// use http_net::{ServerConn, ServerEvent};
654    ///
655    /// let mut conn = ServerConn::new();
656    /// let _ = conn.feed(b"PUT /f HTTP/1.1\r\nHost: a\r\nExpect: 100-continue\r\nContent-Length: 2\r\n\r\n");
657    /// let ServerEvent::Request(req) = conn.poll()? else { unreachable!() };
658    /// assert!(req.expects_continue());
659    /// let mut out = Vec::new();
660    /// conn.send_continue(&mut out)?;
661    /// assert_eq!(out, b"HTTP/1.1 100 Continue\r\n\r\n");
662    /// # Ok::<(), http_net::HttpError>(())
663    /// ```
664    pub fn send_continue(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError> {
665        if self.state != ReqState::Body
666            || self.decoder.is_done()
667            || self.resp != RespState::Idle
668            || self.info.version != Version::Http11
669            || self.continue_sent
670        {
671            return Err(HttpError::InvalidState(
672                "100 Continue answers an HTTP/1.1 request whose body has not been read, \
673                 once, before the final response",
674            ));
675        }
676        self.continue_sent = true;
677        out.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
678        Ok(())
679    }
680
681    /// Writes body bytes of a streamed response into `out`. For a `HEAD`
682    /// request the bytes are dropped.
683    ///
684    /// # Errors
685    ///
686    /// [`HttpError::BodyLengthMismatch`] past the declared
687    /// [`Response::content_length`]; [`HttpError::InvalidState`] when no
688    /// streamed response is in progress.
689    ///
690    /// # Examples
691    ///
692    /// ```
693    /// use http_net::{Response, ServerConn, ServerEvent};
694    ///
695    /// let mut conn = ServerConn::new();
696    /// let _ = conn.feed(b"GET /log HTTP/1.1\r\nHost: a\r\n\r\n");
697    /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
698    /// let mut out = Vec::new();
699    /// conn.respond(&Response::new(200).chunked(), &mut out).unwrap();
700    /// conn.send_body(b"line 1\n", &mut out).unwrap();
701    /// conn.end_body(&mut out).unwrap();
702    /// assert!(out.ends_with(b"7\r\nline 1\n\r\n0\r\n\r\n"));
703    /// ```
704    pub fn send_body(&mut self, data: &[u8], out: &mut Vec<u8>) -> Result<(), HttpError> {
705        match &mut self.resp {
706            RespState::Streaming(encoder) => encoder.write(data, out),
707            _ => Err(HttpError::InvalidState("no streamed response in progress")),
708        }
709    }
710
711    /// Ends a streamed response body (the last chunk for chunked encoding).
712    ///
713    /// # Errors
714    ///
715    /// [`HttpError::BodyLengthMismatch`] when fewer bytes than the declared
716    /// length were sent; [`HttpError::InvalidState`] when no streamed
717    /// response is in progress.
718    ///
719    /// # Examples
720    ///
721    /// ```
722    /// use http_net::{HttpError, Response, ServerConn, ServerEvent};
723    ///
724    /// let mut conn = ServerConn::new();
725    /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
726    /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
727    /// let mut out = Vec::new();
728    /// conn.respond(&Response::new(200).content_length(3), &mut out).unwrap();
729    /// conn.send_body(b"ab", &mut out).unwrap();
730    /// assert_eq!(conn.end_body(&mut out), Err(HttpError::BodyLengthMismatch));
731    /// ```
732    pub fn end_body(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError> {
733        match &mut self.resp {
734            RespState::Streaming(encoder) => {
735                encoder.finish(out)?;
736                if *encoder == Encoder::CloseDelimited {
737                    self.keep_alive = false;
738                }
739                self.resp = RespState::Sent;
740                Ok(())
741            }
742            _ => Err(HttpError::InvalidState("no streamed response in progress")),
743        }
744    }
745}
746
747#[cfg(test)]
748mod tests {
749    use alloc::vec;
750
751    use super::*;
752
753    fn events(conn: &mut ServerConn) -> Vec<alloc::string::String> {
754        let mut log = Vec::new();
755        loop {
756            match conn.poll() {
757                Ok(ServerEvent::Request(r)) => log.push(alloc::format!("req {}", r.target())),
758                Ok(ServerEvent::Body(b)) => log.push(alloc::format!("body {}", b.len())),
759                Ok(ServerEvent::RequestEnd) => {
760                    log.push("end".into());
761                    return log;
762                }
763                Ok(other) => {
764                    log.push(alloc::format!("{other:?}"));
765                    return log;
766                }
767                Err(e) => {
768                    log.push(alloc::format!("err {e:?}"));
769                    return log;
770                }
771            }
772        }
773    }
774
775    #[test]
776    fn test_early_response_closes_connection() {
777        let mut conn = ServerConn::new();
778        let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nContent-Length: 10\r\n\r\nab");
779        assert!(matches!(conn.poll(), Ok(ServerEvent::Request(_))));
780        let mut out = Vec::new();
781        conn.respond(&Response::new(413), &mut out).unwrap();
782        assert!(out.windows(17).any(|w| w == b"connection: close"));
783        assert!(matches!(conn.poll(), Ok(ServerEvent::Closed)));
784    }
785
786    #[test]
787    fn test_respond_after_failure_is_once_and_closes() {
788        let mut conn = ServerConn::new();
789        let _ = conn.feed(b"GET / HTTP/1.1\r\n\r\n");
790        assert_eq!(conn.poll().unwrap_err(), HttpError::MissingHost);
791        let mut out = Vec::new();
792        conn.respond(&Response::new(400), &mut out).unwrap();
793        assert!(out.starts_with(b"HTTP/1.1 400 Bad Request\r\n"));
794        assert!(conn.respond(&Response::new(400), &mut out).is_err());
795        assert!(matches!(conn.poll(), Ok(ServerEvent::Closed)));
796    }
797
798    #[test]
799    fn test_state_errors() {
800        let mut conn = ServerConn::new();
801        let mut out = Vec::new();
802        assert!(matches!(
803            conn.respond(&Response::new(200), &mut out),
804            Err(HttpError::InvalidState(_))
805        ));
806        assert!(matches!(
807            conn.send_body(b"x", &mut out),
808            Err(HttpError::InvalidState(_))
809        ));
810        assert!(matches!(
811            conn.end_body(&mut out),
812            Err(HttpError::InvalidState(_))
813        ));
814        let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
815        assert_eq!(events(&mut conn), vec!["req /", "end"]);
816        assert_eq!(
817            conn.respond(&Response::new(99), &mut out),
818            Err(HttpError::InvalidStatus)
819        );
820        assert_eq!(
821            conn.respond(&Response::new(100), &mut out),
822            Err(HttpError::InvalidStatus)
823        );
824        assert_eq!(
825            conn.respond(&Response::new(204).body(&b"x"[..]), &mut out),
826            Err(HttpError::BodyNotAllowed)
827        );
828        assert!(matches!(
829            conn.respond(&Response::switching_protocols("x"), &mut out),
830            Err(HttpError::InvalidState(_))
831        ));
832        conn.respond(&Response::new(204), &mut out).unwrap();
833        assert!(matches!(
834            conn.respond(&Response::new(200), &mut out),
835            Err(HttpError::InvalidState(_))
836        ));
837    }
838
839    #[test]
840    fn test_http10_keep_alive_and_chunked_fallback() {
841        let mut conn = ServerConn::new();
842        let _ = conn.feed(b"GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n");
843        assert_eq!(events(&mut conn), vec!["req /", "end"]);
844        let mut out = Vec::new();
845        conn.respond(&Response::text(200, "x"), &mut out).unwrap();
846        assert!(out.windows(22).any(|w| w == b"connection: keep-alive"));
847        assert!(matches!(conn.poll(), Ok(ServerEvent::NeedInput)));
848
849        let _ = conn.feed(b"GET / HTTP/1.0\r\n\r\n");
850        assert_eq!(events(&mut conn), vec!["req /", "end"]);
851        let mut out = Vec::new();
852        conn.respond(&Response::new(200).chunked(), &mut out)
853            .unwrap();
854        conn.send_body(b"abc", &mut out).unwrap();
855        conn.end_body(&mut out).unwrap();
856        assert!(out.ends_with(b"\r\n\r\nabc"));
857        assert!(!out.windows(17).any(|w| w == b"transfer-encoding"));
858        assert!(matches!(conn.poll(), Ok(ServerEvent::Closed)));
859    }
860
861    fn upgrade_request(conn: &mut ServerConn, offer: &str) {
862        let msg = alloc::format!(
863            "GET / HTTP/1.1\r\nHost: a\r\nConnection: upgrade\r\nUpgrade: {offer}\r\n\r\n"
864        );
865        let _ = conn.feed(msg.as_bytes());
866        assert_eq!(events(conn), vec!["req /", "end"]);
867    }
868
869    #[test]
870    fn test_switching_protocols_must_name_an_offered_protocol() {
871        let mut conn = ServerConn::new();
872        upgrade_request(&mut conn, "websocket/13, foo/2");
873        let mut out = Vec::new();
874        // `foo` alone would match `foo/2`: a name without a version
875        // answers an offer of that name with any version.
876        for refused in ["ftp", "foo/3", "websocket/12", "h2c"] {
877            assert_eq!(
878                conn.respond(&Response::switching_protocols(refused), &mut out),
879                Err(HttpError::UpgradeNotOffered),
880                "{refused}"
881            );
882            assert!(out.is_empty());
883            assert!(!conn.is_upgraded());
884        }
885        conn.respond(&Response::switching_protocols("WebSocket"), &mut out)
886            .unwrap();
887        assert!(conn.is_upgraded());
888        assert!(out.windows(18).any(|w| w == b"upgrade: WebSocket"));
889    }
890
891    #[test]
892    fn test_refused_switch_leaves_a_normal_response_possible() {
893        let mut conn = ServerConn::new();
894        upgrade_request(&mut conn, "websocket");
895        let mut out = Vec::new();
896        assert_eq!(
897            conn.respond(&Response::switching_protocols("irc"), &mut out),
898            Err(HttpError::UpgradeNotOffered)
899        );
900        conn.respond(&Response::new(426), &mut out).unwrap();
901        assert!(out.starts_with(b"HTTP/1.1 426 Upgrade Required\r\n"));
902        assert!(matches!(conn.poll(), Ok(ServerEvent::NeedInput)));
903    }
904
905    #[test]
906    fn test_h2c_only_offer_is_served_as_http11() {
907        let mut conn = ServerConn::new();
908        let _ = conn.feed(
909            b"GET / HTTP/1.1\r\nHost: a\r\nConnection: Upgrade, HTTP2-Settings\r\nUpgrade: h2c\r\nHTTP2-Settings: AAMAAABkAAQAoAAA\r\n\r\n",
910        );
911        assert!(matches!(conn.poll(), Ok(ServerEvent::Request(r)) if !r.is_upgrade()));
912        assert!(matches!(conn.poll(), Ok(ServerEvent::RequestEnd)));
913        let mut out = Vec::new();
914        assert!(matches!(
915            conn.respond(&Response::switching_protocols("websocket"), &mut out),
916            Err(HttpError::InvalidState(_))
917        ));
918        conn.respond(&Response::new(200), &mut out).unwrap();
919        assert!(matches!(conn.poll(), Ok(ServerEvent::NeedInput)));
920    }
921
922    #[test]
923    fn test_unregistered_status_keeps_the_space_before_an_empty_reason() {
924        let mut conn = ServerConn::new();
925        let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
926        assert_eq!(events(&mut conn), vec!["req /", "end"]);
927        let mut out = Vec::new();
928        conn.respond(&Response::new(299), &mut out).unwrap();
929        assert!(out.starts_with(b"HTTP/1.1 299 \r\n"));
930    }
931
932    #[test]
933    fn test_connect_tunnel() {
934        let mut conn = ServerConn::new();
935        let _ = conn.feed(b"CONNECT example.com:443 HTTP/1.1\r\nHost: example.com:443\r\n\r\nTLS");
936        assert_eq!(events(&mut conn), vec!["req example.com:443", "end"]);
937        let mut out = Vec::new();
938        conn.respond(&Response::new(200), &mut out).unwrap();
939        assert_eq!(out, b"HTTP/1.1 200 OK\r\n\r\n");
940        assert!(matches!(conn.poll(), Ok(ServerEvent::Upgraded)));
941        assert_eq!(conn.remaining_input(), b"TLS");
942        assert!(conn.request().is_some());
943    }
944}