pub struct Request { /* private fields */ }Expand description
A request for a ClientConn to send.
HTTP/1.1 requires a Host field; the connection refuses to send a
request without one. The request line always says HTTP/1.1.
§Examples
use http_net::Request;
let get = Request::get("/index.html").header("host", "example.com");
let post = Request::post("/api")
.header("host", "example.com")
.header("content-type", "application/json")
.body(br#"{"ok":true}"#.to_vec());
assert_eq!(get.method(), "GET");
assert_eq!(post.target(), "/api");Implementations§
Source§impl Request
impl Request
Sourcepub fn new(method: &str, target: &str) -> Self
pub fn new(method: &str, target: &str) -> Self
A request with method and target, validated when it is sent:
the method must be a token and the target must be in a form the
method allows (/path?query, an absolute URI, host:port for
CONNECT, or * for OPTIONS).
§Examples
let r = http_net::Request::new("PURGE", "/cache/a");
assert_eq!(r.method(), "PURGE");Sourcepub fn head(target: &str) -> Self
pub fn head(target: &str) -> Self
A HEAD request: its response carries headers and no body.
§Examples
assert_eq!(http_net::Request::head("/").method(), "HEAD");Sourcepub fn options(target: &str) -> Self
pub fn options(target: &str) -> Self
An OPTIONS request; * asks about the server as a whole.
§Examples
assert_eq!(http_net::Request::options("*").target(), "*");Sourcepub fn forward_from(head: &RequestHead<'_>) -> Self
pub fn forward_from(head: &RequestHead<'_>) -> Self
A request for an upstream server built from a received head, for a
proxy: the same method and target, every field except the hop-by-hop
ones (RFC 9110 section 7.6.1: connection, keep-alive,
proxy-connection, te, transfer-encoding, upgrade, trailer,
and any name the head’s Connection lists; see
is_hop_by_hop) in their original order,
except content-length, which the connection derives again from
the body mode of the head’s framing: a chunked body stays
chunked, a length stays that length (stream it with
ClientConn::send_body). The
connection writes its own framing and connection fields.
The target is copied as received: an absolute-form target (a request
to a proxy) stays absolute, which an origin server also accepts (RFC
9112 section 3.2.2); rewrite it with Request::new if the upstream
wants origin form. Host is forwarded as a field. Add via and
forwarding fields with header; requests are
re-serialized, never passed through as raw bytes.
§Errors
Recorded and returned by
ClientConn::send_request:
HttpError::InvalidState for an upgrade request (the upgrade is
hop-by-hop; a proxy tunnels it instead), and the builder errors of
Request::new and Request::header (for example a missing or
second host surfaces at send).
§Examples
use http_net::{ClientConn, Request, ServerConn, ServerEvent};
let mut downstream = ServerConn::new();
let _ = downstream.feed(b"POST /api HTTP/1.1\r\nHost: app\r\nConnection: X-Hop\r\nX-Hop: 1\r\nKeep-Alive: timeout=5\r\nAccept: */*\r\nContent-Length: 2\r\n\r\nhi");
let ServerEvent::Request(head) = downstream.poll()? else { unreachable!() };
let upstream_req = Request::forward_from(&head).header("via", "1.1 proxy");
let mut upstream = ClientConn::new();
let mut out = Vec::new();
upstream.send_request(&upstream_req, &mut out)?;
assert_eq!(out, b"POST /api HTTP/1.1\r\nHost: app\r\nAccept: */*\r\nvia: 1.1 proxy\r\ncontent-length: 2\r\n\r\n");Sourcepub fn header(self, name: &str, value: impl AsRef<[u8]>) -> Self
pub fn header(self, name: &str, value: impl AsRef<[u8]>) -> Self
Adds a header field, validated as for Response::header. A second
host is refused with HttpError::InvalidHost.
§Examples
let r = http_net::Request::get("/").header("host", "a").header("accept", "*/*");
assert_eq!(r.header_value("accept"), Some(&b"*/*"[..]));Sourcepub fn body(self, body: impl Into<Cow<'static, [u8]>>) -> Self
pub fn body(self, body: impl Into<Cow<'static, [u8]>>) -> Self
Sets the whole body, sent with content-length.
§Examples
let r = http_net::Request::post("/").body(&b"x=1"[..]);
assert_eq!(r.body_bytes(), Some(&b"x=1"[..]));Sourcepub fn chunked(self) -> Self
pub fn chunked(self) -> Self
Streams the body with chunked encoding through
ClientConn::send_body and
ClientConn::end_body.
§Examples
assert_eq!(http_net::Request::post("/").chunked().body_bytes(), None);Sourcepub fn content_length(self, len: u64) -> Self
pub fn content_length(self, len: u64) -> Self
Streams a body of exactly len bytes.
§Examples
assert_eq!(http_net::Request::post("/").content_length(4).body_bytes(), None);Sourcepub fn close(self) -> Self
pub fn close(self) -> Self
Asks the server to close the connection after its response.
§Examples
let _ = http_net::Request::get("/").header("host", "a").close();Sourcepub fn expect_continue(self) -> Self
pub fn expect_continue(self) -> Self
Sends expect: 100-continue and holds the body back until the
server agrees (RFC 9110 section 10.1.1): for large uploads the
server may refuse from the head alone. The body must be streamed
(content_length or
chunked); send it with
ClientConn::send_body after
ClientEvent::Continue, or after a
wait of your choosing. A final status instead means the server does
not want the body: it must not be sent, and the connection closes
after the response.
§Examples
use http_net::{ClientConn, ClientEvent, HttpError, Request};
let mut conn = ClientConn::new();
let mut out = Vec::new();
let upload = Request::put("/f").header("host", "a").content_length(9).expect_continue();
conn.send_request(&upload, &mut out)?;
assert!(out.ends_with(b"expect: 100-continue\r\ncontent-length: 9\r\n\r\n"));
let _ = conn.feed(b"HTTP/1.1 413 Content Too Large\r\nContent-Length: 0\r\n\r\n");
assert!(matches!(conn.poll()?, ClientEvent::Response(r) if r.status() == 413));
assert!(matches!(conn.send_body(b"too large", &mut out), Err(HttpError::InvalidState(_))));
assert!(matches!(conn.poll()?, ClientEvent::ResponseEnd));
assert!(matches!(conn.poll()?, ClientEvent::Closed));Sourcepub fn upgrade(self, protocol: &str) -> Self
pub fn upgrade(self, protocol: &str) -> Self
Asks to switch the connection to protocol (writes
connection: upgrade and upgrade: <protocol>). A 101 answer
hands the connection over; see
ClientEvent::Upgraded.
protocol is a token or a name/version product token. h2c is
refused with HttpError::UpgradeNotOffered: RFC 9113 section 3.1
deprecates the HTTP/2 upgrade.
§Examples
use http_net::{ClientConn, HttpError, Request};
let r = Request::get("/rpc").header("host", "a").upgrade("websocket");
assert_eq!(r.header_value("upgrade"), Some(&b"websocket"[..]));
let h2c = Request::get("/").header("host", "a").upgrade("h2c");
assert_eq!(
ClientConn::new().send_request(&h2c, &mut Vec::new()),
Err(HttpError::UpgradeNotOffered)
);Sourcepub fn body_bytes(&self) -> Option<&[u8]>
pub fn body_bytes(&self) -> Option<&[u8]>
The full body, or None for a streamed one.
§Examples
assert_eq!(http_net::Request::get("/").body_bytes(), Some(&[][..]));Trait Implementations§
Source§impl Debug for Request
Shows method, target, fields, and body size; the values of credential
fields (authorization, proxy-authorization, cookie) are replaced by
<redacted N bytes>.
impl Debug for Request
Shows method, target, fields, and body size; the values of credential
fields (authorization, proxy-authorization, cookie) are replaced by
<redacted N bytes>.