pub struct Request {
pub method: String,
pub path: String,
pub query: Vec<(String, String)>,
pub headers: Vec<(String, String)>,
pub body: Vec<u8>,
pub remote: Option<IpAddr>,
}Expand description
A request as the router sees it: method, path without query, decoded query pairs, headers, and the body.
Fields§
§method: StringGET, POST, … as received (a HEAD arrives as GET).
path: StringThe path without the query string.
query: Vec<(String, String)>The query pairs, percent-decoded, in order.
headers: Vec<(String, String)>Header names and values as received; looked up case-insensitively.
body: Vec<u8>The body, raw.
remote: Option<IpAddr>The address the request came from, when it came over a socket. A request built in this process (a test, the Cockpit composing a call) has none, and is this machine’s.
Implementations§
Source§impl Request
impl Request
Sourcepub fn parse_target(method: &str, target: &str, body: Vec<u8>) -> Self
pub fn parse_target(method: &str, target: &str, body: Vec<u8>) -> Self
Split a request target (/api/v1/objects?kind=rule) into path and decoded pairs.
use majordomus_cli::http::Request;
let r = Request::parse_target("GET", "/api/v1/search?query=Git%20is&limit=2", vec![]);
assert_eq!(r.path, "/api/v1/search");
assert_eq!(r.query, vec![("query".to_string(), "Git is".to_string()), ("limit".to_string(), "2".to_string())]);Sourcepub fn bind(method: HttpMethod, path: &str, input: &Value) -> Self
pub fn bind(method: HttpMethod, path: &str, input: &Value) -> Self
The request that carries input to a capability’s route the way the binding says:
GET puts every top-level property that is not null on the query string (a
scalar as its text, anything else as JSON), POST sends the input as the body.
The inverse of the router’s binding, so a benchmark case reaches the route as a
client would send it.
use majordomus_cli::capability::HttpMethod;
use majordomus_cli::http::Request;
use serde_json::json;
let r = Request::bind(HttpMethod::Get, "/api/v1/search", &json!({ "query": "a b", "limit": 2, "kind": null }));
assert_eq!(r.path, "/api/v1/search");
assert_eq!(r.query, vec![("query".to_string(), "a b".to_string()), ("limit".to_string(), "2".to_string())]);
let p = Request::bind(HttpMethod::Post, "/api/v1/peers/announce", &json!({ "intent": "x" }));
assert_eq!(p.body, br#"{"intent":"x"}"#);Sourcepub fn target(&self) -> String
pub fn target(&self) -> String
The request target this request would be sent as: the path with the query string, percent-encoded.
use majordomus_cli::capability::HttpMethod;
use majordomus_cli::http::Request;
let r = Request::bind(HttpMethod::Get, "/api/v1/search", &serde_json::json!({ "query": "a b&c" }));
assert_eq!(r.target(), "/api/v1/search?query=a%20b%26c");Sourcepub fn with_headers(self, headers: Vec<(String, String)>) -> Self
pub fn with_headers(self, headers: Vec<(String, String)>) -> Self
The same request with its headers.
Sourcepub fn with_remote(self, address: Option<IpAddr>) -> Self
pub fn with_remote(self, address: Option<IpAddr>) -> Self
The same request, as having come from address.
use majordomus_cli::http::Request;
let r = Request::parse_target("GET", "/", vec![]).with_remote(Some("10.0.0.2".parse().unwrap()));
assert_eq!(r.remote, Some("10.0.0.2".parse().unwrap()));Sourcepub fn is_remote(&self) -> bool
pub fn is_remote(&self) -> bool
Did this request come from another host?
Loopback is this machine, in either family and in the IPv4-mapped IPv6 form a dual-stack socket reports. A request with no address was built in this process.
use majordomus_cli::http::Request;
let r = |a: &str| Request::parse_target("POST", "/", vec![]).with_remote(Some(a.parse().unwrap()));
assert!(!r("127.0.0.1").is_remote());
assert!(!r("::1").is_remote());
assert!(!r("::ffff:127.0.0.1").is_remote());
assert!(r("192.168.100.30").is_remote());
assert!(r("100.92.246.32").is_remote());
assert!(r("::ffff:10.0.0.2").is_remote());
assert!(!Request::parse_target("POST", "/", vec![]).is_remote());Sourcepub fn header(&self, name: &str) -> Option<&str>
pub fn header(&self, name: &str) -> Option<&str>
A header value, by case-insensitive name.
use majordomus_cli::http::Request;
let r = Request::parse_target("POST", "/mcp", vec![])
.with_headers(vec![("Mcp-Session-Id".into(), "abc".into())]);
assert_eq!(r.header("mcp-session-id"), Some("abc"));
assert_eq!(r.header("x-none"), None);