use super::*;
use ureq::Agent as UreqAgent;
#[cfg_attr(nightly, doc(cfg(feature = "ureq")))]
#[derive(Debug, displaydoc::Display, thiserror::Error)]
#[allow(clippy::large_enum_variant)]
pub enum UreqError {
Ureq(#[from] Box<ureq::Error>),
Http(#[from] http::Error),
Io(#[from] std::io::Error),
InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
InvalidHeaderName(#[from] http::header::InvalidHeaderName),
UrlError(#[from] url::ParseError),
}
#[cfg_attr(nightly, doc(cfg(feature = "ureq")))] impl Client for UreqAgent {
type Error = UreqError;
fn req(&self, request: Request) -> BoxedFuture<'static, Result<Response, Self::Error>> {
use std::io::Read;
let method = request.method().to_string();
let url = request.uri().to_string();
let mut req = self.request(&method, &url);
for (header, value) in request.headers() {
if let Ok(value) = value.to_str() {
req = req.set(header.as_str(), value);
}
}
Box::pin(async move {
let body = request.into_body();
let response = match req
.send_bytes(&body)
.map_err(|err| UreqError::Ureq(Box::new(err)))
{
Ok(val) => val,
Err(err) => return Err(err),
};
let mut result = http::Response::builder().status(response.status());
let headers = result
.headers_mut()
.expect("expected to get headers mut when building response");
for name in response.headers_names() {
if let Some(value) = response.header(&name) {
let value = match http::header::HeaderValue::from_bytes(value.as_bytes())
.map_err(UreqError::InvalidHeaderValue)
{
Ok(val) => val,
Err(err) => return Err(err),
};
let header = match http::header::HeaderName::from_bytes(name.as_bytes())
.map_err(UreqError::InvalidHeaderName)
{
Ok(val) => val,
Err(err) => return Err(err),
};
headers.append(header, value);
}
}
result = result.version(match response.http_version() {
"HTTP/0.9" => http::Version::HTTP_09,
"HTTP/1.0" => http::Version::HTTP_10,
"HTTP/1.1" => http::Version::HTTP_11,
"HTTP/2.0" => http::Version::HTTP_2,
"HTTP/3.0" => http::Version::HTTP_3,
_ => http::Version::HTTP_11,
});
match response
.into_reader()
.take(10_000_000)
.bytes()
.collect::<Result<hyper::body::Bytes, _>>()
{
Ok(v) => result.body(v.into()).map_err(Into::into),
Err(e) => Err(e.into()),
}
})
}
}