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}