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
impl ServerConn
Sourcepub fn with_limits(limits: Limits) -> Self
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);Sourcepub fn limits(&self) -> &Limits
pub fn limits(&self) -> &Limits
The limits this connection enforces.
§Examples
assert_eq!(http_net::ServerConn::new().limits(), &http_net::Limits::new());Sourcepub fn read_buf(&mut self) -> &mut [u8] ⓘ
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(_))));Sourcepub fn feed_eof(&mut self)
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)));Sourcepub fn poll(&mut self) -> Result<ServerEvent<'_>, HttpError>
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);Sourcepub fn request(&self) -> Option<RequestHead<'_>>
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");Sourcepub fn is_upgraded(&self) -> bool
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());Sourcepub fn remaining_input(&self) -> &[u8] ⓘ
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");Sourcepub fn respond(
&mut self,
response: &Response,
out: &mut Vec<u8>,
) -> Result<(), HttpError>
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
- the first error recorded by the
Responsebuilder; HttpError::InvalidStatusfor a status outside100..=599, or a 1xx other than 101;HttpError::BodyNotAllowedfor a body on 1xx, 204, or 304;HttpError::InvalidStatewhen there is no request to answer, a response was already started, or a 101 does not answer a complete upgrade request.
§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"));Sourcepub fn send_continue(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError>
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");Sourcepub fn send_body(
&mut self,
data: &[u8],
out: &mut Vec<u8>,
) -> Result<(), HttpError>
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"));Sourcepub fn end_body(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError>
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));