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