Summary
impl<T> TryFrom<http::Request<T>> for reqwest::blocking::Request currently destructures only method, uri, and headers from http::request::Parts, then builds a fresh inner async request. That silently resets version to Version::default() and replaces extensions with an empty set.
The async reqwest::Request conversion preserves both fields, so the blocking implementation is inconsistent.
Reproduction
use http::{Request as HttpRequest, Version};
use reqwest::blocking::Request as BlockingRequest;
use reqwest::Request as AsyncRequest;
use std::convert::TryFrom;
fn main() {
let src = HttpRequest::builder()
.method("GET")
.uri("http://localhost/")
.version(Version::HTTP_2)
.body("hello")
.unwrap();
let blocking = BlockingRequest::try_from(src).unwrap();
// Fails today: blocking.version() is HTTP/1.1
assert_eq!(blocking.version(), Version::HTTP_2);
}
For comparison, the async conversion preserves the version:
let src = HttpRequest::builder()
.method("GET")
.uri("http://localhost/")
.version(Version::HTTP_2)
.body("hello")
.unwrap();
let async_req = AsyncRequest::try_from(src).unwrap();
assert_eq!(async_req.version(), Version::HTTP_2); // passes
Expected behavior
Converting http::Request<T> into reqwest::blocking::Request should preserve the source request semantics, including:
version
extensions
- already-preserved fields like
method, uri, headers, and body
Actual behavior
The blocking conversion drops version and extensions and replaces them with defaults from async_impl::Request::new(...).
Impact
- Non-default versions (for example
HTTP_2 or HTTP_10) are silently lost.
- The loss is externally observable immediately via
blocking::Request::version(), and it also affects the request that is ultimately sent because the blocking client forwards the inner async request into the async execution path.
extensions are also discarded, making blocking and async conversions semantically inconsistent.
Summary
impl<T> TryFrom<http::Request<T>> for reqwest::blocking::Requestcurrently destructures onlymethod,uri, andheadersfromhttp::request::Parts, then builds a fresh inner async request. That silently resetsversiontoVersion::default()and replacesextensionswith an empty set.The async
reqwest::Requestconversion preserves both fields, so the blocking implementation is inconsistent.Reproduction
For comparison, the async conversion preserves the version:
Expected behavior
Converting
http::Request<T>intoreqwest::blocking::Requestshould preserve the source request semantics, including:versionextensionsmethod,uri,headers, andbodyActual behavior
The blocking conversion drops
versionandextensionsand replaces them with defaults fromasync_impl::Request::new(...).Impact
HTTP_2orHTTP_10) are silently lost.blocking::Request::version(), and it also affects the request that is ultimately sent because the blocking client forwards the inner async request into the async execution path.extensionsare also discarded, making blocking and async conversions semantically inconsistent.