Skip to main content

Request

Struct Request 

Source
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

Source

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");
Source

pub fn get(target: &str) -> Self

A GET request.

§Examples
assert_eq!(http_net::Request::get("/").method(), "GET");
Source

pub fn post(target: &str) -> Self

A POST request.

§Examples
assert_eq!(http_net::Request::post("/").method(), "POST");
Source

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");
Source

pub fn put(target: &str) -> Self

A PUT request.

§Examples
assert_eq!(http_net::Request::put("/files/a").method(), "PUT");
Source

pub fn delete(target: &str) -> Self

A DELETE request.

§Examples
assert_eq!(http_net::Request::delete("/files/a").method(), "DELETE");
Source

pub fn options(target: &str) -> Self

An OPTIONS request; * asks about the server as a whole.

§Examples
assert_eq!(http_net::Request::options("*").target(), "*");
Source

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.

Every name the client lists in Connection is dropped, as RFC 9110 section 7.6.1 requires, including end-to-end names such as authorization or x-forwarded-for: a client can strip fields a proxy relies on this way. Check connection_options first if the next hop must see one of them. Listing host drops it too, and the request then fails closed at send (no Host).

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

pub fn header(self, name: &str, value: impl AsRef<[u8]>) -> Self

Adds a header field, validated as for Response::header, except that te is allowed on a request. A second host, or a host value that is not host[:port], 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"*/*"[..]));
Source

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"[..]));
Source

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

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

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();
Source

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

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; anything else is refused with HttpError::InvalidHeaderValue. 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)
);
Source

pub fn method(&self) -> &str

The method text.

§Examples
assert_eq!(http_net::Request::new("OPTIONS", "*").method(), "OPTIONS");
Source

pub fn target(&self) -> &str

The request target.

§Examples
assert_eq!(http_net::Request::get("/a?b").target(), "/a?b");
Source

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(&[][..]));
Source

pub fn header_value(&self, name: &str) -> Option<&[u8]>

The value of the first header named name added to this request.

§Examples
let r = http_net::Request::get("/").header("host", "a");
assert_eq!(r.header_value("HOST"), Some(&b"a"[..]));

Trait Implementations§

Source§

impl Clone for Request

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
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>.

Source§

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

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

impl Eq for Request

Source§

impl PartialEq for Request

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Request

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.