Skip to main content

ServerConn

Struct ServerConn 

Source
pub struct ServerConn { /* private fields */ }
Expand description

The server side of one HTTP/1.1 connection: a sans-IO state machine.

The connection owns a bounded input buffer. The caller moves bytes between it and the socket: input in through feed (or read_buf + commit to read straight into the buffer), events out through poll, responses out through respond into a caller-owned Vec<u8>.

Requests are handled one at a time, in order. Keep-alive is automatic: after a response is finished the next request (possibly already buffered, when the client pipelines) is parsed on the next poll. A connection that must close (the client asked, HTTP/1.0 without keep-alive, the response was sent before the request body was read, or a parse error) reports ServerEvent::Closed once its last response is written.

Steady state allocates nothing: the input buffer and the field index are reused across requests.

§Examples

use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let mut out = Vec::new();
// Two pipelined requests in one read.
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");
let mut paths = Vec::new();
loop {
    match conn.poll().unwrap() {
        ServerEvent::Request(req) => paths.push(req.path().to_string()),
        ServerEvent::RequestEnd => conn.respond(&Response::text(200, "ok"), &mut out).unwrap(),
        ServerEvent::NeedInput => break,
        other => panic!("{other:?}"),
    }
}
assert_eq!(paths, ["/a", "/b"]);

Implementations§

Source§

impl ServerConn

Source

pub fn new() -> Self

A connection with the default Limits.

§Examples
let conn = http_net::ServerConn::new();
assert!(conn.request().is_none());
Source

pub fn with_limits(limits: Limits) -> Self

A connection enforcing limits.

§Examples
use http_net::{HttpError, Limits, ServerConn};

let mut conn = ServerConn::with_limits(Limits::new().with_max_body(4));
let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\n");
assert_eq!(conn.poll().unwrap_err(), HttpError::BodyTooLarge);
Source

pub fn limits(&self) -> &Limits

The limits this connection enforces.

§Examples
assert_eq!(http_net::ServerConn::new().limits(), &http_net::Limits::new());
Source

pub fn feed(&mut self, bytes: &[u8]) -> usize

Copies as much of bytes into the input buffer as fits and returns how many bytes were taken. Fewer than bytes.len() means the buffer is full: poll until it asks for input, then feed the rest.

§Examples
let mut conn = http_net::ServerConn::new();
assert_eq!(conn.feed(b"GET / HTTP/1.1\r\n"), 16);
Source

pub fn read_buf(&mut self) -> &mut [u8] ⓘ

Spare space at the end of the input buffer, for reading from a socket without an intermediate copy. Follow with commit. It is empty only when the buffer is full of input the parser has not been asked to process yet; poll first.

§Examples
let mut conn = http_net::ServerConn::new();
let spare = conn.read_buf();
let msg = b"GET / HTTP/1.1\r\nHost: a\r\n\r\n";
spare[..msg.len()].copy_from_slice(msg);
conn.commit(msg.len());
assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::Request(_))));
Source

pub fn commit(&mut self, n: usize)

Records that n bytes were written into read_buf.

§Examples
let mut conn = http_net::ServerConn::new();
conn.read_buf()[0] = b'G';
conn.commit(1);
assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::NeedInput)));
Source

pub fn feed_eof(&mut self)

Records that the peer closed its sending side. A connection idle between requests then reports ServerEvent::Closed; one in the middle of a request reports HttpError::UnexpectedEof.

§Examples
let mut conn = http_net::ServerConn::new();
conn.feed_eof();
assert!(matches!(conn.poll(), Ok(http_net::ServerEvent::Closed)));
Source

pub fn poll(&mut self) -> Result<ServerEvent<'_>, HttpError>

Advances the parser and reports what happened. Call it until it returns ServerEvent::NeedInput, ServerEvent::AwaitingResponse, ServerEvent::Upgraded, or ServerEvent::Closed.

§Errors

Any HttpError parse error. The connection is then finished: send one error response (see HttpError::status) with respond, flush, and close.

§Examples
use http_net::{HttpError, ServerConn};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n folded\r\n\r\n");
assert_eq!(conn.poll().unwrap_err(), HttpError::ObsFold);
Source

pub fn request(&self) -> Option<RequestHead<'_>>

The current request’s head, from its arrival until the next request begins (still available after an upgrade).

§Examples
use http_net::{ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"PUT /f HTTP/1.1\r\nHost: a\r\nContent-Length: 1\r\n\r\nz");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
assert_eq!(conn.request().unwrap().path(), "/f");
Source

pub fn is_upgraded(&self) -> bool

Whether a 101 Switching Protocols (or a 2xx to CONNECT) was sent and the connection now belongs to another protocol.

§Examples
assert!(!http_net::ServerConn::new().is_upgraded());
Source

pub fn remaining_input(&self) -> &[u8] ⓘ

Input that arrived after the last message this connection parsed: after ServerEvent::Upgraded, the first bytes of the new protocol.

§Examples
use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\nConnection: upgrade\r\nUpgrade: x\r\n\r\n\x81\x00");
assert!(matches!(conn.poll().unwrap(), ServerEvent::Request(_)));
assert!(matches!(conn.poll().unwrap(), ServerEvent::RequestEnd));
conn.respond(&Response::switching_protocols("x"), &mut Vec::new()).unwrap();
assert!(matches!(conn.poll().unwrap(), ServerEvent::Upgraded));
assert_eq!(conn.remaining_input(), b"\x81\x00");
Source

pub fn respond( &mut self, response: &Response, out: &mut Vec<u8>, ) -> Result<(), HttpError>

Writes response for the current request into out.

With a full body the response is complete. With a streamed body (Response::chunked, Response::content_length) follow with send_body and end_body. After a parse error, one response may still be sent; it is marked connection: close.

§Errors
§Examples
use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"HEAD / HTTP/1.1\r\nHost: a\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
let mut out = Vec::new();
conn.respond(&Response::text(200, "hello"), &mut out).unwrap();
// HEAD: the length is announced, the body is not sent.
assert!(out.windows(17).any(|w| w == b"content-length: 5"));
assert!(out.ends_with(b"\r\n\r\n"));
Source

pub fn respond_with_date( &mut self, response: &Response, date: &HttpDate, out: &mut Vec<u8>, ) -> Result<(), HttpError>

As respond, adding date: <date> unless the response set its own date field. Keep a DateCache per driver thread and pass cache.update(now): the value is reformatted once per second, not once per response.

§Errors

As respond.

§Examples
use http_net::{DateCache, Response, ServerConn, ServerEvent};

let mut dates = DateCache::new();
let mut conn = ServerConn::new();
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
let mut out = Vec::new();
conn.respond_with_date(&Response::new(204), dates.update(784_111_777), &mut out)?;
assert!(out.windows(35).any(|w| w == b"date: Sun, 06 Nov 1994 08:49:37 GMT"));
Source

pub fn send_informational( &mut self, interim: &Response, out: &mut Vec<u8>, ) -> Result<(), HttpError>

Writes an interim (1xx) response other than 100 and 101, for example 103 Early Hints with link fields, before the final response. It may be sent more than once, for any request method, at any point before the final response starts (RFC 9110 section 15.2), but never to an HTTP/1.0 client. Only the status and the fields are written; an interim response has no body and does not change the connection.

§Errors

The first error recorded by the builder; HttpError::InvalidStatus unless the status is in 102..=199; HttpError::BodyNotAllowed for a body; HttpError::InterimNotAllowed for an HTTP/1.0 request or once the final response has started; HttpError::InvalidState when there is no request (or after a parse error, an upgrade, or the end of the connection).

§Examples
use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
let mut out = Vec::new();
let hints = Response::new(103).header("link", "</style.css>; rel=preload; as=style");
conn.send_informational(&hints, &mut out)?;
conn.respond(&Response::text(200, "page"), &mut out)?;
assert!(out.starts_with(b"HTTP/1.1 103 Early Hints\r\nlink: </style.css>"));
Source

pub fn set_keep_alive(&mut self, keep: bool)

Stops (false) or allows (true) keep-alive. With false the current response, or the next one if it has not started, carries connection: close, and the connection ends after it: the gentlest way to shed load or to cap requests per connection. If the current response has already been written, the connection ends after it. true cannot keep open a connection the protocol requires to close (the client asked, or body bytes were left unread).

§Examples
use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
conn.set_keep_alive(false);
let mut out = Vec::new();
conn.respond(&Response::new(204), &mut out).unwrap();
assert!(out.windows(17).any(|w| w == b"connection: close"));
assert!(matches!(conn.poll().unwrap(), ServerEvent::Closed));
Source

pub fn keep_alive(&self) -> bool

Whether the connection can stay open after the current exchange, as far as is known now: keep-alive is allowed (see set_keep_alive) and neither the request, the response, nor an error requires a close.

§Examples
use http_net::{ServerConn, ServerEvent};

let mut conn = ServerConn::new();
assert!(conn.keep_alive());
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\nConnection: close\r\n\r\n");
assert!(matches!(conn.poll().unwrap(), ServerEvent::Request(_)));
assert!(!conn.keep_alive());
Source

pub fn requests_served(&self) -> u64

The number of responses completed on this connection (full-body responses when written, streamed ones at end_body), so a driver can cap requests per connection.

§Examples
use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
assert_eq!(conn.requests_served(), 0);
conn.respond(&Response::new(204), &mut Vec::new()).unwrap();
assert_eq!(conn.requests_served(), 1);
Source

pub fn progress(&self) -> Progress

The connection’s phase, for header-read, request, and response deadlines. Progress::Head starts at the first byte of a request, so idle keep-alive time (Idle) is never counted against a request.

§Examples
use http_net::{Progress, Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"POST / HTTP/1.1\r\nHost: a\r\nContent-Length: 4\r\n\r\nab");
assert!(matches!(conn.poll().unwrap(), ServerEvent::Request(_)));
assert!(matches!(conn.poll().unwrap(), ServerEvent::Body(_)));
assert!(matches!(conn.poll().unwrap(), ServerEvent::NeedInput));
assert_eq!(conn.progress(), Progress::Body);
let _ = conn.feed(b"cd");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
assert_eq!(conn.progress(), Progress::AwaitingResponse);
conn.respond(&Response::new(200).chunked(), &mut Vec::new()).unwrap();
assert_eq!(conn.progress(), Progress::WritingBody);
conn.end_body(&mut Vec::new()).unwrap();
assert_eq!(conn.progress(), Progress::Idle);
Source

pub fn set_report_trailers(&mut self, report: bool)

When true, a request’s trailer fields are kept (bounded by Limits::max_trailer_fields and Limits::max_trailer_bytes) and reported as ServerEvent::Trailers just before ServerEvent::RequestEnd. When false (the default) they are validated and discarded. Trailers never change how a message is framed either way.

§Examples
use http_net::{ServerConn, ServerEvent};

let mut conn = ServerConn::new();
conn.set_report_trailers(true);
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");
let mut digest = None;
loop {
    match conn.poll().unwrap() {
        ServerEvent::Trailers(t) => digest = t.clone().find(|(n, _)| n.eq_ignore_ascii_case("digest")).map(|(_, v)| v.to_vec()),
        ServerEvent::RequestEnd => break,
        _ => {}
    }
}
assert_eq!(digest.as_deref(), Some(&b"sha-256=x"[..]));
Source

pub fn send_continue(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError>

Writes HTTP/1.1 100 Continue into out: the answer to RequestHead::expects_continue that tells the client to send the body.

RFC 9110 section 10.1.1 requires a server that receives Expect: 100-continue to send either this or a final response before waiting for the body; clients otherwise stall (curl for one second, some indefinitely). Call it after ServerEvent::Request, once the head has been judged acceptable.

§Errors

HttpError::InterimNotAllowed for an HTTP/1.0 request (RFC 9110 section 15.2 forbids any 1xx to an HTTP/1.0 client), once a body byte has been read or the whole body has arrived, once a response has started, or when 100 Continue was already sent for this request; HttpError::InvalidState when no request is waiting for its body (none has arrived, or the connection failed, closed, or upgraded).

§Examples
use http_net::{ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"PUT /f HTTP/1.1\r\nHost: a\r\nExpect: 100-continue\r\nContent-Length: 2\r\n\r\n");
let ServerEvent::Request(req) = conn.poll()? else { unreachable!() };
assert!(req.expects_continue());
let mut out = Vec::new();
conn.send_continue(&mut out)?;
assert_eq!(out, b"HTTP/1.1 100 Continue\r\n\r\n");
Source

pub fn send_body( &mut self, data: &[u8], out: &mut Vec<u8>, ) -> Result<(), HttpError>

Writes body bytes of a streamed response into out. For a HEAD request the bytes are dropped.

§Errors

HttpError::BodyLengthMismatch past the declared Response::content_length; HttpError::InvalidState when no streamed response is in progress.

§Examples
use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET /log HTTP/1.1\r\nHost: a\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
let mut out = Vec::new();
conn.respond(&Response::new(200).chunked(), &mut out).unwrap();
conn.send_body(b"line 1\n", &mut out).unwrap();
conn.end_body(&mut out).unwrap();
assert!(out.ends_with(b"7\r\nline 1\n\r\n0\r\n\r\n"));
Source

pub fn end_body(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError>

Ends a streamed response body (the last chunk for chunked encoding).

§Errors

HttpError::BodyLengthMismatch when fewer bytes than the declared length were sent; HttpError::InvalidState when no streamed response is in progress.

§Examples
use http_net::{HttpError, Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
let mut out = Vec::new();
conn.respond(&Response::new(200).content_length(3), &mut out).unwrap();
conn.send_body(b"ab", &mut out).unwrap();
assert_eq!(conn.end_body(&mut out), Err(HttpError::BodyLengthMismatch));
Source

pub fn end_body_with_trailers( &mut self, trailers: &[(&str, &[u8])], out: &mut Vec<u8>, ) -> Result<(), HttpError>

Ends a streamed chunked body with a trailer section: the last chunk, then trailers as fields. Every field is validated before anything is written.

Trailers are optional metadata a recipient may discard (RFC 9110 section 6.5), so when the body could not be chunked (an HTTP/1.0 client forced a close-delimited body) or is not sent at all (HEAD), they are dropped with it and the call still succeeds: the handler does not need to know which framing the client forced.

§Errors

HttpError::TrailerNotAllowed for a field RFC 9110 section 6.5.1 keeps out of trailers (framing, routing, authentication, request modifiers, response control, content handling: content-length, host, authorization, set-cookie, content-type, date, and the rest of the list in docs/API.md) or for a body declared with Response::content_length; the field errors of Response::header; HttpError::BodyLengthMismatch and HttpError::InvalidState as for end_body.

§Examples
use http_net::{HttpError, Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let _ = conn.feed(b"GET /data HTTP/1.1\r\nHost: a\r\nTE: trailers\r\n\r\n");
while !matches!(conn.poll().unwrap(), ServerEvent::RequestEnd) {}
let mut out = Vec::new();
conn.respond(&Response::new(200).chunked(), &mut out)?;
conn.send_body(b"rows", &mut out)?;
assert_eq!(
    conn.end_body_with_trailers(&[("content-type", b"text/csv")], &mut out),
    Err(HttpError::TrailerNotAllowed)
);
conn.end_body_with_trailers(&[("server-timing", b"db;dur=53")], &mut out)?;
assert!(out.ends_with(b"4\r\nrows\r\n0\r\nserver-timing: db;dur=53\r\n\r\n"));

Trait Implementations§

Source§

impl Debug for ServerConn

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ServerConn

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.