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 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::InvalidState unless the current request is HTTP/1.1, its body has not been read yet, no response has been started, and 100 Continue has not already been sent for it. RFC 9110 section 15.2 forbids any 1xx to an HTTP/1.0 client.

§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));

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.