diff --git a/src/http_interop.rs b/src/http_interop.rs index f2876121..26cda2e5 100644 --- a/src/http_interop.rs +++ b/src/http_interop.rs @@ -169,6 +169,24 @@ impl From for http::Response> { /// # Ok(()) /// # } /// ``` +/// +/// # Converting from [`http::Request`] +/// +/// Notably `ureq` does _not_ implement the conversion from [`http::Request`] because it contains +/// the body of a request together with the actual request data. However, [`http`] provides +/// [`http::Request::into_parts()`] to split out a request into [`http::request::Parts`] and a +/// `body`, for which the conversion _is_ implemented and can be used as follows: +/// +/// ``` +/// # fn main() -> Result<(), ureq::Error> { +/// # ureq::is_test(true); +/// let http_request = http::Request::builder().method("GET").uri("http://example.com").body(vec![0u8]).unwrap(); +/// let (http_parts, body) = http_request.into_parts(); +/// let request: ureq::Request = http_parts.into(); +/// request.send_bytes(&body)?; +/// # Ok(()) +/// # } +/// ``` impl From for Request { fn from(value: http::request::Builder) -> Self { let mut new_request = crate::agent().request( @@ -197,6 +215,43 @@ impl From for Request { } } +/// Converts [`http::request::Parts`] into a [`Request`]. +/// +/// Requires feature `ureq = { version = "*", features = ["http"] }` +/// +/// An [`http::Request`] can be split out into its [`http::request::Parts`] and body as follows: +/// +/// ``` +/// # fn main() -> Result<(), ureq::Error> { +/// # ureq::is_test(true); +/// let http_request = http::Request::builder().method("GET").uri("http://example.com").body(vec![0u8]).unwrap(); +/// let (http_parts, body) = http_request.into_parts(); +/// let request: ureq::Request = http_parts.into(); +/// request.send_bytes(&body)?; +/// # Ok(()) +/// # } +/// ``` +impl From for Request { + fn from(value: http::request::Parts) -> Self { + let mut new_request = crate::agent().request(value.method.as_str(), &value.uri.to_string()); + + for (name, value) in &value.headers { + // TODO: Aren't complete header values available as raw byte slices? + let mut raw_header: Vec = name.to_string().into_bytes(); + raw_header.extend(b": "); + raw_header.extend(value.as_bytes()); + + let header = HeaderLine::from(raw_header) + .into_header() + .expect("Unreachable"); + + crate::header::add_header(&mut new_request.headers, header) + } + + new_request + } +} + /// Converts a [Request](crate::Request) into an [http] [Builder](http::request::Builder). /// /// This will only convert valid UTF-8 header values into headers on the