use ureq (with native-tls) instead of curl

Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
Dietmar Maurer 2022-02-01 08:09:44 +01:00
parent bdcecd3214
commit f3ddce5297
3 changed files with 67 additions and 75 deletions

View File

@ -16,12 +16,13 @@ path = "src/lib.rs"
[dependencies]
anyhow = "1.0"
curl = { version = "0.4.33" }
http = "0.2"
nix = "0.19.1"
openidconnect = { version = "2.1", default-features = false, features = ["curl"] }
openidconnect = { version = "2.2", default-features = false, features = [] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror="1.0"
ureq = { version = "2.4", features = ["native-tls"] }
url = "2.1"
proxmox-time = "1"

14
debian/control vendored
View File

@ -2,20 +2,22 @@ Source: rust-proxmox-openid
Section: rust
Priority: optional
Build-Depends: debhelper (>= 12),
dh-cargo (>= 24),
dh-cargo (>= 25),
cargo:native <!nocheck>,
rustc:native <!nocheck>,
libstd-rust-dev <!nocheck>,
librust-anyhow-1+default-dev <!nocheck>,
librust-curl-0.4+default-dev (>= 0.4.33-~~) <!nocheck>,
librust-http-0.2+default-dev <!nocheck>,
librust-nix-0.19+default-dev (>= 0.19.1-~~) <!nocheck>,
librust-openidconnect-2+curl-dev (>= 2.1-~~) <!nocheck>,
librust-openidconnect-2-dev (>= 2.2-~~) <!nocheck>,
librust-proxmox-sys-0.2+default-dev <!nocheck>,
librust-proxmox-time-1+default-dev <!nocheck>,
librust-serde-1+default-dev <!nocheck>,
librust-serde-1+derive-dev <!nocheck>,
librust-serde-json-1+default-dev <!nocheck>,
librust-thiserror-1+default-dev <!nocheck>,
librust-ureq-2+default-dev (>= 2.4-~~) <!nocheck>,
librust-ureq-2+native-tls-dev (>= 2.4-~~) <!nocheck>,
librust-url-2+default-dev (>= 2.1-~~) <!nocheck>
Maintainer: Proxmox Support Team <support@proxmox.com>
Standards-Version: 4.5.1
@ -29,15 +31,17 @@ Multi-Arch: same
Depends:
${misc:Depends},
librust-anyhow-1+default-dev,
librust-curl-0.4+default-dev (>= 0.4.33-~~),
librust-http-0.2+default-dev,
librust-nix-0.19+default-dev (>= 0.19.1-~~),
librust-openidconnect-2+curl-dev (>= 2.1-~~),
librust-openidconnect-2-dev (>= 2.2-~~),
librust-proxmox-sys-0.2+default-dev,
librust-proxmox-time-1+default-dev,
librust-serde-1+default-dev,
librust-serde-1+derive-dev,
librust-serde-json-1+default-dev,
librust-thiserror-1+default-dev,
librust-ureq-2+default-dev (>= 2.4-~~),
librust-ureq-2+native-tls-dev (>= 2.4-~~),
librust-url-2+default-dev (>= 2.1-~~)
Provides:
librust-proxmox-openid+default-dev (= ${binary:Version}),

View File

@ -1,6 +1,3 @@
use std::io::Read;
use curl::easy::Easy;
use http::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
use http::method::Method;
use http::status::StatusCode;
@ -10,83 +7,73 @@ use openidconnect::{
HttpResponse,
};
/// Synchronous Curl HTTP client.
// Copied from OAuth2 create, because we want to use ureq with
// native-tls. But current OAuth2 crate pulls in rustls, so we cannot
// use their 'ureq' feature.
///
/// Copied fron OAuth2 create, added fix https://github.com/ramosbugs/oauth2-rs/pull/147
pub fn http_client(request: HttpRequest) -> Result<HttpResponse, openidconnect::curl::Error> {
/// Error type returned by failed ureq HTTP requests.
///
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Non-ureq HTTP error.
#[error("HTTP error")]
Http(#[from] http::Error),
/// IO error
#[error("IO error")]
IO(#[from] std::io::Error),
/// Other error.
#[error("Other error: {}", _0)]
Other(String),
/// Error returned by ureq crate.
// boxed due to https://github.com/algesten/ureq/issues/296
#[error("ureq request failed")]
Ureq(#[from] Box<ureq::Error>),
}
use openidconnect::curl::Error;
let mut easy = Easy::new();
easy.url(&request.url.to_string()[..])
.map_err(Error::Curl)?;
///
/// Synchronous HTTP client for ureq.
///
pub fn http_client(request: HttpRequest) -> Result<HttpResponse, Error> {
let mut req = if let Method::POST = request.method {
ureq::post(&request.url.to_string())
} else {
ureq::get(&request.url.to_string())
};
let mut headers = curl::easy::List::new();
request
.headers
.iter()
.map(|(name, value)| {
headers
.append(&format!(
"{}: {}",
name,
value.to_str().map_err(|_| Error::Other(format!(
for (name, value) in request.headers {
if let Some(name) = name {
req = req.set(
&name.to_string(),
value.to_str().map_err(|_| {
Error::Other(format!(
"invalid {} header value {:?}",
name,
value.as_bytes()
)))?
))
.map_err(Error::Curl)
})
.collect::<Result<_, _>>()?;
))
})?,
);
}
}
easy.http_headers(headers).map_err(Error::Curl)?;
if let Method::POST = request.method {
easy.post(true).map_err(Error::Curl)?;
easy.post_field_size(request.body.len() as u64)
.map_err(Error::Curl)?;
let response = if let Method::POST = request.method {
req.send(&*request.body)
} else {
assert_eq!(request.method, Method::GET);
req.call()
}
.map_err(Box::new)?;
let mut form_slice = &request.body[..];
let mut data = Vec::new();
{
let mut transfer = easy.transfer();
let status_code = StatusCode::from_u16(response.status())
.map_err(|err| Error::Http(err.into()))?;
transfer
.read_function(|buf| Ok(form_slice.read(buf).unwrap_or(0)))
.map_err(Error::Curl)?;
transfer
.write_function(|new_data| {
data.extend_from_slice(new_data);
Ok(new_data.len())
})
.map_err(Error::Curl)?;
transfer.perform().map_err(Error::Curl)?;
}
let status_code = easy.response_code().map_err(Error::Curl)? as u16;
let content_type = HeaderValue::from_str(response.content_type())
.map_err(|err| Error::Http(err.into()))?;
Ok(HttpResponse {
status_code: StatusCode::from_u16(status_code).map_err(|err| Error::Http(err.into()))?,
headers: easy
.content_type()
.map_err(Error::Curl)?
.map(|content_type| {
Ok(vec![(
CONTENT_TYPE,
HeaderValue::from_str(content_type).map_err(|err| Error::Http(err.into()))?,
)]
.into_iter()
.collect::<HeaderMap>())
})
.transpose()?
.unwrap_or_else(HeaderMap::new),
body: data,
status_code,
headers: vec![(CONTENT_TYPE, content_type)]
.into_iter()
.collect::<HeaderMap>(),
body: response.into_string()?.as_bytes().into(),
})
}