Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Hyper 1.0 #520

Merged
merged 33 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
bcd8ffe
wip
chrislearn Nov 15, 2023
137f37d
Merge branch 'main' into hyper1
chrislearn Nov 23, 2023
06a345f
wip
chrislearn Nov 26, 2023
a70ed2b
wip
chrislearn Nov 26, 2023
bc701d4
wip
chrislearn Nov 26, 2023
4caae62
Format Rust code using rustfmt
github-actions[bot] Nov 26, 2023
d3f74ec
chore(deps): update rustls-pemfile requirement from 1 to 2
dependabot[bot] Nov 30, 2023
4956c2a
wip
chrislearn Nov 30, 2023
09dc72c
Merge branch 'dependabot/cargo/rustls-pemfile-2' into rustls-deps
chrislearn Dec 5, 2023
85aedaf
wip
chrislearn Dec 5, 2023
fb35c8f
Merge branch 'main' into rustls-deps
chrislearn Dec 5, 2023
f530304
rustls
chrislearn Dec 6, 2023
fdcb152
Merge branch 'rustls-deps' into hyper1
chrislearn Dec 6, 2023
05e805b
u
chrislearn Dec 11, 2023
7646332
Merge branch 'main' into hyper1
chrislearn Dec 11, 2023
b1ecb33
wip
chrislearn Dec 12, 2023
c35ed79
Format Rust code using rustfmt
github-actions[bot] Dec 12, 2023
b5450ed
wip
chrislearn Dec 12, 2023
bc37309
wip
chrislearn Dec 12, 2023
f47e0fb
wip
chrislearn Dec 12, 2023
21f85ad
Format Rust code using rustfmt
github-actions[bot] Dec 12, 2023
eeb672f
wip
chrislearn Dec 12, 2023
627ae28
cargo clippy
chrislearn Dec 12, 2023
19d51e9
wip
chrislearn Dec 12, 2023
07ddf3d
wip
chrislearn Dec 12, 2023
d996fbd
wip
chrislearn Dec 13, 2023
c19c540
wip
chrislearn Dec 13, 2023
e2c77f5
fix tower compact
chrislearn Dec 13, 2023
9be5eca
Format Rust code using rustfmt
github-actions[bot] Dec 13, 2023
b106fa7
Merge branch 'main' into hyper1
chrislearn Dec 13, 2023
1629c94
Update version 0.61.0
chrislearn Dec 13, 2023
f68156f
fix ci
chrislearn Dec 13, 2023
1e52b26
Format Rust code using rustfmt
github-actions[bot] Dec 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <chrislearn@hotmail.com>"]
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