upgrade axum to 0.8.9 (and side deps) (#6808)

* upgrade axum to 0.8.9 (and side deps)

Bumps axum 0.7.5 → 0.8.9, axum-extra 0.9.4 → 0.12.6,
axum-client-ip 0.6.1 → 1.3.1, axum-test 16.2.0 → 20.0.0,
utoipa-swagger-ui 8.1 → 9.0.2.

* warn upon using fallback ip

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* chore: replace use of deprecated try_next()

* update console-subscriber to ensure single version of axum in the lock file

* removed unused axum-test dev-dep

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
Jędrzej Stuczyński
2026-05-22 15:39:33 +01:00
committed by GitHub
parent 6b0a904d10
commit 28b22f6b22
33 changed files with 580 additions and 558 deletions
Generated
+363 -469
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -222,10 +222,10 @@ anyhow = "1.0.98"
arc-swap = "1.7.1"
argon2 = "0.5.0"
async-trait = "0.1.88"
axum = "0.7.5"
axum-client-ip = "0.6.1"
axum-extra = "0.9.4"
axum-test = "16.2.0"
axum = "0.8.9"
axum-client-ip = "1.3.1"
axum-extra = "0.12.6"
axum-test = "20.0.0"
base64 = "0.22.1"
base85rs = "0.1.3"
bincode = "1.3.3"
@@ -250,7 +250,7 @@ clap_complete_fig = "4.5"
colored = "2.2"
comfy-table = "7.1.4"
console = "0.16.0"
console-subscriber = "0.4.1"
console-subscriber = "0.5.0"
console_error_panic_hook = "0.1"
const-str = "0.5.6"
const_format = "0.2.34"
@@ -392,7 +392,7 @@ uniffi = "0.29.2"
uniffi_build = "0.29.0"
url = "2.5"
utoipa = "5.2"
utoipa-swagger-ui = "8.1"
utoipa-swagger-ui = "9.0.2"
utoipauto = "0.2"
uuid = "1.19.0"
vergen = { version = "=8.3.1", default-features = false }
@@ -0,0 +1,39 @@
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use axum::extract::{ConnectInfo, FromRequestParts};
use axum::http::request::Parts;
use axum_client_ip::RightmostXForwardedFor;
use std::convert::Infallible;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tracing::warn;
/// Best-effort client IP extractor.
///
/// Prefers the rightmost entry of `X-Forwarded-For` (set by a trusted reverse
/// proxy); falls back to the TCP peer address when the header is absent, and to
/// the unspecified address when neither is available (tests).
#[derive(Debug, Clone, Copy)]
pub struct ClientIpAddr(pub IpAddr);
impl<S> FromRequestParts<S> for ClientIpAddr
where
S: Send + Sync,
{
type Rejection = Infallible;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
if let Ok(RightmostXForwardedFor(ip)) =
RightmostXForwardedFor::from_request_parts(parts, state).await
{
return Ok(ClientIpAddr(ip));
}
if let Ok(ConnectInfo(addr)) =
ConnectInfo::<SocketAddr>::from_request_parts(parts, state).await
{
return Ok(ClientIpAddr(addr.ip()));
}
warn!("ClientIpAddr: no X-Forwarded-For or ConnectInfo found; using 0.0.0.0 fallback");
Ok(ClientIpAddr(IpAddr::V4(Ipv4Addr::UNSPECIFIED)))
}
}
@@ -1,12 +1,12 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::middleware::client_ip::ClientIpAddr;
use axum::extract::Request;
use axum::http::HeaderValue;
use axum::http::header::{HOST, USER_AGENT};
use axum::middleware::Next;
use axum::response::IntoResponse;
use axum_client_ip::InsecureClientIp;
use colored::Colorize;
use std::time::Instant;
use tracing::{debug, info};
@@ -17,24 +17,24 @@ enum LogLevel {
}
pub async fn log_request_info(
insecure_client_ip: InsecureClientIp,
client_ip: ClientIpAddr,
request: Request,
next: Next,
) -> impl IntoResponse {
log_request(insecure_client_ip, request, next, LogLevel::Info).await
log_request(client_ip, request, next, LogLevel::Info).await
}
pub async fn log_request_debug(
insecure_client_ip: InsecureClientIp,
client_ip: ClientIpAddr,
request: Request,
next: Next,
) -> impl IntoResponse {
log_request(insecure_client_ip, request, next, LogLevel::Debug).await
log_request(client_ip, request, next, LogLevel::Debug).await
}
/// Simple logger for requests
async fn log_request(
InsecureClientIp(addr): InsecureClientIp,
ClientIpAddr(addr): ClientIpAddr,
request: Request,
next: Next,
level: LogLevel,
@@ -2,4 +2,5 @@
// SPDX-License-Identifier: Apache-2.0
pub mod bearer_auth;
pub mod client_ip;
pub mod logging;
@@ -1,7 +1,6 @@
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use axum::extract::FromRequestParts;
use axum::http::Request;
use axum::http::request::Parts;
@@ -56,7 +55,6 @@ impl DummyConnectInfo {
}
}
#[async_trait]
impl<S> FromRequestParts<S> for DummyConnectInfo
where
S: Send + Sync,
@@ -57,7 +57,7 @@ pub(crate) mod test {
async fn handle_check_request(&mut self, polled_request: CheckRequest) {
let mut requests = vec![polled_request];
while let Ok(Some(queued_up)) = self.check_request_receiver.try_next() {
while let Ok(queued_up) = self.check_request_receiver.try_recv() {
requests.push(queued_up);
}
+1 -1
View File
@@ -121,7 +121,7 @@ impl UpgradeModeWatcher {
async fn handle_check_request(&mut self, polled_request: CheckRequest) {
let mut requests = vec![polled_request];
while let Ok(Some(queued_up)) = self.check_request_receiver.try_next() {
while let Ok(queued_up) = self.check_request_receiver.try_recv() {
requests.push(queued_up);
}
+3 -3
View File
@@ -32,15 +32,15 @@ pub(crate) fn issued_routes() -> Router<AppState> {
axum::routing::get(issued_ticketbooks_count),
)
.route(
"/issued-ticketbooks-for-count/:expiration_date",
"/issued-ticketbooks-for-count/{expiration_date}",
axum::routing::get(issued_ticketbooks_for_count),
)
.route(
"/issued-ticketbooks-on-count/:issuance_date",
"/issued-ticketbooks-on-count/{issuance_date}",
axum::routing::get(issued_ticketbooks_on_count),
)
.route(
"/issued-ticketbooks-for/:expiration_date",
"/issued-ticketbooks-for/{expiration_date}",
axum::routing::get(issued_ticketbooks_for),
)
.route(
+1 -2
View File
@@ -1369,8 +1369,7 @@ impl TestFixture {
Router::new()
.nest("/v1/ecash", ecash_routes())
.with_state(app_state),
)
.unwrap(),
),
storage,
chain_state: bundle.chain_state,
epoch: bundle.epoch,
+2 -2
View File
@@ -23,8 +23,8 @@ const MAX_FAMILIES_PAGE_SIZE: u32 = 200;
pub(crate) fn routes() -> Router<AppState> {
Router::new()
.route("/", get(get_families))
.route("/:family_id", get(get_family_by_id))
.route("/by-node/:node_id", get(get_family_for_node))
.route("/{family_id}", get(get_family_by_id))
.route("/by-node/{node_id}", get(get_family_for_node))
}
#[utoipa::path(
+1 -2
View File
@@ -52,8 +52,7 @@ impl NodeFamiliesTestFixture {
Router::new()
.nest("/v1/node-families", handlers::routes())
.with_state(app_state),
)
.unwrap();
);
NodeFamiliesTestFixture {
axum: server,
@@ -25,7 +25,7 @@ use utoipa::IntoParams;
pub(super) fn network_monitor_routes() -> Router<AppState> {
Router::new()
.nest(
"/gateway/:identity",
"/gateway/{identity}",
Router::new()
.route("/history", axum::routing::get(gateway_uptime_history))
.route(
@@ -34,7 +34,7 @@ pub(super) fn network_monitor_routes() -> Router<AppState> {
),
)
.nest(
"/mixnode/:mix_id",
"/mixnode/{mix_id}",
Router::new()
.route("/history", axum::routing::get(mixnode_uptime_history))
.route(
@@ -45,14 +45,14 @@ pub(super) fn network_monitor_routes() -> Router<AppState> {
.nest(
"/mixnodes",
Router::new().route(
"/unstable/:mix_id/test-results",
"/unstable/{mix_id}/test-results",
axum::routing::get(unstable::mixnode_test_results),
),
)
.nest(
"/gateways",
Router::new().route(
"/unstable/:gateway_identity/test-results",
"/unstable/{gateway_identity}/test-results",
axum::routing::get(unstable::gateway_test_results),
),
)
@@ -60,7 +60,7 @@ pub(super) fn network_monitor_routes() -> Router<AppState> {
"/network-monitor/unstable",
Router::new()
.route(
"/run/:monitor_run_id/details",
"/run/{monitor_run_id}/details",
axum::routing::get(monitor_run_report),
)
.route(
+9 -6
View File
@@ -30,19 +30,22 @@ pub(crate) fn routes() -> Router<AppState> {
.route("/noise", get(nodes_noise))
.route("/bonded", get(get_bonded_nodes))
.route("/described", get(get_described_nodes))
.route("/annotation/:node_id", get(get_node_annotation))
.route("/performance/:node_id", get(get_current_node_performance))
.route("/stake-saturation/:node_id", get(get_node_stake_saturation))
.route("/annotation/{node_id}", get(get_node_annotation))
.route("/performance/{node_id}", get(get_current_node_performance))
.route(
"/historical-performance/:node_id",
"/stake-saturation/{node_id}",
get(get_node_stake_saturation),
)
.route(
"/historical-performance/{node_id}",
get(get_historical_performance),
)
.route(
"/performance-history/:node_id",
"/performance-history/{node_id}",
get(get_node_performance_history),
)
// to make it compatible with all the explorers that were used to using 0-100 values
.route("/uptime-history/:node_id", get(get_node_uptime_history))
.route("/uptime-history/{node_id}", get(get_node_uptime_history))
.route("/rewarded-set", get(rewarded_set))
.layer(CompressionLayer::new())
}
@@ -22,7 +22,7 @@ pub(crate) mod data_collector;
pub(crate) mod models;
pub(crate) fn routes() -> Router<AppState> {
Router::new().route("/:address", get(address))
Router::new().route("/{address}", get(address))
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, utoipa::IntoParams)]
@@ -62,9 +62,9 @@ pub mod routes {
pub mod shares {
use super::*;
pub const SHARE_BY_ID: &str = "/:share_id";
pub const SHARE_BY_ID: &str = "/{share_id}";
pub const SHARE_BY_DEVICE_AND_CREDENTIAL_ID: &str =
"/device/:device_id/credential/:credential_id";
"/device/{device_id}/credential/{credential_id}";
absolute_route!(share_by_id_absolute, shares_absolute(), SHARE_BY_ID);
absolute_route!(
+10
View File
@@ -77,3 +77,13 @@ fn setup_cors() -> CorsLayer {
.allow_headers(tower_http::cors::Any)
.allow_credentials(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn router_constructs_without_panic() {
let _ = RouterBuilder::with_default_routes().finalize_routes();
}
}
+30 -12
View File
@@ -58,6 +58,21 @@ impl AppState {
}
}
fn build_router(state: AppState) -> Router {
Router::new()
.route("/v1/send", post(send_handler).with_state(state))
.merge(SwaggerUi::new("/v1/ui").url("/v1/docs/openapi.json", ApiDoc::openapi()))
.route("/v1/accounting", get(accounting_handler))
.route("/v1/sent", get(sent_handler))
.route("/v1/dot/{mix_id}", get(mix_dot_handler))
.route("/v1/dot", get(graph_handler))
.route("/v1/mermaid", get(mermaid_handler))
.route("/v1/stats", get(stats_handler))
.route("/v1/node_stats/{mix_id}", get(node_stats_handler))
.route("/v1/node_stats", get(all_nodes_stats_handler))
.route("/v1/received", get(recv_handler))
}
impl HttpServer {
pub fn new(listener: SocketAddr, cancel: CancellationToken) -> Self {
HttpServer { listener, cancel }
@@ -66,18 +81,7 @@ impl HttpServer {
pub async fn run(self, clients: ClientsWrapper) -> anyhow::Result<()> {
let n_clients = clients.read().await.len();
let state = AppState { clients };
let app = Router::new()
.route("/v1/send", post(send_handler).with_state(state))
.merge(SwaggerUi::new("/v1/ui").url("/v1/docs/openapi.json", ApiDoc::openapi()))
.route("/v1/accounting", get(accounting_handler))
.route("/v1/sent", get(sent_handler))
.route("/v1/dot/:mix_id", get(mix_dot_handler))
.route("/v1/dot", get(graph_handler))
.route("/v1/mermaid", get(mermaid_handler))
.route("/v1/stats", get(stats_handler))
.route("/v1/node_stats/:mix_id", get(node_stats_handler))
.route("/v1/node_stats", get(all_nodes_stats_handler))
.route("/v1/received", get(recv_handler));
let app = build_router(state);
let listener = tokio::net::TcpListener::bind(self.listener).await?;
let server_future =
@@ -98,3 +102,17 @@ impl HttpServer {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::VecDeque;
use std::sync::Arc;
use tokio::sync::RwLock;
#[test]
fn router_constructs_without_panic() {
let clients: ClientsWrapper = Arc::new(RwLock::new(VecDeque::new()));
let _ = build_router(AppState { clients });
}
}
@@ -84,6 +84,5 @@ sqlx = { workspace = true, features = [
] }
[dev-dependencies]
axum-test = { workspace = true }
time = { workspace = true, features = ["macros"] }
nym-gateway-probe = { workspace = true, features = ["test-utils"] }
@@ -13,7 +13,7 @@ use crate::http::{error::HttpResult, state::AppState};
pub(crate) fn routes() -> Router<AppState> {
Router::new()
.route(
"/country/:two_letter_country_code",
"/country/{two_letter_country_code}",
axum::routing::get(get_gateways_by_country),
)
.route("/countries", axum::routing::get(get_gateway_countries))
@@ -18,7 +18,7 @@ pub(crate) fn routes() -> Router<AppState> {
axum::routing::get(get_entry_gateway_countries),
)
.route(
"/entry/country/:two_letter_country_code",
"/entry/country/{two_letter_country_code}",
axum::routing::get(get_entry_gateways_by_country),
)
}
@@ -18,7 +18,7 @@ pub(crate) fn routes() -> Router<AppState> {
axum::routing::get(get_entry_gateway_countries),
)
.route(
"/exit/country/:two_letter_country_code",
"/exit/country/{two_letter_country_code}",
axum::routing::get(get_exit_gateways_by_country),
)
}
@@ -16,7 +16,7 @@ pub(crate) fn routes() -> Router<AppState> {
Router::new()
.route("/", axum::routing::get(gateways))
.route("/skinny", axum::routing::get(gateways_skinny))
.route("/:identity_key", axum::routing::get(get_gateway))
.route("/{identity_key}", axum::routing::get(get_gateway))
}
#[utoipa::path(
@@ -14,8 +14,8 @@ use crate::http::{
pub(crate) fn routes() -> Router<AppState> {
Router::new().route("/", axum::routing::get(get_all_sessions))
// .route("/:node_id", axum::routing::get(get_node_sessions))
// .route("/:day", axum::routing::get(get_daily_sessions))
// .route("/{node_id}", axum::routing::get(get_node_sessions))
// .route("/{day}", axum::routing::get(get_daily_sessions))
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::IntoParams)]
@@ -18,7 +18,7 @@ pub(crate) fn routes() -> Router<AppState> {
Router::new()
.route("/", axum::routing::get(nym_nodes))
.route(
"/:node_id/delegations",
"/{node_id}/delegations",
axum::routing::get(node_delegations),
)
}
@@ -26,8 +26,8 @@ use tracing::error;
pub(crate) fn routes() -> Router<AppState> {
Router::new()
.route("/", axum::routing::get(request_testrun))
.route("/:testrun_id", axum::routing::post(submit_testrun))
.route("/:testrun_id/v2", axum::routing::post(submit_testrun_v2))
.route("/{testrun_id}", axum::routing::post(submit_testrun))
.route("/{testrun_id}/v2", axum::routing::post(submit_testrun_v2))
.layer(DefaultBodyLimit::max(1024 * 1024 * 5))
}
+7 -4
View File
@@ -5,8 +5,10 @@ use axum::Router;
use axum::extract::ConnectInfo;
use axum::extract::connect_info::IntoMakeServiceWithConnectInfo;
use axum::middleware::AddExtension;
use axum::serve::Serve;
use axum::serve::WithGracefulShutdown;
use std::net::SocketAddr;
use tokio::net::TcpListener;
use tokio_util::sync::WaitForCancellationFutureOwned;
pub use router::{HttpServerConfig, NymNodeRouter, api};
@@ -15,6 +17,7 @@ pub mod helpers;
pub mod router;
pub mod state;
type InnerService = IntoMakeServiceWithConnectInfo<Router, SocketAddr>;
type ConnectInfoExt = AddExtension<Router, ConnectInfo<SocketAddr>>;
pub type NymNodeHttpServer = Serve<InnerService, ConnectInfoExt>;
type MakeService = IntoMakeServiceWithConnectInfo<Router, SocketAddr>;
type InnerService = AddExtension<Router, ConnectInfo<SocketAddr>>;
pub type NymNodeHttpServer =
WithGracefulShutdown<TcpListener, MakeService, InnerService, WaitForCancellationFutureOwned>;
@@ -14,7 +14,7 @@ pub struct Config {
pub(super) fn routes<S: Send + Sync + 'static + Clone>(config: Config) -> Router<S> {
if let Some(assets) = config.assets_path {
Router::new().nest_service("/", ServeDir::new(assets))
Router::new().fallback_service(ServeDir::new(assets))
} else {
Router::new().route("/", get(default))
}
+26 -2
View File
@@ -22,6 +22,7 @@ use nym_node_requests::routes;
use std::net::SocketAddr;
use std::path::Path;
use std::sync::Arc;
use tokio_util::sync::WaitForCancellationFutureOwned;
use zeroize::Zeroizing;
pub mod api;
@@ -176,7 +177,7 @@ impl NymNodeRouter {
Redirect::to(&routes::api::v1::metrics::prometheus_absolute())
}),
)
.nest(routes::LANDING_PAGE, landing_page::routes(config.landing))
.merge(landing_page::routes(config.landing))
.nest(routes::API, api::routes(config.api))
.layer(axum::middleware::from_fn(logging::log_request_info))
.with_state(state),
@@ -186,6 +187,7 @@ impl NymNodeRouter {
pub async fn build_server(
self,
bind_address: &SocketAddr,
shutdown: WaitForCancellationFutureOwned,
) -> Result<NymNodeHttpServer, NymNodeHttpError> {
let listener = tokio::net::TcpListener::bind(bind_address)
.await
@@ -198,6 +200,28 @@ impl NymNodeRouter {
listener,
self.inner
.into_make_service_with_connect_info::<SocketAddr>(),
))
)
.with_graceful_shutdown(shutdown))
}
}
#[cfg(test)]
mod tests {
use super::*;
use nym_crypto::asymmetric::{ed25519, x25519};
use nym_node_requests::api::SignedData;
use nym_node_requests::api::v1::lewes_protocol::models::LewesProtocol;
use nym_test_utils::helpers::deterministic_rng;
use std::collections::BTreeMap;
#[test]
fn router_constructs_without_panic() {
let mut rng = deterministic_rng();
let signing = ed25519::KeyPair::new(&mut rng);
let x25519_pub: x25519::DHPublicKey = x25519::PrivateKey::new(&mut rng).public_key().into();
let lp = LewesProtocol::new(false, 0, 0, x25519_pub, BTreeMap::new());
let signed = SignedData::new(lp, signing.private_key()).unwrap();
let config = HttpServerConfig::new(signed);
let _ = NymNodeRouter::new(config, AppState::dummy());
}
}
+26
View File
@@ -73,4 +73,30 @@ impl AppState {
},
}
}
#[cfg(test)]
pub(crate) fn dummy() -> Self {
use crate::node::key_rotation::key::SphinxPrivateKey;
use rand::rngs::OsRng;
let ed25519_keys = ed25519::KeyPair::new(&mut OsRng);
let attester_pk = *ed25519_keys.public_key();
let static_information = StaticNodeInformation {
ed25519_identity_keys: Arc::new(ed25519_keys),
x25519_versioned_noise_key: None,
ip_addresses: vec![],
hostname: None,
};
let active_sphinx = ActiveSphinxKeys::new_fresh(SphinxPrivateKey::new(&mut OsRng, 0));
AppState::new(
static_information,
active_sphinx,
NymNodeMetrics::new(),
SharedVerlocStats::default(),
Url::parse("https://attestation.test").unwrap(),
UpgradeModeState::new(attester_pk),
Duration::from_secs(60),
)
}
}
+12 -7
View File
@@ -81,6 +81,7 @@ use std::ops::Deref;
use std::path::Path;
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio_util::sync::WaitForCancellationFutureOwned;
use tracing::{debug, info, trace};
use zeroize::Zeroizing;
@@ -872,7 +873,10 @@ impl NymNode {
.collect()
}
pub(crate) async fn build_http_server(&self) -> Result<NymNodeHttpServer, NymNodeError> {
pub(crate) async fn build_http_server(
&self,
shutdown: WaitForCancellationFutureOwned,
) -> Result<NymNodeHttpServer, NymNodeError> {
let auxiliary_details = api_requests::v1::node::models::AuxiliaryDetails {
location: self.config.host.location,
announce_ports: AnnouncePorts {
@@ -1023,7 +1027,7 @@ impl NymNode {
);
Ok(NymNodeRouter::new(config, app_state)
.build_server(&self.config.http.bind_address)
.build_server(&self.config.http.bind_address, shutdown)
.await?)
}
@@ -1342,16 +1346,17 @@ impl NymNode {
);
debug!("config: {:#?}", self.config);
let http_server = self.build_http_server().await?;
let bind_address = self.config.http.bind_address;
let server_shutdown = self.shutdown_manager.clone_shutdown_token();
let shutdown = self
.shutdown_manager
.clone_shutdown_token()
.cancelled_owned();
let http_server = self.build_http_server(shutdown).await?;
self.shutdown_manager.try_spawn_named(
async move {
info!("starting NymNodeHTTPServer on {bind_address}");
http_server
.with_graceful_shutdown(async move { server_shutdown.cancelled().await })
.await
http_server.await
},
"HttpApi",
);
+8 -14
View File
@@ -1,6 +1,6 @@
use axum::{Json, Router, extract::State};
use axum_client_ip::InsecureClientIp;
use axum_extra::{TypedHeader, headers::UserAgent};
use nym_http_api_common::middleware::client_ip::ClientIpAddr;
use nym_statistics_common::report::vpn_client::{
ActiveDeviceReport, StaticInformationReport, VpnClientStatsReport, VpnClientStatsReportV2,
};
@@ -35,15 +35,12 @@ pub(crate) fn routes() -> Router<AppState> {
async fn submit_stats_report(
State(mut state): State<AppState>,
TypedHeader(user_agent): TypedHeader<UserAgent>,
insecure_ip_addr: InsecureClientIp,
ClientIpAddr(client_ip): ClientIpAddr,
Json(report): Json<VpnClientStatsReport>,
) -> HttpResult<Json<()>> {
let now = time::OffsetDateTime::now_utc();
let gateway_record = state
.network_view()
.get_country_by_ip(&insecure_ip_addr.0)
.await;
let gateway_record = state.network_view().get_country_by_ip(&client_ip).await;
let from_mixnet = gateway_record.is_some();
let maybe_location = gateway_record.unwrap_or_default();
@@ -60,7 +57,7 @@ async fn submit_stats_report(
&report,
user_agent,
from_mixnet,
insecure_ip_addr.0,
client_ip,
maybe_location,
);
@@ -93,15 +90,12 @@ async fn submit_stats_report(
async fn submit_active_device(
State(mut state): State<AppState>,
TypedHeader(user_agent): TypedHeader<UserAgent>,
insecure_ip_addr: InsecureClientIp,
ClientIpAddr(client_ip): ClientIpAddr,
Json(report): Json<ActiveDeviceReport>,
) -> HttpResult<Json<()>> {
let now = time::OffsetDateTime::now_utc();
let gateway_record = state
.network_view()
.get_country_by_ip(&insecure_ip_addr.0)
.await;
let gateway_record = state.network_view().get_country_by_ip(&client_ip).await;
let from_mixnet = gateway_record.is_some();
@@ -140,7 +134,7 @@ async fn submit_active_device(
async fn submit_session_report(
State(mut state): State<AppState>,
TypedHeader(user_agent): TypedHeader<UserAgent>,
insecure_ip_addr: InsecureClientIp, // This is the reverse proxy IP for now, but maybe in the future?
ClientIpAddr(client_ip): ClientIpAddr,
Json(report): Json<VpnClientStatsReportV2>,
) -> HttpResult<Json<()>> {
let now = time::OffsetDateTime::now_utc();
@@ -164,7 +158,7 @@ async fn submit_session_report(
&report,
user_agent,
from_mixnet,
insecure_ip_addr.0,
client_ip,
maybe_location,
);
+10
View File
@@ -79,3 +79,13 @@ fn setup_cors() -> CorsLayer {
.allow_headers(tower_http::cors::Any)
.allow_credentials(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn router_constructs_without_panic() {
let _ = RouterBuilder::with_default_routes().finalize_routes();
}
}