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}