Skip to content

Commit

Permalink
Upgrade to Hyper 1.0 (#520)
Browse files Browse the repository at this point in the history
* wip

* wip

* wip

* wip

* Format Rust code using rustfmt

* chore(deps): update rustls-pemfile requirement from 1 to 2

Updates the requirements on [rustls-pemfile](https://github.com/rustls/pemfile) to permit the latest version.
- [Release notes](https://github.com/rustls/pemfile/releases)
- [Commits](rustls/pemfile@v/1.0.0...v/1.0.4)

---
updated-dependencies:
- dependency-name: rustls-pemfile
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>

* wip

* wip

* rustls

* u

* wip

* Format Rust code using rustfmt

* wip

* wip

* wip

* Format Rust code using rustfmt

* wip

* cargo clippy

* wip

* wip

* wip

* wip

* fix tower compact

* Format Rust code using rustfmt

* Update version 0.61.0

* fix ci

* Format Rust code using rustfmt

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 13, 2023
1 parent 59a6b13 commit 79ec353
Show file tree
Hide file tree
Showing 53 changed files with 1,011 additions and 598 deletions.
66 changes: 31 additions & 35 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"

[workspace.package]
version = "0.61.0"
version = "0.62.0"
authors = ["Chrislearn Young <[email protected]>"]
edition = "2021"
rust-version = "1.70"
Expand All @@ -16,14 +16,27 @@ documentation = "https://docs.rs/salvo/"
readme = "./README.md"
keywords = ["http", "async", "web", "framework", "server"]
license = "MIT OR Apache-2.0"
categories = [
"web-programming::http-server",
"web-programming::websocket",
"network-programming",
"asynchronous",
]
categories = ["web-programming::http-server", "web-programming::websocket", "network-programming", "asynchronous"]

[workspace.dependencies]
salvo_macros = { version = "0.62.0", path = "crates/macros", default-features = false }
salvo_core = { version = "0.62.0", path = "crates/core", default-features = false }
salvo_extra = { version = "0.62.0", path = "crates/extra", default-features = false }
salvo-compression = { version = "0.62.0", path = "crates/compression", default-features = false }
salvo-cache = { version = "0.62.0", path = "crates/cache", default-features = false }
salvo-cors = { version = "0.62.0", path = "crates/cors", default-features = false }
salvo-csrf = { version = "0.62.0", path = "crates/csrf", default-features = false }
salvo-flash = { version = "0.62.0", path = "crates/flash", default-features = false }
salvo-http3 = { version = "0.0.5", default-features = false }
salvo-jwt-auth = { version = "0.62.0", path = "crates/jwt-auth", default-features = false }
salvo-oapi = { version = "0.62.0", path = "./crates/oapi", default-features = false }
salvo-oapi-macros = { version = "0.62.0", path = "crates/oapi-macros", default-features = false }
salvo-otel = { version = "0.62.0", path = "crates/otel", default-features = false }
salvo-proxy = { version = "0.62.0", path = "crates/proxy", default-features = false }
salvo-rate-limiter = { version = "0.62.0", path = "crates/rate-limiter", default-features = false }
salvo-serve-static = { version = "0.62.0", path = "crates/serve-static", default-features = false }
salvo-session = { version = "0.62.0", path = "crates/session", default-features = false }

aead = "0.5"
aes-gcm = "0.10"
anyhow = "1"
Expand All @@ -47,13 +60,15 @@ fastrand = "2"
form_urlencoded = "1"
futures-channel = "0.3"
futures-util = { version = "0.3", default-features = false }
headers = "0.3"
http = "0.2"
http-body-util = "0.1.0-rc.3"
headers = "0.4"
http = "1"
http-body-util = "0.1"
hmac = "0.12"
hex = "0.4"
hostname-validator = "1"
hyper = "=1.0.0-rc.4"
hyper = { version = "1", features = ["full"] }
hyper-util = { version = "0.1.1", default-features = true }
hyper-tls = "0.6"
indexmap = "2"
inventory = "0.3"
jsonwebtoken = "9.1"
Expand Down Expand Up @@ -82,30 +97,11 @@ quote = "1"
rand = "0.8"
rcgen = "0.11"
regex = "1"
reqwest = { version = "0.11", default-features = false }
ring = "0.17"
rust_decimal = "1"
rustls = "0.21"
rustls-pemfile = "1"
rust-embed = { version = ">= 6, <= 9" }
salvo-utils = { version = "0.0.6", default-features = true }
salvo_macros = { version = "0.61.0", path = "crates/macros", default-features = false }
salvo_core = { version = "0.61.0", path = "crates/core", default-features = false }
salvo_extra = { version = "0.61.0", path = "crates/extra", default-features = false }
salvo-compression = { version = "0.61.0", path = "crates/compression", default-features = false }
salvo-cache = { version = "0.61.0", path = "crates/cache", default-features = false }
salvo-cors = { version = "0.61.0", path = "crates/cors", default-features = false }
salvo-csrf = { version = "0.61.0", path = "crates/csrf", default-features = false }
salvo-flash = { version = "0.61.0", path = "crates/flash", default-features = false }
salvo-http3 = { version = "0.0.4", default-features = false }
salvo-jwt-auth = { version = "0.61.0", path = "crates/jwt-auth", default-features = false }
salvo-oapi = { version = "0.61.0", path = "./crates/oapi", default-features = false }
salvo-oapi-macros = { version = "0.61.0", path = "crates/oapi-macros", default-features = false }
salvo-otel = { version = "0.61.0", path = "crates/otel", default-features = false }
salvo-proxy = { version = "0.61.0", path = "crates/proxy", default-features = false }
salvo-rate-limiter = { version = "0.61.0", path = "crates/rate-limiter", default-features = false }
salvo-serve-static = { version = "0.61.0", path = "crates/serve-static", default-features = false }
salvo-session = { version = "0.61.0", path = "crates/session", default-features = false }
rustls = "0.22"
rustls-pemfile = "2"
rust-embed = { version = ">= 6, <= 8" }
serde = "1"
serde_json = "1"
serde-xml-rs = "0.6"
Expand All @@ -120,7 +116,7 @@ thiserror = "1"
time = "0.3"
tokio = "1"
tokio-native-tls = "0.3"
tokio-rustls = "0.24"
tokio-rustls = "0.25"
tokio-openssl = "0.6"
tokio-stream = { version = "0.1", default-features = false }
tokio-tungstenite = { version = "0.21", default-features = false }
Expand All @@ -137,4 +133,4 @@ x509-parser = "0.15"
# Compress
brotli = { version = "3.3", default-features = false }
flate2 = { version = "1.0", default-features = false }
zstd = { version = "0.13", default-features = false }
zstd = { version = "0.13", default-features = false }
11 changes: 7 additions & 4 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ cookie = ["dep:cookie"]
http1 = []
fix-http1-request-uri = ["http1"]
http2 = ["hyper/http2"]
quinn = ["dep:salvo-http3", "dep:quinn", "rustls"]
quinn = ["dep:salvo-http3", "dep:quinn", "dep:tokio-rustls-old", "dep:rustls-pemfile-old", "rustls"]
rustls = ["http1", "http2", "dep:tokio-rustls", "dep:rustls-pemfile"]
native-tls = ["http1", "http2", "dep:tokio-native-tls", "dep:native-tls"]
openssl = ["http2", "dep:openssl", "dep:tokio-openssl"]
unix = ["http1"]
test = ["dep:brotli", "dep:flate2", "dep:zstd", "dep:encoding_rs", "dep:serde_urlencoded", "dep:url", "tokio/macros"]
acme = ["http1", "http2", "hyper/client", "dep:reqwest", "dep:rcgen", "dep:ring", "dep:x509-parser", "dep:tokio-rustls", "dep:rustls-pemfile"]
acme = ["http1", "http2", "hyper-util/http1", "hyper-util/http2","hyper-util/client-legacy", "dep:hyper-tls", "dep:rcgen", "dep:ring", "dep:x509-parser", "dep:tokio-rustls", "dep:rustls-pemfile"]
tower-compat = ["dep:tower"]

[dependencies]
rustls-pemfile-old = { version = "1", package = "rustls-pemfile", optional = true }
tokio-rustls-old = { version = "0.24", package = "tokio-rustls", optional = true }

anyhow = { workspace = true, optional = true }
async-trait = { workspace = true }
base64 = { workspace = true }
Expand Down Expand Up @@ -63,12 +66,12 @@ quinn = { workspace = true, optional = true, features = ["runtime-tokio", "ring"
rand = { workspace = true }
rcgen = { workspace = true, optional = true }
regex = { workspace = true }
reqwest = { workspace = true, optional = true, features = ["rustls-tls", "json"] }
ring = { workspace = true, optional = true }
rustls-pemfile = { workspace = true, optional = true }
salvo-http3 = { workspace = true, optional = true, features = ["quinn"] }
salvo_macros = { workspace = true }
salvo-utils = { workspace = true, features = ["runtime"] }
hyper-tls = { workspace = true, optional = true }
hyper-util = { workspace = true, features = ["tokio"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["raw_value"] }
serde-xml-rs = { workspace = true }
Expand Down
94 changes: 48 additions & 46 deletions crates/core/src/conn/acme/client.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use std::{
io::{Error as IoError, ErrorKind, Result as IoResult},
sync::Arc,
time::Duration,
};
use std::sync::Arc;

use base64::engine::{general_purpose::URL_SAFE_NO_PAD, Engine};
use bytes::Bytes;
use http::header;
use reqwest::Client;
use http_body_util::{BodyExt, Full};
use hyper::Uri;
use hyper_tls::HttpsConnector;
use hyper_util::client::legacy::{connect::HttpConnector, Client};
use hyper_util::rt::TokioExecutor;
use serde::{Deserialize, Serialize};

use super::{Challenge, Problem};

use super::{jose, key_pair::KeyPair, ChallengeType};
use super::{Challenge, Problem};
use super::{Directory, Identifier};

use crate::Error;

pub(super) type HyperClient = Client<HttpsConnector<HttpConnector>, Full<Bytes>>;

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct NewOrderResponse {
Expand All @@ -34,7 +36,7 @@ pub(crate) struct FetchAuthorizationResponse {
}

pub(crate) struct AcmeClient {
pub(crate) client: Client,
pub(crate) client: HyperClient,
pub(crate) directory: Directory,
pub(crate) key_pair: Arc<KeyPair>,
pub(crate) contacts: Vec<String>,
Expand All @@ -43,8 +45,8 @@ pub(crate) struct AcmeClient {

impl AcmeClient {
#[inline]
pub(crate) async fn new(directory_url: &str, key_pair: Arc<KeyPair>, contacts: Vec<String>) -> IoResult<Self> {
let client = Client::builder().timeout(Duration::from_secs(30)).build().unwrap();
pub(crate) async fn new(directory_url: &str, key_pair: Arc<KeyPair>, contacts: Vec<String>) -> crate::Result<Self> {
let client = Client::builder(TokioExecutor::new()).build(HttpsConnector::new());
let directory = get_directory(&client, directory_url).await?;
Ok(Self {
client,
Expand All @@ -55,19 +57,19 @@ impl AcmeClient {
})
}

pub(crate) async fn new_order(&mut self, domains: &[String]) -> IoResult<NewOrderResponse> {
pub(crate) async fn new_order(&mut self, domains: &[String]) -> crate::Result<NewOrderResponse> {
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct NewOrderRequest {
identifiers: Vec<Identifier>,
}

impl FetchAuthorizationResponse {
pub(crate) fn find_challenge(&self, ctype: ChallengeType) -> IoResult<&Challenge> {
pub(crate) fn find_challenge(&self, ctype: ChallengeType) -> crate::Result<&Challenge> {
self.challenges
.iter()
.find(|c| c.kind == ctype.to_string())
.ok_or_else(|| IoError::new(ErrorKind::Other, format!("unable to find `{}` challenge", ctype)))
.ok_or_else(|| Error::other(format!("unable to find `{}` challenge", ctype)))
}
}

Expand Down Expand Up @@ -107,7 +109,7 @@ impl AcmeClient {
}

#[inline]
pub(crate) async fn fetch_authorization(&self, auth_url: &str) -> IoResult<FetchAuthorizationResponse> {
pub(crate) async fn fetch_authorization(&self, auth_url: &str) -> crate::Result<FetchAuthorizationResponse> {
tracing::debug!(auth_uri = %auth_url, "fetch authorization");

let nonce = get_nonce(&self.client, &self.directory.new_nonce).await?;
Expand Down Expand Up @@ -136,7 +138,7 @@ impl AcmeClient {
domain: &str,
challenge_type: ChallengeType,
url: &str,
) -> IoResult<()> {
) -> crate::Result<()> {
tracing::debug!(
auth_uri = %url,
domain = domain,
Expand All @@ -159,7 +161,7 @@ impl AcmeClient {
}

#[inline]
pub(crate) async fn send_csr(&self, url: &str, csr: &[u8]) -> IoResult<NewOrderResponse> {
pub(crate) async fn send_csr(&self, url: &str, csr: &[u8]) -> crate::Result<NewOrderResponse> {
tracing::debug!(url = %url, "send certificate request");

#[derive(Debug, Serialize)]
Expand All @@ -183,7 +185,7 @@ impl AcmeClient {
}

#[inline]
pub(crate) async fn obtain_certificate(&self, url: &str) -> IoResult<Bytes> {
pub(crate) async fn obtain_certificate(&self, url: &str) -> crate::Result<Bytes> {
tracing::debug!(url = %url, "send certificate request");

let nonce = get_nonce(&self.client, &self.directory.new_nonce).await?;
Expand All @@ -196,34 +198,35 @@ impl AcmeClient {
None::<()>,
)
.await?;
res.bytes()
.await
.map_err(|e| IoError::new(ErrorKind::Other, format!("failed to download certificate: {}", e)))
Ok(res.into_body().collect().await?.to_bytes())
}
}

async fn get_directory(client: &Client, directory_url: &str) -> IoResult<Directory> {
async fn get_directory(client: &HyperClient, directory_url: &str) -> crate::Result<Directory> {
tracing::debug!("loading directory");

let directory_url = directory_url
.parse::<Uri>()
.map_err(|e| Error::other(format!("failed to parse directory dir: {}", e)))?;
let res = client
.get(directory_url)
.send()
.await
.map_err(|e| IoError::new(ErrorKind::Other, format!("failed to load directory: {}", e)))?;
.map_err(|e| Error::other(format!("failed to load directory: {}", e)))?;

if !res.status().is_success() {
return Err(IoError::new(
ErrorKind::Other,
format!("failed to load directory: status = {}", res.status()),
));
return Err(Error::other(format!(
"failed to load directory: status = {}",
res.status()
)));
}

let data = res
.bytes()
.into_body()
.collect()
.await
.map_err(|e| IoError::new(ErrorKind::Other, format!("failed to read response: {}", e)))?;
.map_err(|e| Error::other(format!("failed to load body: {}", e)))?
.to_bytes();
let directory = serde_json::from_slice::<Directory>(&data)
.map_err(|e| IoError::new(ErrorKind::Other, format!("failed to load directory: {}", e)))?;
.map_err(|e| Error::other(format!("failed to load directory: {}", e)))?;

tracing::debug!(
new_nonce = ?directory.new_nonce,
Expand All @@ -234,20 +237,19 @@ async fn get_directory(client: &Client, directory_url: &str) -> IoResult<Directo
Ok(directory)
}

async fn get_nonce(client: &Client, nonce_url: &str) -> IoResult<String> {
async fn get_nonce(client: &HyperClient, nonce_url: &str) -> crate::Result<String> {
tracing::debug!("creating nonce");

let res = client
.get(nonce_url)
.send()
.get(nonce_url.parse::<Uri>()?)
.await
.map_err(|e| IoError::new(ErrorKind::Other, format!("failed to get nonce: {}", e)))?;
.map_err(|e| Error::other(format!("failed to get nonce: {}", e)))?;

if !res.status().is_success() {
return Err(IoError::new(
ErrorKind::Other,
format!("failed to load directory: status = {}", res.status()),
));
return Err(Error::other(format!(
"failed to load directory: status = {}",
res.status()
)));
}

let nonce = res
Expand All @@ -262,11 +264,11 @@ async fn get_nonce(client: &Client, nonce_url: &str) -> IoResult<String> {
}

async fn create_acme_account(
client: &Client,
client: &HyperClient,
directory: &Directory,
key_pair: &KeyPair,
contacts: Vec<String>,
) -> IoResult<String> {
) -> crate::Result<String> {
tracing::debug!("creating acme account");

#[derive(Serialize)]
Expand All @@ -293,11 +295,11 @@ async fn create_acme_account(
.await?;
let kid = res
.headers()
.get(header::LOCATION)
.ok_or_else(|| IoError::new(ErrorKind::Other, "unable to get account id"))?
.get("location")
.ok_or_else(|| Error::other("unable to get account id"))?
.to_str()
.map(|s| s.to_owned())
.map_err(|_| IoError::new(ErrorKind::Other, "unable to get account id"));
.map_err(|_| Error::other("unable to get account id"));

tracing::debug!(kid = ?kid, "account created");
kid
Expand Down
Loading

0 comments on commit 79ec353

Please sign in to comment.