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 date::HttpDate,
9 error::HttpError,
10 head::{
11 HeadKind, HeadScanner, Headers, RequestHead, RequestInfo, Scan, Version, interpret_request,
12 },
13 limits::Limits,
14 message::{OutBody, Response, check_trailers, push_last_chunk_with_trailers},
15 method::Method,
16 status::reason_phrase,
17 syntax::push_decimal,
18};
19
20/// What a [`ServerConn`] has for the caller after [`poll`](ServerConn::poll).
21///
22/// # Examples
23///
24/// ```
25/// use http_net::{Response, ServerConn, ServerEvent};
26///
27/// let mut conn = ServerConn::new();
28/// let mut out = Vec::new();
29/// let _ = conn.feed(b"POST /echo HTTP/1.1\r\nHost: a\r\nContent-Length: 2\r\n\r\nhi");
30/// let mut body = Vec::new();
31/// loop {
32/// match conn.poll().unwrap() {
33/// ServerEvent::Request(req) => assert_eq!(req.path(), "/echo"),
34/// ServerEvent::Body(chunk) => body.extend_from_slice(chunk),
35/// ServerEvent::RequestEnd => {
36/// conn.respond(&Response::new(200).body(body.clone()), &mut out).unwrap();
37/// }
38/// ServerEvent::NeedInput => break,
39/// other => panic!("{other:?}"),
40/// }
41/// }
42/// assert!(out.ends_with(b"\r\n\r\nhi"));
43/// ```
44#[non_exhaustive]
45#[derive(Debug)]
46pub enum ServerEvent<'a> {
47 /// A request head arrived. Its body (if any) follows as
48 /// [`Body`](ServerEvent::Body) events, then
49 /// [`RequestEnd`](ServerEvent::RequestEnd). A response may be sent from
50 /// this point on; sending it while body bytes are still unread closes
51 /// the connection afterwards (a request without a body stays
52 /// keep-alive). If the head
53 /// [`expects_continue`](RequestHead::expects_continue), answer with
54 /// [`send_continue`](ServerConn::send_continue) or a final response
55 /// before waiting for the body.
56 Request(RequestHead<'a>),
57 /// A run of body bytes, after chunked decoding.
58 Body(&'a [u8]),
59 /// The request's trailer fields, just before
60 /// [`RequestEnd`](ServerEvent::RequestEnd): only with
61 /// [`set_report_trailers(true)`](ServerConn::set_report_trailers) and a
62 /// non-empty trailer section. They never change how the request was
63 /// framed. The values of credential fields are redacted in `Debug`.
64 Trailers(Headers<'a>),
65 /// The request is complete. Send the response if it has not been sent.
66 RequestEnd,
67 /// More input is needed: read from the socket, then
68 /// [`feed`](ServerConn::feed) (or [`read_buf`](ServerConn::read_buf) and
69 /// [`commit`](ServerConn::commit)), or [`feed_eof`](ServerConn::feed_eof)
70 /// if the peer closed.
71 NeedInput,
72 /// The request is complete and its response has not been finished yet.
73 /// Pipelined requests wait in the buffer until it is.
74 AwaitingResponse,
75 /// A `101 Switching Protocols` (or a 2xx to `CONNECT`) was sent: the
76 /// connection now belongs to the new protocol. Bytes that already arrived
77 /// for it are in [`remaining_input`](ServerConn::remaining_input).
78 Upgraded,
79 /// The connection is finished: flush any output, then close the socket.
80 Closed,
81}
82
83#[derive(Clone, Copy, Debug, PartialEq, Eq)]
84enum ReqState {
85 Head,
86 Body,
87 Complete,
88 Upgraded,
89 Failed,
90 Closed,
91}
92
93#[derive(Clone, Copy, Debug, PartialEq, Eq)]
94enum RespState {
95 Idle,
96 Streaming(Encoder),
97 Sent,
98}
99
100/// The phase of a connection, for drivers that run header-read, request,
101/// and response deadlines: what [`ServerConn::progress`] and
102/// [`ClientConn::progress`](crate::ClientConn::progress) report.
103///
104/// # Examples
105///
106/// ```
107/// use http_net::{Progress, ServerConn, ServerEvent};
108///
109/// let mut conn = ServerConn::new();
110/// assert_eq!(conn.progress(), Progress::Idle);
111/// let _ = conn.feed(b"GET / HTTP/1.1\r\n");
112/// assert!(matches!(conn.poll(), Ok(ServerEvent::NeedInput)));
113/// assert_eq!(conn.progress(), Progress::Head);
114/// ```
115#[non_exhaustive]
116#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
117pub enum Progress {
118 /// Between messages: no byte of the next one has been seen. Idle
119 /// keep-alive time belongs to this phase, so a request deadline should
120 /// not start here.
121 Idle,
122 /// Some bytes of a head have arrived; the head is not complete.
123 Head,
124 /// The head is complete and body bytes are still to come.
125 Body,
126 /// Server: the request is complete (or has no body left to read) and its
127 /// response is not finished. Client: the request was sent and nothing of
128 /// the response has arrived.
129 AwaitingResponse,
130 /// A streamed body is being written: the response on a server, the
131 /// request on a client.
132 WritingBody,
133 /// The connection belongs to another protocol.
134 Upgraded,
135 /// The connection is finished (or will be once the last response is
136 /// written).
137 Closed,
138}
139
140/// The server side of one HTTP/1.1 connection: a sans-IO state machine.
141///
142/// The connection owns a bounded input buffer. The caller moves bytes
143/// between it and the socket: input in through [`feed`](Self::feed) (or
144/// [`read_buf`](Self::read_buf) + [`commit`](Self::commit) to read straight
145/// into the buffer), events out through [`poll`](Self::poll), responses out
146/// through [`respond`](Self::respond) into a caller-owned `Vec<u8>`.
147///
148/// Requests are handled one at a time, in order. Keep-alive is automatic:
149/// after a response is finished the next request (possibly already buffered,
150/// when the client pipelines) is parsed on the next `poll`. A connection
151/// that must close (the client asked, HTTP/1.0 without keep-alive, the
152/// response was sent before the request body was read, or a parse error)
153/// reports [`ServerEvent::Closed`] once its last response is written.
154///
155/// Steady state allocates nothing: the input buffer and the field index are
156/// reused across requests.
157///
158/// # Examples
159///
160/// ```
161/// use http_net::{Response, ServerConn, ServerEvent};
162///
163/// let mut conn = ServerConn::new();
164/// let mut out = Vec::new();
165/// // Two pipelined requests in one read.
166/// 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");
167/// let mut paths = Vec::new();
168/// loop {
169/// match conn.poll().unwrap() {
170/// ServerEvent::Request(req) => paths.push(req.path().to_string()),
171/// ServerEvent::RequestEnd => conn.respond(&Response::text(200, "ok"), &mut out).unwrap(),
172/// ServerEvent::NeedInput => break,
173/// other => panic!("{other:?}"),
174/// }
175/// }
176/// assert_eq!(paths, ["/a", "/b"]);
177/// ```
178pub struct ServerConn {
179 buf: Buffer,
180 limits: Limits,
181 scanner: HeadScanner,
182 trailers: HeadScanner,
183 decoder: Decoder,
184 info: RequestInfo,
185 state: ReqState,
186 resp: RespState,
187 keep_alive: bool,
188 /// Cleared by `set_keep_alive(false)`: every later response closes.
189 allow_keep_alive: bool,
190 continue_sent: bool,
191 /// A body byte of the current request was delivered.
192 body_seen: bool,
193 /// The response being streamed was declared chunked (trailers allowed,
194 /// even if an HTTP/1.0 client forced a close-delimited body).
195 resp_chunked: bool,
196 report_trailers: bool,
197 requests_served: u64,
198}
199
200impl Default for ServerConn {
201 fn default() -> Self {
202 Self::new()
203 }
204}
205
206impl core::fmt::Debug for ServerConn {
207 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
208 f.debug_struct("ServerConn")
209 .field("state", &self.state)
210 .field("response", &self.resp)
211 .field("buffered", &self.buf.unread().len())
212 .field("limits", &self.limits)
213 .finish()
214 }
215}
216
217impl ServerConn {
218 /// A connection with the default [`Limits`].
219 ///
220 /// # Examples
221 ///
222 /// ```
223 /// let conn = http_net::ServerConn::new();
224 /// assert!(conn.request().is_none());
225 /// ```
226 #[must_use]
227 pub fn new() -> Self {
228 Self::with_limits(Limits::new())
229 }
230
231 /// A connection enforcing `limits`.
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// use http_net::{HttpError, Limits, ServerConn};
237 ///
238 /// let mut conn = ServerConn::with_limits(Limits::new().with_max_body(4));
239 /// let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\n");
240 /// assert_eq!(conn.poll().unwrap_err(), HttpError::BodyTooLarge);
241 /// ```
242 #[must_use]
243 pub fn with_limits(limits: Limits) -> Self {
244 let mut buf = Buffer::new(limits.buffer_capacity());
245 buf.pin_at_pos();
246 Self {
247 buf,
248 limits,
249 scanner: HeadScanner::new(),
250 trailers: HeadScanner::new(),
251 decoder: Decoder::new(),
252 info: RequestInfo::EMPTY,
253 state: ReqState::Head,
254 resp: RespState::Idle,
255 keep_alive: false,
256 allow_keep_alive: true,
257 continue_sent: false,
258 body_seen: false,
259 resp_chunked: false,
260 report_trailers: false,
261 requests_served: 0,
262 }
263 }
264
265 /// The limits this connection enforces.
266 ///
267 /// # Examples
268 ///
269 /// ```
270 /// assert_eq!(http_net::ServerConn::new().limits(), &http_net::Limits::new());
271 /// ```
272 #[must_use]
273 pub fn limits(&self) -> &Limits {
274 &self.limits
275 }
276
277 /// Copies as much of `bytes` into the input buffer as fits and returns
278 /// how many bytes were taken. Fewer than `bytes.len()` means the buffer
279 /// is full: [`poll`](Self::poll) until it asks for input, then feed the
280 /// rest.
281 ///
282 /// # Examples
283 ///
284 /// ```
285 /// let mut conn = http_net::ServerConn::new();
286 /// assert_eq!(conn.feed(b"GET / HTTP/1.1\r\n"), 16);
287 /// ```
288 #[must_use = "bytes beyond the returned count were not taken"]
289 pub fn feed(&mut self, bytes: &[u8]) -> usize {
290 self.buf.feed(bytes)
291 }
292
293 /// Spare space at the end of the input buffer, for reading from a
294 /// socket without an intermediate copy. Follow with
295 /// [`commit`](Self::commit). It is empty only when the buffer is full of
296 /// input the parser has not been asked to process yet; poll first.
297 ///
298 /// # Examples
299 ///
300 /// ```
301 /// let mut conn = http_net::ServerConn::new();
302 /// let spare = conn.read_buf();
303 /// let msg = b"GET / HTTP/1.1\r\nHost: a\r\n\r\n";
304 /// spare[..msg.len()].copy_from_slice(msg);
305 /// conn.commit(msg.len());
306 /// assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::Request(_))));
307 /// ```
308 pub fn read_buf(&mut self) -> &mut [u8] {
309 self.buf.spare()
310 }
311
312 /// Records that `n` bytes were written into [`read_buf`](Self::read_buf).
313 ///
314 /// # Examples
315 ///
316 /// ```
317 /// let mut conn = http_net::ServerConn::new();
318 /// conn.read_buf()[0] = b'G';
319 /// conn.commit(1);
320 /// assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::NeedInput)));
321 /// ```
322 pub fn commit(&mut self, n: usize) {
323 self.buf.commit(n);
324 }
325
326 /// Records that the peer closed its sending side. A connection idle
327 /// between requests then reports [`ServerEvent::Closed`]; one in the
328 /// middle of a request reports [`HttpError::UnexpectedEof`].
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// let mut conn = http_net::ServerConn::new();
334 /// conn.feed_eof();
335 /// assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::Closed)));
336 /// ```
337 pub fn feed_eof(&mut self) {
338 self.buf.set_eof();
339 }
340
341 /// Advances the parser and reports what happened. Call it until it
342 /// returns [`ServerEvent::NeedInput`], [`ServerEvent::AwaitingResponse`],
343 /// [`ServerEvent::Upgraded`], or [`ServerEvent::Closed`].
344 ///
345 /// # Errors
346 ///
347 /// Any [`HttpError`] parse error. The connection is then finished: send
348 /// one error response (see [`HttpError::status`]) with
349 /// [`respond`](Self::respond), flush, and close.
350 ///
351 /// # Examples
352 ///
353 /// ```
354 /// use http_net::{HttpError, ServerConn};
355 ///
356 /// let mut conn = ServerConn::new();
357 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n folded\r\n\r\n");
358 /// assert_eq!(conn.poll().unwrap_err(), HttpError::ObsFold);
359 /// ```
360 pub fn poll(&mut self) -> Result<ServerEvent<'_>, HttpError> {
361 loop {
362 match self.state {
363 ReqState::Head => return self.poll_head(),
364 ReqState::Body => {
365 if self.resp == RespState::Sent && !self.decoder.is_read() {
366 // Answered before the body was read: the rest of the
367 // body cannot be trusted to frame the next request.
368 self.state = ReqState::Closed;
369 return Ok(ServerEvent::Closed);
370 }
371 return self.poll_body();
372 }
373 ReqState::Complete => {
374 if self.resp != RespState::Sent {
375 return Ok(ServerEvent::AwaitingResponse);
376 }
377 if !self.keep_alive {
378 self.state = ReqState::Closed;
379 return Ok(ServerEvent::Closed);
380 }
381 self.next_exchange();
382 }
383 ReqState::Upgraded => return Ok(ServerEvent::Upgraded),
384 ReqState::Failed | ReqState::Closed => return Ok(ServerEvent::Closed),
385 }
386 }
387 }
388
389 fn poll_head(&mut self) -> Result<ServerEvent<'_>, HttpError> {
390 let start = self.buf.pin();
391 let msg = self.buf.from(start);
392 let progress = self
393 .scanner
394 .advance(msg, &self.limits, HeadKind::Request, true)
395 .map_err(|e| self.fail(e))?;
396 let len = match progress {
397 Scan::Partial if self.buf.is_eof() => {
398 if self.buf.from(start).is_empty() {
399 self.state = ReqState::Closed;
400 return Ok(ServerEvent::Closed);
401 }
402 return Err(self.fail(HttpError::UnexpectedEof));
403 }
404 Scan::Partial => return Ok(ServerEvent::NeedInput),
405 Scan::Done(len) => len,
406 };
407 let info = interpret_request(
408 self.buf.from(start),
409 self.scanner.start_line(),
410 &self.scanner.fields,
411 &self.limits,
412 )
413 .map_err(|e| self.fail(e))?;
414 self.buf.consume(len);
415 self.buf.extend_pin_to_pos();
416 self.info = info;
417 self.keep_alive = info.keep_alive;
418 self.decoder.start(info.framing);
419 self.state = ReqState::Body;
420 Ok(ServerEvent::Request(self.view()))
421 }
422
423 fn poll_body(&mut self) -> Result<ServerEvent<'_>, HttpError> {
424 let mut framing_bytes = 0;
425 let step = self.decoder.step(
426 self.buf.unread(),
427 self.buf.is_eof(),
428 &self.limits,
429 &mut self.trailers,
430 self.report_trailers,
431 &mut framing_bytes,
432 );
433 self.buf.consume(framing_bytes);
434 match step.map_err(|e| self.fail(e))? {
435 Step::Data(n) => {
436 let start = self.buf.pos();
437 self.buf.consume(n);
438 self.body_seen = true;
439 Ok(ServerEvent::Body(self.buf.range(start, start + n)))
440 }
441 Step::Trailers => Ok(ServerEvent::Trailers(Headers::new(
442 self.buf.unread(),
443 &self.trailers.fields,
444 ))),
445 Step::Done => {
446 self.state = ReqState::Complete;
447 Ok(ServerEvent::RequestEnd)
448 }
449 Step::NeedMore => Ok(ServerEvent::NeedInput),
450 }
451 }
452
453 fn fail(&mut self, e: HttpError) -> HttpError {
454 self.state = ReqState::Failed;
455 self.keep_alive = false;
456 e
457 }
458
459 fn next_exchange(&mut self) {
460 self.buf.unpin();
461 self.buf.pin_at_pos();
462 self.scanner.reset();
463 self.resp = RespState::Idle;
464 self.info = RequestInfo::EMPTY;
465 self.continue_sent = false;
466 self.body_seen = false;
467 self.state = ReqState::Head;
468 }
469
470 /// Whether a response to the current request has been started.
471 #[cfg(feature = "std")]
472 pub(crate) fn response_started(&self) -> bool {
473 self.resp != RespState::Idle
474 }
475
476 /// Whether the current request's body has been read to its end: the
477 /// exchange is complete, or the request has no body at all (a response
478 /// given at [`ServerEvent::Request`] then leaves nothing unread).
479 fn body_read(&self) -> bool {
480 self.state == ReqState::Complete || (self.state == ReqState::Body && self.decoder.is_read())
481 }
482
483 fn view(&self) -> RequestHead<'_> {
484 RequestHead::new(
485 self.buf.from(self.buf.pin()),
486 &self.scanner.fields,
487 &self.info,
488 )
489 }
490
491 /// The current request's head, from its arrival until the next request
492 /// begins (still available after an upgrade).
493 ///
494 /// # Examples
495 ///
496 /// ```
497 /// use http_net::{ServerConn, ServerEvent};
498 ///
499 /// let mut conn = ServerConn::new();
500 /// let _ = conn.feed(b"PUT /f HTTP/1.1\r\nHost: a\r\nContent-Length: 1\r\n\r\nz");
501 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
502 /// assert_eq!(conn.request().unwrap().path(), "/f");
503 /// ```
504 #[must_use]
505 pub fn request(&self) -> Option<RequestHead<'_>> {
506 match self.state {
507 ReqState::Body | ReqState::Complete | ReqState::Upgraded => Some(self.view()),
508 _ => None,
509 }
510 }
511
512 /// Whether a `101 Switching Protocols` (or a 2xx to `CONNECT`) was sent
513 /// and the connection now belongs to another protocol.
514 ///
515 /// # Examples
516 ///
517 /// ```
518 /// assert!(!http_net::ServerConn::new().is_upgraded());
519 /// ```
520 #[must_use]
521 pub fn is_upgraded(&self) -> bool {
522 self.state == ReqState::Upgraded
523 }
524
525 /// Input that arrived after the last message this connection parsed:
526 /// after [`ServerEvent::Upgraded`], the first bytes of the new protocol.
527 ///
528 /// # Examples
529 ///
530 /// ```
531 /// use http_net::{Response, ServerConn, ServerEvent};
532 ///
533 /// let mut conn = ServerConn::new();
534 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\nConnection: upgrade\r\nUpgrade: x\r\n\r\n\x81\x00");
535 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Request(_)));
536 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::RequestEnd));
537 /// conn.respond(&Response::switching_protocols("x"), &mut Vec::new()).unwrap();
538 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Upgraded));
539 /// assert_eq!(conn.remaining_input(), b"\x81\x00");
540 /// ```
541 #[must_use]
542 pub fn remaining_input(&self) -> &[u8] {
543 self.buf.unread()
544 }
545
546 /// Writes `response` for the current request into `out`.
547 ///
548 /// With a full body the response is complete. With a streamed body
549 /// ([`Response::chunked`], [`Response::content_length`]) follow with
550 /// [`send_body`](Self::send_body) and [`end_body`](Self::end_body).
551 /// After a parse error, one response may still be sent; it is marked
552 /// `connection: close`.
553 ///
554 /// # Errors
555 ///
556 /// - the first error recorded by the [`Response`] builder;
557 /// - [`HttpError::InvalidStatus`] for a status outside `100..=599`, or a
558 /// 1xx other than 101;
559 /// - [`HttpError::BodyNotAllowed`] for a body on 1xx, 204, 304, 101, or a
560 /// 2xx to `CONNECT`;
561 /// - [`HttpError::UpgradeNotOffered`] for a 101 whose protocol the
562 /// request's `Upgrade` field did not offer;
563 /// - [`HttpError::InvalidState`] when there is no request to answer, a
564 /// response was already started, or a 101 does not answer a complete
565 /// upgrade request.
566 ///
567 /// # Examples
568 ///
569 /// ```
570 /// use http_net::{Response, ServerConn, ServerEvent};
571 ///
572 /// let mut conn = ServerConn::new();
573 /// let _ = conn.feed(b"HEAD / HTTP/1.1\r\nHost: a\r\n\r\n");
574 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
575 /// let mut out = Vec::new();
576 /// conn.respond(&Response::text(200, "hello"), &mut out).unwrap();
577 /// // HEAD: the length is announced, the body is not sent.
578 /// assert!(out.windows(17).any(|w| w == b"content-length: 5"));
579 /// assert!(out.ends_with(b"\r\n\r\n"));
580 /// ```
581 pub fn respond(&mut self, response: &Response, out: &mut Vec<u8>) -> Result<(), HttpError> {
582 self.respond_dated(response, None, out)
583 }
584
585 /// As [`respond`](Self::respond), adding `date: <date>` unless the
586 /// response set its own `date` field. Keep a
587 /// [`DateCache`](crate::DateCache) per driver thread and pass
588 /// `cache.update(now)`: the value is reformatted once per second, not
589 /// once per response.
590 ///
591 /// # Errors
592 ///
593 /// As [`respond`](Self::respond).
594 ///
595 /// # Examples
596 ///
597 /// ```
598 /// use http_net::{DateCache, Response, ServerConn, ServerEvent};
599 ///
600 /// let mut dates = DateCache::new();
601 /// let mut conn = ServerConn::new();
602 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
603 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
604 /// let mut out = Vec::new();
605 /// conn.respond_with_date(&Response::new(204), dates.update(784_111_777), &mut out)?;
606 /// assert!(out.windows(35).any(|w| w == b"date: Sun, 06 Nov 1994 08:49:37 GMT"));
607 /// # Ok::<(), http_net::HttpError>(())
608 /// ```
609 pub fn respond_with_date(
610 &mut self,
611 response: &Response,
612 date: &HttpDate,
613 out: &mut Vec<u8>,
614 ) -> Result<(), HttpError> {
615 self.respond_dated(response, Some(date.as_bytes()), out)
616 }
617
618 /// Writes an interim (1xx) response other than `100` and `101`, for
619 /// example `103 Early Hints` with `link` fields, before the final
620 /// response. It may be sent more than once, for any request method,
621 /// at any point before the final response starts (RFC 9110 section
622 /// 15.2), but never to an HTTP/1.0 client. Only the status and the
623 /// fields are written; an interim response has no body and does not
624 /// change the connection.
625 ///
626 /// # Errors
627 ///
628 /// The first error recorded by the builder; [`HttpError::InvalidStatus`]
629 /// unless the status is in `102..=199`; [`HttpError::BodyNotAllowed`]
630 /// for a body; [`HttpError::InterimNotAllowed`] for an HTTP/1.0 request
631 /// or once the final response has started; [`HttpError::InvalidState`]
632 /// when there is no request (or after a parse error, an upgrade, or the
633 /// end of the connection).
634 ///
635 /// # Examples
636 ///
637 /// ```
638 /// use http_net::{Response, ServerConn, ServerEvent};
639 ///
640 /// let mut conn = ServerConn::new();
641 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
642 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
643 /// let mut out = Vec::new();
644 /// let hints = Response::new(103).header("link", "</style.css>; rel=preload; as=style");
645 /// conn.send_informational(&hints, &mut out)?;
646 /// conn.respond(&Response::text(200, "page"), &mut out)?;
647 /// assert!(out.starts_with(b"HTTP/1.1 103 Early Hints\r\nlink: </style.css>"));
648 /// # Ok::<(), http_net::HttpError>(())
649 /// ```
650 pub fn send_informational(
651 &mut self,
652 interim: &Response,
653 out: &mut Vec<u8>,
654 ) -> Result<(), HttpError> {
655 if let Some(e) = interim.error() {
656 return Err(e);
657 }
658 let status = interim.status();
659 if !(102..=199).contains(&status) {
660 return Err(HttpError::InvalidStatus);
661 }
662 if !matches!(&interim.body, OutBody::Full(b) if b.is_empty()) {
663 return Err(HttpError::BodyNotAllowed);
664 }
665 if !matches!(self.state, ReqState::Body | ReqState::Complete) {
666 return Err(HttpError::InvalidState(
667 "an interim response needs a request to answer",
668 ));
669 }
670 if self.info.version != Version::Http11 || self.resp != RespState::Idle {
671 return Err(HttpError::InterimNotAllowed);
672 }
673 out.extend_from_slice(b"HTTP/1.1 ");
674 push_decimal(out, u64::from(status));
675 out.push(b' ');
676 out.extend_from_slice(reason_phrase(status).as_bytes());
677 out.extend_from_slice(b"\r\n");
678 out.extend_from_slice(interim.fields());
679 out.extend_from_slice(b"\r\n");
680 Ok(())
681 }
682
683 /// Stops (`false`) or allows (`true`) keep-alive. With `false` the
684 /// current response, or the next one if it has not started, carries
685 /// `connection: close`, and the connection ends after it: the gentlest
686 /// way to shed load or to cap requests per connection. If the current
687 /// response has already been written, the connection ends after it.
688 /// `true` cannot keep open a connection the protocol requires to close
689 /// (the client asked, or body bytes were left unread).
690 ///
691 /// # Examples
692 ///
693 /// ```
694 /// use http_net::{Response, ServerConn, ServerEvent};
695 ///
696 /// let mut conn = ServerConn::new();
697 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
698 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
699 /// conn.set_keep_alive(false);
700 /// let mut out = Vec::new();
701 /// conn.respond(&Response::new(204), &mut out).unwrap();
702 /// assert!(out.windows(17).any(|w| w == b"connection: close"));
703 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Closed));
704 /// ```
705 pub fn set_keep_alive(&mut self, keep: bool) {
706 self.allow_keep_alive = keep;
707 if !keep && self.resp != RespState::Idle {
708 self.keep_alive = false;
709 }
710 }
711
712 /// Whether the connection can stay open after the current exchange, as
713 /// far as is known now: keep-alive is allowed (see
714 /// [`set_keep_alive`](Self::set_keep_alive)) and neither the request,
715 /// the response, nor an error requires a close.
716 ///
717 /// # Examples
718 ///
719 /// ```
720 /// use http_net::{ServerConn, ServerEvent};
721 ///
722 /// let mut conn = ServerConn::new();
723 /// assert!(conn.keep_alive());
724 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\nConnection: close\r\n\r\n");
725 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Request(_)));
726 /// assert!(!conn.keep_alive());
727 /// ```
728 #[must_use]
729 pub fn keep_alive(&self) -> bool {
730 self.allow_keep_alive
731 && match self.state {
732 ReqState::Head => true,
733 ReqState::Body | ReqState::Complete => self.keep_alive,
734 ReqState::Upgraded | ReqState::Failed | ReqState::Closed => false,
735 }
736 }
737
738 /// The number of responses completed on this connection (full-body
739 /// responses when written, streamed ones at `end_body`), so a driver can
740 /// cap requests per connection.
741 ///
742 /// # Examples
743 ///
744 /// ```
745 /// use http_net::{Response, ServerConn, ServerEvent};
746 ///
747 /// let mut conn = ServerConn::new();
748 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
749 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
750 /// assert_eq!(conn.requests_served(), 0);
751 /// conn.respond(&Response::new(204), &mut Vec::new()).unwrap();
752 /// assert_eq!(conn.requests_served(), 1);
753 /// ```
754 #[must_use]
755 pub fn requests_served(&self) -> u64 {
756 self.requests_served
757 }
758
759 /// The connection's phase, for header-read, request, and response
760 /// deadlines. [`Progress::Head`] starts at the first byte of a request,
761 /// so idle keep-alive time (`Idle`) is never counted against a request.
762 ///
763 /// # Examples
764 ///
765 /// ```
766 /// use http_net::{Progress, Response, ServerConn, ServerEvent};
767 ///
768 /// let mut conn = ServerConn::new();
769 /// let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nContent-Length: 4\r\n\r\nab");
770 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Request(_)));
771 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::Body(_)));
772 /// assert!(matches!(conn.poll().unwrap(), ServerEvent::NeedInput));
773 /// assert_eq!(conn.progress(), Progress::Body);
774 /// let _ = conn.feed(b"cd");
775 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
776 /// assert_eq!(conn.progress(), Progress::AwaitingResponse);
777 /// conn.respond(&Response::new(200).chunked(), &mut Vec::new()).unwrap();
778 /// assert_eq!(conn.progress(), Progress::WritingBody);
779 /// conn.end_body(&mut Vec::new()).unwrap();
780 /// assert_eq!(conn.progress(), Progress::Idle);
781 /// ```
782 #[must_use]
783 pub fn progress(&self) -> Progress {
784 if matches!(self.resp, RespState::Streaming(_)) {
785 return Progress::WritingBody;
786 }
787 match self.state {
788 ReqState::Head if self.buf.from(self.buf.pin()).is_empty() => Progress::Idle,
789 ReqState::Head => Progress::Head,
790 ReqState::Body if self.resp == RespState::Sent => Progress::Closed,
791 ReqState::Body if !self.decoder.is_read() => Progress::Body,
792 ReqState::Body => Progress::AwaitingResponse,
793 ReqState::Complete if self.resp != RespState::Sent => Progress::AwaitingResponse,
794 ReqState::Complete if self.keep_alive => Progress::Idle,
795 ReqState::Complete => Progress::Closed,
796 // One error response is still expected.
797 ReqState::Failed if self.resp == RespState::Idle => Progress::AwaitingResponse,
798 ReqState::Upgraded => Progress::Upgraded,
799 ReqState::Failed | ReqState::Closed => Progress::Closed,
800 }
801 }
802
803 /// When `true`, a request's trailer fields are kept (bounded by
804 /// [`Limits::max_trailer_fields`] and [`Limits::max_trailer_bytes`]) and
805 /// reported as [`ServerEvent::Trailers`] just before
806 /// [`ServerEvent::RequestEnd`]. When `false` (the default) they are
807 /// validated and discarded. Trailers never change how a message is
808 /// framed either way.
809 ///
810 /// # Examples
811 ///
812 /// ```
813 /// use http_net::{ServerConn, ServerEvent};
814 ///
815 /// let mut conn = ServerConn::new();
816 /// conn.set_report_trailers(true);
817 /// let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: chunked\r\n\r\n2\r\nhi\r\n0\r\nDigest: sha-256=x\r\n\r\n");
818 /// let mut digest = None;
819 /// loop {
820 /// match conn.poll().unwrap() {
821 /// ServerEvent::Trailers(t) => digest = t.clone().find(|(n, _)| n.eq_ignore_ascii_case("digest")).map(|(_, v)| v.to_vec()),
822 /// ServerEvent::RequestEnd => break,
823 /// _ => {}
824 /// }
825 /// }
826 /// assert_eq!(digest.as_deref(), Some(&b"sha-256=x"[..]));
827 /// ```
828 pub fn set_report_trailers(&mut self, report: bool) {
829 self.report_trailers = report;
830 }
831
832 pub(crate) fn respond_dated(
833 &mut self,
834 response: &Response,
835 date: Option<&[u8]>,
836 out: &mut Vec<u8>,
837 ) -> Result<(), HttpError> {
838 if let Some(e) = response.error() {
839 return Err(e);
840 }
841 let failed = self.state == ReqState::Failed;
842 match self.state {
843 ReqState::Body | ReqState::Complete | ReqState::Failed => {}
844 ReqState::Head => return Err(HttpError::InvalidState("no request to respond to")),
845 ReqState::Upgraded | ReqState::Closed => {
846 return Err(HttpError::InvalidState(
847 "the connection is closed or upgraded",
848 ));
849 }
850 }
851 if self.resp != RespState::Idle {
852 return Err(HttpError::InvalidState("a response was already started"));
853 }
854 let status = response.status();
855 if !(100..=599).contains(&status) || ((100..200).contains(&status) && status != 101) {
856 return Err(HttpError::InvalidStatus);
857 }
858 let (method, version) = if failed {
859 (Method::Get, Version::Http11)
860 } else {
861 (self.info.method, self.info.version)
862 };
863 let bodiless = (100..200).contains(&status) || status == 204 || status == 304;
864 let tunnel = status == 101 || (method == Method::Connect && (200..300).contains(&status));
865 if bodiless || tunnel {
866 let empty = matches!(&response.body, OutBody::Full(b) if b.is_empty());
867 if !empty {
868 return Err(HttpError::BodyNotAllowed);
869 }
870 }
871 if tunnel {
872 let complete_upgrade =
873 self.body_read() && (self.info.upgrade || method == Method::Connect);
874 if !complete_upgrade || (status == 101 && !response.upgrade) || failed {
875 return Err(HttpError::InvalidState(
876 "101 (or 2xx to CONNECT) must answer a complete upgrade request; \
877 build it with Response::switching_protocols",
878 ));
879 }
880 // RFC 9110 section 7.8: never switch to a protocol the client
881 // did not offer.
882 if status == 101
883 && !response
884 .upgrade_protocol()
885 .is_some_and(|p| self.view().offers(p))
886 {
887 return Err(HttpError::UpgradeNotOffered);
888 }
889 }
890
891 let mut close = failed
892 || response.close
893 || !self.keep_alive
894 || !self.allow_keep_alive
895 || !self.body_read();
896 let head_only = method == Method::Head || bodiless || tunnel;
897 self.resp_chunked = matches!(response.body, OutBody::Chunked);
898 let (mut encoder, declared) = match &response.body {
899 OutBody::Full(b) => (
900 Encoder::Length {
901 remaining: b.len() as u64,
902 },
903 Some(b.len() as u64),
904 ),
905 OutBody::Length(n) => (Encoder::Length { remaining: *n }, Some(*n)),
906 OutBody::Chunked if version == Version::Http10 => {
907 close = true;
908 (Encoder::CloseDelimited, None)
909 }
910 OutBody::Chunked => (Encoder::Chunked, None),
911 };
912
913 out.extend_from_slice(b"HTTP/1.1 ");
914 push_decimal(out, u64::from(status));
915 out.push(b' ');
916 out.extend_from_slice(reason_phrase(status).as_bytes());
917 out.extend_from_slice(b"\r\n");
918 if !(bodiless || tunnel) {
919 push_framing(out, encoder, declared);
920 }
921 if tunnel {
922 close = false;
923 } else if close {
924 out.extend_from_slice(b"connection: close\r\n");
925 } else if version == Version::Http10 {
926 out.extend_from_slice(b"connection: keep-alive\r\n");
927 }
928 if let Some(date) = date.filter(|_| !response.has_date) {
929 out.extend_from_slice(b"date: ");
930 out.extend_from_slice(date);
931 out.extend_from_slice(b"\r\n");
932 }
933 out.extend_from_slice(response.fields());
934 out.extend_from_slice(b"\r\n");
935
936 if head_only {
937 encoder = Encoder::Discard;
938 }
939 self.keep_alive = !close;
940 match &response.body {
941 OutBody::Full(b) => {
942 encoder.write(b, out)?;
943 self.resp = RespState::Sent;
944 self.requests_served += 1;
945 }
946 _ => self.resp = RespState::Streaming(encoder),
947 }
948 if tunnel {
949 self.state = ReqState::Upgraded;
950 } else if failed {
951 self.state = ReqState::Closed;
952 }
953 Ok(())
954 }
955
956 /// Writes `HTTP/1.1 100 Continue` into `out`: the answer to
957 /// [`RequestHead::expects_continue`](crate::RequestHead::expects_continue)
958 /// that tells the client to send the body.
959 ///
960 /// RFC 9110 section 10.1.1 requires a server that receives
961 /// `Expect: 100-continue` to send either this or a final response before
962 /// waiting for the body; clients otherwise stall (curl for one second,
963 /// some indefinitely). Call it after [`ServerEvent::Request`], once the
964 /// head has been judged acceptable.
965 ///
966 /// # Errors
967 ///
968 /// [`HttpError::InterimNotAllowed`] for an HTTP/1.0 request (RFC 9110
969 /// section 15.2 forbids any 1xx to an HTTP/1.0 client), once a body byte
970 /// has been read or the whole body has arrived, once a response has
971 /// started, or when `100 Continue` was already sent for this request;
972 /// [`HttpError::InvalidState`] when no request is waiting for its body
973 /// (none has arrived, or the connection failed, closed, or upgraded).
974 ///
975 /// # Examples
976 ///
977 /// ```
978 /// use http_net::{ServerConn, ServerEvent};
979 ///
980 /// let mut conn = ServerConn::new();
981 /// let _ = conn.feed(b"PUT /f HTTP/1.1\r\nHost: a\r\nExpect: 100-continue\r\nContent-Length: 2\r\n\r\n");
982 /// let ServerEvent::Request(req) = conn.poll()? else { unreachable!() };
983 /// assert!(req.expects_continue());
984 /// let mut out = Vec::new();
985 /// conn.send_continue(&mut out)?;
986 /// assert_eq!(out, b"HTTP/1.1 100 Continue\r\n\r\n");
987 /// # Ok::<(), http_net::HttpError>(())
988 /// ```
989 pub fn send_continue(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError> {
990 if !matches!(self.state, ReqState::Body | ReqState::Complete) {
991 return Err(HttpError::InvalidState(
992 "100 Continue needs a request whose body is still to come",
993 ));
994 }
995 if self.state == ReqState::Complete
996 || self.decoder.is_read()
997 || self.body_seen
998 || self.resp != RespState::Idle
999 || self.info.version != Version::Http11
1000 || self.continue_sent
1001 {
1002 return Err(HttpError::InterimNotAllowed);
1003 }
1004 self.continue_sent = true;
1005 out.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
1006 Ok(())
1007 }
1008
1009 /// Writes body bytes of a streamed response into `out`. For a `HEAD`
1010 /// request the bytes are dropped.
1011 ///
1012 /// # Errors
1013 ///
1014 /// [`HttpError::BodyLengthMismatch`] past the declared
1015 /// [`Response::content_length`]; [`HttpError::InvalidState`] when no
1016 /// streamed response is in progress.
1017 ///
1018 /// # Examples
1019 ///
1020 /// ```
1021 /// use http_net::{Response, ServerConn, ServerEvent};
1022 ///
1023 /// let mut conn = ServerConn::new();
1024 /// let _ = conn.feed(b"GET /log HTTP/1.1\r\nHost: a\r\n\r\n");
1025 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
1026 /// let mut out = Vec::new();
1027 /// conn.respond(&Response::new(200).chunked(), &mut out).unwrap();
1028 /// conn.send_body(b"line 1\n", &mut out).unwrap();
1029 /// conn.end_body(&mut out).unwrap();
1030 /// assert!(out.ends_with(b"7\r\nline 1\n\r\n0\r\n\r\n"));
1031 /// ```
1032 pub fn send_body(&mut self, data: &[u8], out: &mut Vec<u8>) -> Result<(), HttpError> {
1033 match &mut self.resp {
1034 RespState::Streaming(encoder) => encoder.write(data, out),
1035 _ => Err(HttpError::InvalidState("no streamed response in progress")),
1036 }
1037 }
1038
1039 /// Ends a streamed response body (the last chunk for chunked encoding).
1040 ///
1041 /// # Errors
1042 ///
1043 /// [`HttpError::BodyLengthMismatch`] when fewer bytes than the declared
1044 /// length were sent; [`HttpError::InvalidState`] when no streamed
1045 /// response is in progress.
1046 ///
1047 /// # Examples
1048 ///
1049 /// ```
1050 /// use http_net::{HttpError, Response, ServerConn, ServerEvent};
1051 ///
1052 /// let mut conn = ServerConn::new();
1053 /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
1054 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
1055 /// let mut out = Vec::new();
1056 /// conn.respond(&Response::new(200).content_length(3), &mut out).unwrap();
1057 /// conn.send_body(b"ab", &mut out).unwrap();
1058 /// assert_eq!(conn.end_body(&mut out), Err(HttpError::BodyLengthMismatch));
1059 /// ```
1060 pub fn end_body(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError> {
1061 self.end_body_with_trailers(&[], out)
1062 }
1063
1064 /// Ends a streamed chunked body with a trailer section: the last chunk,
1065 /// then `trailers` as fields. Every field is validated before anything
1066 /// is written.
1067 ///
1068 /// Trailers are optional metadata a recipient may discard (RFC 9110
1069 /// section 6.5), so when the body could not be chunked (an HTTP/1.0
1070 /// client forced a close-delimited body) or is not sent at all (`HEAD`),
1071 /// they are dropped with it and the call still succeeds: the handler
1072 /// does not need to know which framing the client forced.
1073 ///
1074 /// # Errors
1075 ///
1076 /// [`HttpError::TrailerNotAllowed`] for a field RFC 9110 section 6.5.1
1077 /// keeps out of trailers (framing, routing, authentication, request
1078 /// modifiers, response control, content handling: `content-length`,
1079 /// `host`, `authorization`, `set-cookie`, `content-type`, `date`, and
1080 /// the rest of the list in `docs/API.md`) or for a body declared with
1081 /// [`Response::content_length`]; the field errors of
1082 /// [`Response::header`]; [`HttpError::BodyLengthMismatch`] and
1083 /// [`HttpError::InvalidState`] as for [`end_body`](Self::end_body).
1084 ///
1085 /// # Examples
1086 ///
1087 /// ```
1088 /// use http_net::{HttpError, Response, ServerConn, ServerEvent};
1089 ///
1090 /// let mut conn = ServerConn::new();
1091 /// let _ = conn.feed(b"GET /data HTTP/1.1\r\nHost: a\r\nTE: trailers\r\n\r\n");
1092 /// while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
1093 /// let mut out = Vec::new();
1094 /// conn.respond(&Response::new(200).chunked(), &mut out)?;
1095 /// conn.send_body(b"rows", &mut out)?;
1096 /// assert_eq!(
1097 /// conn.end_body_with_trailers(&[("content-type", b"text/csv")], &mut out),
1098 /// Err(HttpError::TrailerNotAllowed)
1099 /// );
1100 /// conn.end_body_with_trailers(&[("server-timing", b"db;dur=53")], &mut out)?;
1101 /// assert!(out.ends_with(b"4\r\nrows\r\n0\r\nserver-timing: db;dur=53\r\n\r\n"));
1102 /// # Ok::<(), http_net::HttpError>(())
1103 /// ```
1104 pub fn end_body_with_trailers(
1105 &mut self,
1106 trailers: &[(&str, &[u8])],
1107 out: &mut Vec<u8>,
1108 ) -> Result<(), HttpError> {
1109 let RespState::Streaming(encoder) = &mut self.resp else {
1110 return Err(HttpError::InvalidState("no streamed response in progress"));
1111 };
1112 if !trailers.is_empty() && !self.resp_chunked {
1113 return Err(HttpError::TrailerNotAllowed);
1114 }
1115 match encoder {
1116 Encoder::Chunked => push_last_chunk_with_trailers(out, trailers)?,
1117 _ => {
1118 check_trailers(trailers)?;
1119 encoder.finish(out)?;
1120 }
1121 }
1122 if *encoder == Encoder::CloseDelimited {
1123 self.keep_alive = false;
1124 }
1125 self.resp = RespState::Sent;
1126 self.requests_served += 1;
1127 Ok(())
1128 }
1129}
1130
1131#[cfg(test)]
1132mod tests {
1133 use alloc::vec;
1134
1135 use super::*;
1136
1137 fn events(conn: &mut ServerConn) -> Vec<alloc::string::String> {
1138 let mut log = Vec::new();
1139 loop {
1140 match conn.poll() {
1141 Ok(ServerEvent::Request(r)) => log.push(alloc::format!("req {}", r.target())),
1142 Ok(ServerEvent::Body(b)) => log.push(alloc::format!("body {}", b.len())),
1143 Ok(ServerEvent::RequestEnd) => {
1144 log.push("end".into());
1145 return log;
1146 }
1147 Ok(other) => {
1148 log.push(alloc::format!("{other:?}"));
1149 return log;
1150 }
1151 Err(e) => {
1152 log.push(alloc::format!("err {e:?}"));
1153 return log;
1154 }
1155 }
1156 }
1157 }
1158
1159 #[test]
1160 fn test_early_response_closes_connection() {
1161 let mut conn = ServerConn::new();
1162 let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nContent-Length: 10\r\n\r\nab");
1163 assert!(matches!(conn.poll(), Ok(ServerEvent::Request(_))));
1164 let mut out = Vec::new();
1165 conn.respond(&Response::new(413), &mut out).unwrap();
1166 assert!(out.windows(17).any(|w| w == b"connection: close"));
1167 assert!(matches!(conn.poll(), Ok(ServerEvent::Closed)));
1168 }
1169
1170 #[test]
1171 fn test_respond_after_failure_is_once_and_closes() {
1172 let mut conn = ServerConn::new();
1173 let _ = conn.feed(b"GET / HTTP/1.1\r\n\r\n");
1174 assert_eq!(conn.poll().unwrap_err(), HttpError::MissingHost);
1175 let mut out = Vec::new();
1176 conn.respond(&Response::new(400), &mut out).unwrap();
1177 assert!(out.starts_with(b"HTTP/1.1 400 Bad Request\r\n"));
1178 assert!(conn.respond(&Response::new(400), &mut out).is_err());
1179 assert!(matches!(conn.poll(), Ok(ServerEvent::Closed)));
1180 }
1181
1182 #[test]
1183 fn test_state_errors() {
1184 let mut conn = ServerConn::new();
1185 let mut out = Vec::new();
1186 assert!(matches!(
1187 conn.respond(&Response::new(200), &mut out),
1188 Err(HttpError::InvalidState(_))
1189 ));
1190 assert!(matches!(
1191 conn.send_body(b"x", &mut out),
1192 Err(HttpError::InvalidState(_))
1193 ));
1194 assert!(matches!(
1195 conn.end_body(&mut out),
1196 Err(HttpError::InvalidState(_))
1197 ));
1198 let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
1199 assert_eq!(events(&mut conn), vec!["req /", "end"]);
1200 assert_eq!(
1201 conn.respond(&Response::new(99), &mut out),
1202 Err(HttpError::InvalidStatus)
1203 );
1204 assert_eq!(
1205 conn.respond(&Response::new(100), &mut out),
1206 Err(HttpError::InvalidStatus)
1207 );
1208 assert_eq!(
1209 conn.respond(&Response::new(204).body(&b"x"[..]), &mut out),
1210 Err(HttpError::BodyNotAllowed)
1211 );
1212 assert!(matches!(
1213 conn.respond(&Response::switching_protocols("x"), &mut out),
1214 Err(HttpError::InvalidState(_))
1215 ));
1216 conn.respond(&Response::new(204), &mut out).unwrap();
1217 assert!(matches!(
1218 conn.respond(&Response::new(200), &mut out),
1219 Err(HttpError::InvalidState(_))
1220 ));
1221 }
1222
1223 #[test]
1224 fn test_http10_keep_alive_and_chunked_fallback() {
1225 let mut conn = ServerConn::new();
1226 let _ = conn.feed(b"GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n");
1227 assert_eq!(events(&mut conn), vec!["req /", "end"]);
1228 let mut out = Vec::new();
1229 conn.respond(&Response::text(200, "x"), &mut out).unwrap();
1230 assert!(out.windows(22).any(|w| w == b"connection: keep-alive"));
1231 assert!(matches!(conn.poll(), Ok(ServerEvent::NeedInput)));
1232
1233 let _ = conn.feed(b"GET / HTTP/1.0\r\n\r\n");
1234 assert_eq!(events(&mut conn), vec!["req /", "end"]);
1235 let mut out = Vec::new();
1236 conn.respond(&Response::new(200).chunked(), &mut out)
1237 .unwrap();
1238 conn.send_body(b"abc", &mut out).unwrap();
1239 conn.end_body(&mut out).unwrap();
1240 assert!(out.ends_with(b"\r\n\r\nabc"));
1241 assert!(!out.windows(17).any(|w| w == b"transfer-encoding"));
1242 assert!(matches!(conn.poll(), Ok(ServerEvent::Closed)));
1243 }
1244
1245 fn upgrade_request(conn: &mut ServerConn, offer: &str) {
1246 let msg = alloc::format!(
1247 "GET / HTTP/1.1\r\nHost: a\r\nConnection: upgrade\r\nUpgrade: {offer}\r\n\r\n"
1248 );
1249 let _ = conn.feed(msg.as_bytes());
1250 assert_eq!(events(conn), vec!["req /", "end"]);
1251 }
1252
1253 #[test]
1254 fn test_switching_protocols_must_name_an_offered_protocol() {
1255 let mut conn = ServerConn::new();
1256 upgrade_request(&mut conn, "websocket/13, foo/2");
1257 let mut out = Vec::new();
1258 // `foo` alone would match `foo/2`: a name without a version
1259 // answers an offer of that name with any version.
1260 for refused in ["ftp", "foo/3", "websocket/12", "h2c"] {
1261 assert_eq!(
1262 conn.respond(&Response::switching_protocols(refused), &mut out),
1263 Err(HttpError::UpgradeNotOffered),
1264 "{refused}"
1265 );
1266 assert!(out.is_empty());
1267 assert!(!conn.is_upgraded());
1268 }
1269 conn.respond(&Response::switching_protocols("WebSocket"), &mut out)
1270 .unwrap();
1271 assert!(conn.is_upgraded());
1272 assert!(out.windows(18).any(|w| w == b"upgrade: WebSocket"));
1273 }
1274
1275 #[test]
1276 fn test_refused_switch_leaves_a_normal_response_possible() {
1277 let mut conn = ServerConn::new();
1278 upgrade_request(&mut conn, "websocket");
1279 let mut out = Vec::new();
1280 assert_eq!(
1281 conn.respond(&Response::switching_protocols("irc"), &mut out),
1282 Err(HttpError::UpgradeNotOffered)
1283 );
1284 conn.respond(&Response::new(426), &mut out).unwrap();
1285 assert!(out.starts_with(b"HTTP/1.1 426 Upgrade Required\r\n"));
1286 assert!(matches!(conn.poll(), Ok(ServerEvent::NeedInput)));
1287 }
1288
1289 #[test]
1290 fn test_h2c_only_offer_is_served_as_http11() {
1291 let mut conn = ServerConn::new();
1292 let _ = conn.feed(
1293 b"GET / HTTP/1.1\r\nHost: a\r\nConnection: Upgrade, HTTP2-Settings\r\nUpgrade: h2c\r\nHTTP2-Settings: AAMAAABkAAQAoAAA\r\n\r\n",
1294 );
1295 assert!(matches!(conn.poll(), Ok(ServerEvent::Request(r)) if !r.is_upgrade()));
1296 assert!(matches!(conn.poll(), Ok(ServerEvent::RequestEnd)));
1297 let mut out = Vec::new();
1298 assert!(matches!(
1299 conn.respond(&Response::switching_protocols("websocket"), &mut out),
1300 Err(HttpError::InvalidState(_))
1301 ));
1302 conn.respond(&Response::new(200), &mut out).unwrap();
1303 assert!(matches!(conn.poll(), Ok(ServerEvent::NeedInput)));
1304 }
1305
1306 #[test]
1307 fn test_unregistered_status_keeps_the_space_before_an_empty_reason() {
1308 let mut conn = ServerConn::new();
1309 let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
1310 assert_eq!(events(&mut conn), vec!["req /", "end"]);
1311 let mut out = Vec::new();
1312 conn.respond(&Response::new(299), &mut out).unwrap();
1313 assert!(out.starts_with(b"HTTP/1.1 299 \r\n"));
1314 }
1315
1316 #[test]
1317 fn test_connect_tunnel() {
1318 let mut conn = ServerConn::new();
1319 let _ = conn.feed(b"CONNECT example.com:443 HTTP/1.1\r\nHost: example.com:443\r\n\r\nTLS");
1320 assert_eq!(events(&mut conn), vec!["req example.com:443", "end"]);
1321 let mut out = Vec::new();
1322 conn.respond(&Response::new(200), &mut out).unwrap();
1323 assert_eq!(out, b"HTTP/1.1 200 OK\r\n\r\n");
1324 assert!(matches!(conn.poll(), Ok(ServerEvent::Upgraded)));
1325 assert_eq!(conn.remaining_input(), b"TLS");
1326 assert!(conn.request().is_some());
1327 }
1328}