refactor: migrate web server to axum (lite)

This commit is contained in:
Rob Ede 2024-05-27 03:50:24 +01:00
parent 85a077e80d
commit d4d0db2e1e
No known key found for this signature in database
GPG key ID: 97C636207D3EF933
15 changed files with 163 additions and 129 deletions

203
Cargo.lock generated
View file

@ -81,6 +81,17 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "async-trait"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
version = "1.1.2" version = "1.1.2"
@ -93,6 +104,61 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "axum"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper 1.0.1",
"tokio",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper 0.1.2",
"tower-layer",
"tower-service",
"tracing",
]
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.71" version = "0.3.71"
@ -1390,25 +1456,6 @@ dependencies = [
"phf", "phf",
] ]
[[package]]
name = "h2"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http 0.2.12",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.4.5" version = "0.4.5"
@ -1420,7 +1467,7 @@ dependencies = [
"fnv", "fnv",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"http 1.1.0", "http",
"indexmap", "indexmap",
"slab", "slab",
"tokio", "tokio",
@ -1471,17 +1518,6 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "http"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]] [[package]]
name = "http" name = "http"
version = "1.1.0" version = "1.1.0"
@ -1493,17 +1529,6 @@ dependencies = [
"itoa", "itoa",
] ]
[[package]]
name = "http-body"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
"http 0.2.12",
"pin-project-lite",
]
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "1.0.0" version = "1.0.0"
@ -1511,7 +1536,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [ dependencies = [
"bytes", "bytes",
"http 1.1.0", "http",
] ]
[[package]] [[package]]
@ -1522,8 +1547,8 @@ checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
"http 1.1.0", "http",
"http-body 1.0.0", "http-body",
"pin-project-lite", "pin-project-lite",
] ]
@ -1539,30 +1564,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "0.14.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.3.1" version = "1.3.1"
@ -1572,10 +1573,11 @@ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"h2 0.4.5", "h2",
"http 1.1.0", "http",
"http-body 1.0.0", "http-body",
"httparse", "httparse",
"httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"smallvec", "smallvec",
@ -1590,8 +1592,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"http 1.1.0", "http",
"hyper 1.3.1", "hyper",
"hyper-util", "hyper-util",
"rustls", "rustls",
"rustls-pki-types", "rustls-pki-types",
@ -1608,7 +1610,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
dependencies = [ dependencies = [
"bytes", "bytes",
"http-body-util", "http-body-util",
"hyper 1.3.1", "hyper",
"hyper-util", "hyper-util",
"native-tls", "native-tls",
"tokio", "tokio",
@ -1625,9 +1627,9 @@ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"http 1.1.0", "http",
"http-body 1.0.0", "http-body",
"hyper 1.3.1", "hyper",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio", "tokio",
@ -1765,6 +1767,12 @@ dependencies = [
"regex-automata 0.1.10", "regex-automata 0.1.10",
] ]
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]] [[package]]
name = "maud" name = "maud"
version = "0.26.0" version = "0.26.0"
@ -2275,11 +2283,11 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2 0.4.5", "h2",
"http 1.1.0", "http",
"http-body 1.0.0", "http-body",
"http-body-util", "http-body-util",
"hyper 1.3.1", "hyper",
"hyper-rustls", "hyper-rustls",
"hyper-tls", "hyper-tls",
"hyper-util", "hyper-util",
@ -2298,7 +2306,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper 0.1.2",
"system-configuration", "system-configuration",
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
@ -2453,6 +2461,12 @@ dependencies = [
"owned_ttf_parser", "owned_ttf_parser",
] ]
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.18" version = "1.0.18"
@ -2546,6 +2560,16 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_path_to_error"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
dependencies = [
"itoa",
"serde",
]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.6" version = "0.6.6"
@ -2604,6 +2628,7 @@ name = "shiny-robots"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"axum",
"badge", "badge",
"cadence", "cadence",
"crates-index", "crates-index",
@ -2614,7 +2639,6 @@ dependencies = [
"futures-util", "futures-util",
"gix", "gix",
"grass", "grass",
"hyper 0.14.28",
"indexmap", "indexmap",
"lru_time_cache", "lru_time_cache",
"maud", "maud",
@ -2631,6 +2655,7 @@ dependencies = [
"sha-1", "sha-1",
"tokio", "tokio",
"toml 0.8.13", "toml 0.8.13",
"tower",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
] ]
@ -2721,6 +2746,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "sync_wrapper"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]] [[package]]
name = "system-configuration" name = "system-configuration"
version = "0.5.1" version = "0.5.1"
@ -2752,7 +2783,7 @@ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"gix", "gix",
"home", "home",
"http 1.1.0", "http",
"libc", "libc",
"memchr", "memchr",
"rayon", "rayon",
@ -3000,6 +3031,7 @@ dependencies = [
"tokio", "tokio",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
"tracing",
] ]
[[package]] [[package]]
@ -3020,6 +3052,7 @@ version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [ dependencies = [
"log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes", "tracing-attributes",
"tracing-core", "tracing-core",

View file

@ -15,13 +15,13 @@ edition = "2021"
badge = { path = "./libs/badge" } badge = { path = "./libs/badge" }
anyhow = "1" anyhow = "1"
axum = "0.7"
cadence = "1" cadence = "1"
crates-index = { version = "2", default-features = false, features = ["git"] } crates-index = { version = "2", default-features = false, features = ["git"] }
derive_more = "0.99" derive_more = "0.99"
dotenvy = "0.15" dotenvy = "0.15"
font-awesome-as-a-crate = "0.3" font-awesome-as-a-crate = "0.3"
futures-util = { version = "0.3", default-features = false, features = ["std"] } futures-util = { version = "0.3", default-features = false, features = ["std"] }
hyper = { version = "0.14.10", features = ["full"] }
error_reporter = "1" error_reporter = "1"
indexmap = { version = "2", features = ["serde"] } indexmap = { version = "2", features = ["serde"] }
lru_time_cache = "0.11" lru_time_cache = "0.11"
@ -38,6 +38,7 @@ serde = { version = "1", features = ["derive"] }
serde_urlencoded = "0.7" serde_urlencoded = "0.7"
tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros", "sync", "time"] } tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros", "sync", "time"] }
toml = "0.8" toml = "0.8"
tower = "0.4"
tracing = "0.1.30" tracing = "0.1.30"
tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] }

View file

@ -12,11 +12,11 @@ use futures_util::{
stream::{self, BoxStream}, stream::{self, BoxStream},
StreamExt as _, StreamExt as _,
}; };
use hyper::service::Service;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use relative_path::{RelativePath, RelativePathBuf}; use relative_path::{RelativePath, RelativePathBuf};
use rustsec::database::Database; use rustsec::database::Database;
use semver::VersionReq; use semver::VersionReq;
use tower::Service;
use crate::{ use crate::{
interactors::{ interactors::{

View file

@ -6,10 +6,10 @@ use std::{
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use crates_index::{Crate, DependencyKind}; use crates_index::{Crate, DependencyKind};
use futures_util::FutureExt as _; use futures_util::FutureExt as _;
use hyper::service::Service;
use semver::{Version, VersionReq}; use semver::{Version, VersionReq};
use serde::Deserialize; use serde::Deserialize;
use tokio::task::spawn_blocking; use tokio::task::spawn_blocking;
use tower::Service;
use crate::{ use crate::{
models::crates::{CrateDep, CrateDeps, CrateName, CratePath, CrateRelease}, models::crates::{CrateDep, CrateDeps, CrateName, CratePath, CrateRelease},

View file

@ -5,8 +5,8 @@ use std::{
use anyhow::Error; use anyhow::Error;
use futures_util::FutureExt as _; use futures_util::FutureExt as _;
use hyper::service::Service;
use serde::Deserialize; use serde::Deserialize;
use tower::Service;
use crate::{ use crate::{
models::repo::{RepoPath, Repository}, models::repo::{RepoPath, Repository},

View file

@ -5,8 +5,8 @@ use std::{
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use futures_util::FutureExt as _; use futures_util::FutureExt as _;
use hyper::service::Service;
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
use tower::Service;
use crate::{models::repo::RepoPath, BoxFuture}; use crate::{models::repo::RepoPath, BoxFuture};

View file

@ -6,8 +6,8 @@ use std::{
use anyhow::Error; use anyhow::Error;
use futures_util::FutureExt as _; use futures_util::FutureExt as _;
use hyper::service::Service;
use rustsec::database::Database; use rustsec::database::Database;
use tower::Service;
use crate::BoxFuture; use crate::BoxFuture;

View file

@ -9,12 +9,8 @@ use std::{
time::Duration, time::Duration,
}; };
use axum::{extract::Request, Router};
use cadence::{QueuingMetricSink, UdpMetricSink}; use cadence::{QueuingMetricSink, UdpMetricSink};
use hyper::{
server::conn::AddrStream,
service::{make_service_fn, service_fn},
Server,
};
use reqwest::redirect::Policy as RedirectPolicy; use reqwest::redirect::Policy as RedirectPolicy;
use tracing::Instrument as _; use tracing::Instrument as _;
@ -92,25 +88,20 @@ async fn main() {
let mut engine = Engine::new(client.clone(), index); let mut engine = Engine::new(client.clone(), index);
engine.set_metrics(metrics); engine.set_metrics(metrics);
let make_svc = make_service_fn(move |_socket: &AddrStream| { let app = App::new(engine.clone());
let engine = engine.clone();
async move { let lst = tokio::net::TcpListener::bind(addr).await.unwrap();
let server = App::new(engine.clone());
Ok::<_, hyper::Error>(service_fn(move |req| {
let server = server.clone();
async move {
let path = req.uri().path().to_owned();
server let router = Router::new().fallback(|req: Request| async move {
.handle(req) let path = req.uri().path().to_owned();
.instrument(tracing::info_span!("@", %path))
.await app.handle(req)
} .instrument(tracing::info_span!("@", %path))
})) .await
} .unwrap()
}); });
let server = Server::bind(&addr).serve(make_svc);
let server = axum::serve(lst, router);
tracing::info!("Server running on port {port}"); tracing::info!("Server running on port {port}");

View file

@ -1,11 +1,16 @@
use std::{env, sync::Arc, time::Instant}; use std::{env, sync::Arc, time::Instant};
use axum::{
body::Body,
extract::Request,
http::{
header::{CACHE_CONTROL, CONTENT_TYPE, ETAG, LOCATION},
Method, StatusCode,
},
response::Response,
};
use badge::BadgeStyle; use badge::BadgeStyle;
use futures_util::future; use futures_util::future;
use hyper::{
header::{CACHE_CONTROL, CONTENT_TYPE, ETAG, LOCATION},
Body, Error as HyperError, Method, Request, Response, StatusCode,
};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use route_recognizer::{Params, Router}; use route_recognizer::{Params, Router};
use semver::VersionReq; use semver::VersionReq;
@ -90,7 +95,7 @@ impl App {
} }
} }
pub async fn handle(&self, req: Request<Body>) -> Result<Response<Body>, HyperError> { pub async fn handle(&self, req: Request<Body>) -> Result<Response<Body>, axum::Error> {
let start = Instant::now(); let start = Instant::now();
// allows `/path/` to also match `/path` // allows `/path/` to also match `/path`
@ -147,7 +152,7 @@ impl App {
&self, &self,
_req: Request<Body>, _req: Request<Body>,
_params: Params, _params: Params,
) -> Result<Response<Body>, HyperError> { ) -> Result<Response<Body>, axum::Error> {
let engine = self.engine.clone(); let engine = self.engine.clone();
let popular = let popular =
@ -172,7 +177,7 @@ impl App {
req: Request<Body>, req: Request<Body>,
params: Params, params: Params,
format: StatusFormat, format: StatusFormat,
) -> Result<Response<Body>, HyperError> { ) -> Result<Response<Body>, axum::Error> {
let server = self.clone(); let server = self.clone();
let site = params.find("site").expect("route param 'site' not found"); let site = params.find("site").expect("route param 'site' not found");
@ -229,7 +234,7 @@ impl App {
&self, &self,
_req: Request<Body>, _req: Request<Body>,
params: Params, params: Params,
) -> Result<Response<Body>, HyperError> { ) -> Result<Response<Body>, axum::Error> {
let engine = self.engine.clone(); let engine = self.engine.clone();
let name = params.find("name").expect("route param 'name' not found"); let name = params.find("name").expect("route param 'name' not found");
@ -295,7 +300,7 @@ impl App {
req: Request<Body>, req: Request<Body>,
params: Params, params: Params,
format: StatusFormat, format: StatusFormat,
) -> Result<Response<Body>, HyperError> { ) -> Result<Response<Body>, axum::Error> {
let server = self.clone(); let server = self.clone();
let name = params.find("name").expect("route param 'name' not found"); let name = params.find("name").expect("route param 'name' not found");

View file

@ -1,5 +1,5 @@
use axum::{body::Body, http::header::CONTENT_TYPE, response::Response};
use badge::{Badge, BadgeOptions}; use badge::{Badge, BadgeOptions};
use hyper::{header::CONTENT_TYPE, Body, Response};
use crate::{engine::AnalyzeDependenciesOutcome, server::ExtraConfig}; use crate::{engine::AnalyzeDependenciesOutcome, server::ExtraConfig};

View file

@ -1,6 +1,10 @@
use hyper::{ use axum::{
header::{CACHE_CONTROL, CONTENT_TYPE}, body::Body,
Body, Response, StatusCode, http::{
header::{CACHE_CONTROL, CONTENT_TYPE},
StatusCode,
},
response::Response,
}; };
use maud::html; use maud::html;

View file

@ -1,4 +1,4 @@
use hyper::{Body, Response}; use axum::{body::Body, response::Response};
use maud::{html, Markup}; use maud::{html, Markup};
use crate::{ use crate::{

View file

@ -1,6 +1,6 @@
use std::time::Duration; use std::time::Duration;
use hyper::{header::CONTENT_TYPE, Body, Response}; use axum::{body::Body, http::header::CONTENT_TYPE, response::Response};
use maud::{html, Markup, Render, DOCTYPE}; use maud::{html, Markup, Render, DOCTYPE};
pub mod error; pub mod error;

View file

@ -1,5 +1,5 @@
use axum::{body::Body, response::Response};
use font_awesome_as_a_crate::{svg as fa, Type as FaType}; use font_awesome_as_a_crate::{svg as fa, Type as FaType};
use hyper::{Body, Response};
use indexmap::IndexMap; use indexmap::IndexMap;
use maud::{html, Markup, PreEscaped}; use maud::{html, Markup, PreEscaped};
use pulldown_cmark::{html, Parser}; use pulldown_cmark::{html, Parser};

View file

@ -1,9 +1,9 @@
use std::{fmt, sync::Arc, time::Duration}; use std::{fmt, sync::Arc, time::Duration};
use derive_more::{Display, Error, From}; use derive_more::{Display, Error, From};
use hyper::service::Service;
use lru_time_cache::LruCache; use lru_time_cache::LruCache;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tower::Service;
#[derive(Debug, Clone, Display, From, Error)] #[derive(Debug, Clone, Display, From, Error)]
pub struct CacheError<E> { pub struct CacheError<E> {