pub struct ClientConn { /* private fields */ }Expand description
The client side of one HTTP/1.1 connection: a sans-IO state machine.
One request is outstanding at a time. send_request
serializes a Request; feed and poll
parse the response. When the response allows it, the connection returns
to ClientEvent::Idle and can send the next request (keep-alive).
The response is framed with the request in mind: a HEAD request’s
response has no body whatever its headers say, a CONNECT 2xx becomes a
tunnel, and a response with neither Content-Length nor
Transfer-Encoding runs until the server closes.
§Examples
use http_net::{ClientConn, ClientEvent, Request};
let mut conn = ClientConn::new();
let mut out = Vec::new();
conn.send_request(&Request::get("/a").header("host", "h"), &mut out).unwrap();
assert_eq!(out, b"GET /a HTTP/1.1\r\nhost: h\r\n\r\n");
let _ = conn.feed(b"HTTP/1.1 204 No Content\r\n\r\n");
assert!(matches!(conn.poll().unwrap(), ClientEvent::Response(_)));
assert!(matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd));
assert!(matches!(conn.poll().unwrap(), ClientEvent::Idle));Implementations§
Source§impl ClientConn
impl ClientConn
Sourcepub fn with_limits(limits: Limits) -> Self
pub fn with_limits(limits: Limits) -> Self
A connection enforcing limits on responses.
§Examples
let conn = http_net::ClientConn::with_limits(http_net::Limits::new().with_max_body(1 << 24));
assert_eq!(conn.limits().max_body(), 1 << 24);Sourcepub fn limits(&self) -> &Limits
pub fn limits(&self) -> &Limits
The limits this connection enforces.
§Examples
assert_eq!(http_net::ClientConn::new().limits().max_headers(), 100);Sourcepub fn feed(&mut self, bytes: &[u8]) -> usize
pub fn feed(&mut self, bytes: &[u8]) -> usize
Copies as much of bytes into the input buffer as fits; returns how
many were taken (see ServerConn::feed).
§Examples
let mut conn = http_net::ClientConn::new();
assert_eq!(conn.feed(b"HTTP/1.1"), 8);Sourcepub fn feed_eof(&mut self)
pub fn feed_eof(&mut self)
Records that the server closed its sending side: ends a body that
runs until close, or reports HttpError::UnexpectedEof mid-message.
§Examples
use http_net::{ClientConn, ClientEvent, Request};
let mut conn = ClientConn::new();
conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new()).unwrap();
let _ = conn.feed(b"HTTP/1.0 200 OK\r\n\r\nall of it");
assert!(matches!(conn.poll().unwrap(), ClientEvent::Response(_)));
assert!(matches!(conn.poll().unwrap(), ClientEvent::Body(b"all of it")));
assert!(matches!(conn.poll().unwrap(), ClientEvent::NeedInput));
conn.feed_eof();
assert!(matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd));
assert!(matches!(conn.poll().unwrap(), ClientEvent::Closed));Sourcepub fn send_request(
&mut self,
request: &Request,
out: &mut Vec<u8>,
) -> Result<(), HttpError>
pub fn send_request( &mut self, request: &Request, out: &mut Vec<u8>, ) -> Result<(), HttpError>
Writes request into out and starts waiting for its response.
A full body is sent with content-length (omitted for an empty body
on methods that do not expect one); a streamed body continues with
send_body and end_body.
§Errors
- the first error recorded by the
Requestbuilder; HttpError::MissingHostwhen the request has nohostheader;HttpError::InvalidStatewhen a request is already outstanding or the connection is closed.
§Examples
use http_net::{ClientConn, HttpError, Request};
let mut conn = ClientConn::new();
let mut out = Vec::new();
assert_eq!(conn.send_request(&Request::get("/"), &mut out), Err(HttpError::MissingHost));
conn.send_request(&Request::post("/f").header("host", "a").body(&b"xyz"[..]), &mut out).unwrap();
assert_eq!(out, b"POST /f HTTP/1.1\r\nhost: a\r\ncontent-length: 3\r\n\r\nxyz");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 request.
§Errors
HttpError::BodyLengthMismatch past the declared length;
HttpError::InvalidState when no streamed request is in progress.
§Examples
use http_net::{ClientConn, Request};
let mut conn = ClientConn::new();
let mut out = Vec::new();
conn.send_request(&Request::post("/up").header("host", "a").chunked(), &mut out).unwrap();
conn.send_body(b"part", &mut out).unwrap();
conn.end_body(&mut out).unwrap();
assert!(out.ends_with(b"4\r\npart\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 request body.
§Errors
HttpError::BodyLengthMismatch when fewer bytes than declared were
sent; HttpError::InvalidState when no streamed request is in
progress.
§Examples
use http_net::{ClientConn, Request};
let mut conn = ClientConn::new();
let mut out = Vec::new();
conn.send_request(&Request::post("/").header("host", "a").content_length(2), &mut out).unwrap();
conn.send_body(b"ok", &mut out).unwrap();
conn.end_body(&mut out).unwrap();
assert!(out.ends_with(b"\r\n\r\nok"));Sourcepub fn poll(&mut self) -> Result<ClientEvent<'_>, HttpError>
pub fn poll(&mut self) -> Result<ClientEvent<'_>, HttpError>
Advances the response parser and reports what happened.
§Errors
Any HttpError parse error; the connection is then closed and must
not be reused.
§Examples
use http_net::{ClientConn, HttpError, Request};
let mut conn = ClientConn::new();
conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new()).unwrap();
let _ = conn.feed(b"HTTP/1.1 200 OK\r\nContent-Length: 1\r\nContent-Length: 1\r\n\r\nx");
assert_eq!(conn.poll().unwrap_err(), HttpError::DuplicateContentLength);Sourcepub fn response(&self) -> Option<ResponseHead<'_>>
pub fn response(&self) -> Option<ResponseHead<'_>>
The current response’s head, from its arrival until the next request is sent (still available after an upgrade).
§Examples
use http_net::{ClientConn, ClientEvent, Request};
let mut conn = ClientConn::new();
conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new()).unwrap();
let _ = conn.feed(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
while !matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd) {}
assert_eq!(conn.response().unwrap().status(), 200);Sourcepub fn is_upgraded(&self) -> bool
pub fn is_upgraded(&self) -> bool
Whether the server switched protocols and the connection now belongs to another protocol.
§Examples
assert!(!http_net::ClientConn::new().is_upgraded());Sourcepub fn remaining_input(&self) -> &[u8] ⓘ
pub fn remaining_input(&self) -> &[u8] ⓘ
Input that arrived after the last message parsed: after
ClientEvent::Upgraded, the first bytes of the new protocol.
§Examples
use http_net::{ClientConn, ClientEvent, Request};
let mut conn = ClientConn::new();
conn.send_request(&Request::get("/").header("host", "a").upgrade("x"), &mut Vec::new()).unwrap();
let _ = conn.feed(b"HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nUpgrade: x\r\n\r\nhi");
assert!(matches!(conn.poll().unwrap(), ClientEvent::Response(_)));
assert!(matches!(conn.poll().unwrap(), ClientEvent::Upgraded));
assert_eq!(conn.remaining_input(), b"hi");