From bc22e00a3b1714b7b1bf5146db786e144906ec28 Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Sat, 1 Jun 2024 13:47:27 -0600 Subject: [PATCH] server: Upgrade to Axum 0.7 --- Cargo.lock | 233 +++++++++++++++++++++++-------- server/Cargo.toml | 7 +- server/src/access/http.rs | 4 +- server/src/api/binary_cache.rs | 12 +- server/src/api/v1/upload_path.rs | 6 +- server/src/lib.rs | 6 +- server/src/middleware.rs | 22 +-- 7 files changed, 208 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bfe129..d1f6dba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -295,7 +295,7 @@ dependencies = [ "attic-token", "aws-config", "aws-sdk-s3", - "axum", + "axum 0.7.5", "axum-macros", "base64 0.21.7", "bytes", @@ -309,6 +309,7 @@ dependencies = [ "fastcdc", "futures", "hex", + "http-body-util", "humantime", "humantime-serde", "itoa", @@ -379,8 +380,8 @@ dependencies = [ "bytes", "fastrand", "hex", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.28", "ring", "time", "tokio", @@ -411,8 +412,8 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "pin-project-lite", "tracing", ] @@ -433,7 +434,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "fastrand", - "http", + "http 0.2.12", "percent-encoding", "tracing", "uuid", @@ -460,8 +461,8 @@ dependencies = [ "aws-smithy-xml", "aws-types", "bytes", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "once_cell", "percent-encoding", "regex", @@ -486,7 +487,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http", + "http 0.2.12", "regex", "tracing", ] @@ -508,7 +509,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http", + "http 0.2.12", "regex", "tracing", ] @@ -531,7 +532,7 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", - "http", + "http 0.2.12", "regex", "tracing", ] @@ -550,7 +551,7 @@ dependencies = [ "form_urlencoded", "hex", "hmac", - "http", + "http 0.2.12", "num-bigint", "once_cell", "p256 0.11.1", @@ -586,8 +587,8 @@ dependencies = [ "crc32c", "crc32fast", "hex", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "md-5", "pin-project-lite", "sha1", @@ -618,8 +619,8 @@ dependencies = [ "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "once_cell", "percent-encoding", "pin-project-lite", @@ -658,9 +659,9 @@ dependencies = [ "aws-smithy-types", "bytes", "fastrand", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-rustls", "once_cell", "pin-project-lite", @@ -679,7 +680,7 @@ dependencies = [ "aws-smithy-async", "aws-smithy-types", "bytes", - "http", + "http 0.2.12", "pin-project-lite", "tokio", "tracing", @@ -696,8 +697,8 @@ dependencies = [ "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "itoa", "num-integer", "pin-project-lite", @@ -728,7 +729,7 @@ dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "http", + "http 0.2.12", "rustc_version", "tracing", ] @@ -740,13 +741,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.3.4", "bitflags 1.3.2", "bytes", "futures-util", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 0.1.2", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +dependencies = [ + "async-trait", + "axum-core 0.4.3", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-util", "itoa", "matchit", "memchr", @@ -758,11 +788,12 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -774,8 +805,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "mime", "rustversion", "tower-layer", @@ -783,10 +814,31 @@ dependencies = [ ] [[package]] -name = "axum-macros" -version = "0.3.8" +name = "axum-core" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -1883,7 +1935,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.2.6", "slab", "tokio", @@ -2021,6 +2073,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -2028,15 +2091,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", "pin-project-lite", ] [[package]] -name = "http-range-header" -version = "0.3.1" +name = "http-body" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] [[package]] name = "httparse" @@ -2077,8 +2157,8 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -2090,6 +2170,25 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -2097,8 +2196,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.28", "log", "rustls", "rustls-native-certs", @@ -2112,12 +2211,27 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper", + "hyper 0.14.28", "pin-project-lite", "tokio", "tokio-io-timeout", ] +[[package]] +name = "hyper-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "tokio", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -3086,9 +3200,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-rustls", "ipnet", "js-sys", @@ -3103,7 +3217,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-rustls", @@ -4134,6 +4248,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "system-configuration" version = "0.5.1" @@ -4398,13 +4518,13 @@ checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" dependencies = [ "async-stream", "async-trait", - "axum", + "axum 0.6.20", "base64 0.21.7", "bytes", "h2", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-timeout", "percent-encoding", "pin-project", @@ -4439,17 +4559,16 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "bitflags 2.5.0", "bytes", - "futures-core", "futures-util", - "http", - "http-body", - "http-range-header", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "pin-project-lite", "tower-layer", "tower-service", diff --git a/server/Cargo.toml b/server/Cargo.toml index dd2b657..606281f 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -27,8 +27,8 @@ async-stream = "0.3.5" async-trait = "0.1.68" aws-config = "0.57.1" aws-sdk-s3 = "0.35.0" -axum = "0.6.18" -axum-macros = "0.3.7" +axum = "0.7.5" +axum-macros = "0.4.1" base64 = "0.21.2" bytes = "1.4.0" chrono = "0.4.24" @@ -40,6 +40,7 @@ enum-as-inner = "0.6.0" fastcdc = "3.0.3" futures = "0.3.28" hex = "0.4.3" +http-body-util = "0.1.1" humantime = "2.1.0" humantime-serde = "1.1.1" itoa = "=1.0.5" @@ -53,7 +54,7 @@ serde_json = "1.0.96" serde_with = "3.0.0" tokio-util = { version = "0.7.8", features = [ "io" ] } toml = "0.8.8" -tower-http = { version = "0.4.0", features = [ "catch-panic", "trace" ] } +tower-http = { version = "0.5.2", features = [ "catch-panic", "trace" ] } tracing = "0.1.37" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.17", features = [ "json" ] } diff --git a/server/src/access/http.rs b/server/src/access/http.rs index 0138def..1d108ff 100644 --- a/server/src/access/http.rs +++ b/server/src/access/http.rs @@ -1,6 +1,6 @@ //! HTTP middlewares for access control. -use axum::{http::Request, middleware::Next, response::Response}; +use axum::{extract::Request, middleware::Next, response::Response}; use sea_orm::DatabaseConnection; use tokio::sync::OnceCell; @@ -93,7 +93,7 @@ impl AuthState { } /// Performs auth. -pub async fn apply_auth(req: Request, next: Next) -> Response { +pub async fn apply_auth(req: Request, next: Next) -> Response { let token: Option = req .headers() .get("Authorization") diff --git a/server/src/api/binary_cache.rs b/server/src/api/binary_cache.rs index 0c62ae8..05e6630 100644 --- a/server/src/api/binary_cache.rs +++ b/server/src/api/binary_cache.rs @@ -9,9 +9,8 @@ use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use std::path::PathBuf; use std::sync::Arc; -use axum::body::HttpBody as _; use axum::{ - body::StreamBody, + body::Body, extract::{Extension, Path}, http::StatusCode, response::{IntoResponse, Redirect, Response}, @@ -19,6 +18,7 @@ use axum::{ Router, }; use futures::stream::BoxStream; +use http_body_util::BodyExt; use serde::Serialize; use tokio_util::io::ReaderStream; use tracing::instrument; @@ -218,10 +218,10 @@ async fn get_nar( Download::Url(url) => Ok(Redirect::temporary(&url).into_response()), Download::AsyncRead(stream) => { let stream = ReaderStream::new(stream); - let body = StreamBody::new(stream).map_err(|e| { + let body = Body::from_stream(stream).map_err(|e| { tracing::error!("Stream error: {e}"); e - }); + }).into_inner(); Ok(body.into_response()) } @@ -255,10 +255,10 @@ async fn get_nar( // TODO: Make num_prefetch configurable // The ideal size depends on the average chunk size let merged = merge_chunks(chunks, streamer, storage, 2); - let body = StreamBody::new(merged).map_err(|e| { + let body = Body::from_stream(merged).map_err(|e| { tracing::error!("Stream error: {e}"); e - }); + }).into_inner(); Ok(body.into_response()) } diff --git a/server/src/api/v1/upload_path.rs b/server/src/api/v1/upload_path.rs index ba00b25..3673797 100644 --- a/server/src/api/v1/upload_path.rs +++ b/server/src/api/v1/upload_path.rs @@ -8,7 +8,8 @@ use anyhow::anyhow; use async_compression::tokio::bufread::{BrotliEncoder, XzEncoder, ZstdEncoder}; use async_compression::Level as CompressionLevel; use axum::{ - extract::{BodyStream, Extension, Json}, + body::Body, + extract::{Extension, Json}, http::HeaderMap, }; use bytes::{Bytes, BytesMut}; @@ -120,8 +121,9 @@ pub(crate) async fn upload_path( Extension(state): Extension, Extension(req_state): Extension, headers: HeaderMap, - stream: BodyStream, + body: Body, ) -> ServerResult> { + let stream = body.into_data_stream(); let mut stream = StreamReader::new( stream.map(|r| r.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))), ); diff --git a/server/src/lib.rs b/server/src/lib.rs index 38d3b1a..2aba734 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -26,6 +26,7 @@ pub mod nix_manifest; pub mod oobe; mod storage; +use std::future::IntoFuture; use std::net::SocketAddr; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -38,6 +39,7 @@ use axum::{ Router, }; use sea_orm::{query::Statement, ConnectionTrait, Database, DatabaseConnection}; +use tokio::net::TcpListener; use tokio::sync::OnceCell; use tokio::time; use tower_http::catch_panic::CatchPanicLayer; @@ -221,8 +223,10 @@ pub async fn run_api_server(cli_listen: Option, config: Config) -> R eprintln!("Listening on {:?}...", listen); + let listener = TcpListener::bind(&listen).await?; + let (server_ret, _) = tokio::join!( - axum::Server::bind(&listen).serve(rest.into_make_service()), + axum::serve(listener, rest).into_future(), async { if state.config.database.heartbeat { let _ = state.run_db_heartbeat().await; diff --git a/server/src/middleware.rs b/server/src/middleware.rs index 522c81f..88686e0 100644 --- a/server/src/middleware.rs +++ b/server/src/middleware.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use anyhow::anyhow; use axum::{ - extract::{Extension, Host}, - http::{HeaderValue, Request}, + extract::{Extension, Host, Request}, + http::HeaderValue, middleware::Next, response::Response, }; @@ -14,11 +14,11 @@ use crate::error::{ErrorKind, ServerResult}; use attic::api::binary_cache::ATTIC_CACHE_VISIBILITY; /// Initializes per-request state. -pub async fn init_request_state( +pub async fn init_request_state( Extension(state): Extension, Host(host): Host, - mut req: Request, - next: Next, + mut req: Request, + next: Next, ) -> Response { // X-Forwarded-Proto is an untrusted header let client_claims_https = @@ -45,11 +45,11 @@ pub async fn init_request_state( /// /// We also require that all request have a Host header in /// the first place. -pub async fn restrict_host( +pub async fn restrict_host( Extension(state): Extension, Host(host): Host, - req: Request, - next: Next, + req: Request, + next: Next, ) -> ServerResult { let allowed_hosts = &state.config.allowed_hosts; @@ -61,10 +61,10 @@ pub async fn restrict_host( } /// Sets the `X-Attic-Cache-Visibility` header in responses. -pub(crate) async fn set_visibility_header( +pub(crate) async fn set_visibility_header( Extension(req_state): Extension, - req: Request, - next: Next, + req: Request, + next: Next, ) -> ServerResult { let mut response = next.run(req).await;