Skip to content

Commit 2d03121

Browse files
Improved logging
1 parent f7f435e commit 2d03121

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

src/main.rs

+51-7
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@ mod services;
55
mod structures;
66

77
use std::{
8-
net::{Ipv4Addr, SocketAddr},
8+
net::{IpAddr, Ipv4Addr, SocketAddr},
9+
str::FromStr,
910
sync::{Arc, PoisonError, RwLock},
1011
time::Duration,
1112
};
1213

1314
use askama::Template;
1415
use axum::{
1516
body::Body,
16-
extract::{Path, Query, Request, State},
17+
extract::{FromRequestParts, Path, Query, Request, State},
1718
handler::Handler,
1819
http::{
1920
header::{ACCEPT, CACHE_CONTROL, CONTENT_TYPE},
21+
request::Parts,
2022
HeaderName, HeaderValue, StatusCode,
2123
},
2224
middleware::Next,
@@ -302,7 +304,9 @@ async fn ping_frame(
302304
State(state): State<AppState>,
303305
CspNonce(nonce): CspNonce,
304306
Path((edition, hostname)): Path<(String, String)>,
307+
CfConnectingIp(ip): CfConnectingIp,
305308
) -> Result<PingFrameTemplate, Failure> {
309+
info!(edition, path = "frame", target = hostname, on_behalf = ?ip, "Pinging server");
306310
let ping = ping_generic(&edition, hostname.clone()).await?;
307311
Ok(PingFrameTemplate {
308312
ping,
@@ -327,7 +331,9 @@ pub struct PingElementTemplate {
327331
async fn ping_markup(
328332
State(state): State<AppState>,
329333
Path((edition, hostname)): Path<(String, String)>,
334+
CfConnectingIp(ip): CfConnectingIp,
330335
) -> Result<PingElementTemplate, Failure> {
336+
info!(edition, path = "markup", target = hostname, on_behalf = ?ip, "Pinging server");
331337
let ping = ping_generic(&edition, hostname.clone()).await?;
332338
Ok(PingElementTemplate {
333339
ping,
@@ -338,9 +344,12 @@ async fn ping_markup(
338344
})
339345
}
340346

341-
async fn ping_image(Path((edition, hostname)): Path<(String, String)>) -> Result<Png, StatusCode> {
347+
async fn ping_image(
348+
Path((edition, hostname)): Path<(String, String)>,
349+
CfConnectingIp(ip): CfConnectingIp,
350+
) -> Result<Png, StatusCode> {
342351
const PREFIX_LEN: usize = "data:image/png;base64,".len();
343-
debug!(edition, hostname, "Serving icon");
352+
info!(edition, path = "image", target = hostname, on_behalf = ?ip, "Pinging server");
344353
let ping = match ping_generic(&edition, hostname.clone()).await {
345354
Ok(v) => v,
346355
Err(e) => {
@@ -362,11 +371,19 @@ async fn ping_image(Path((edition, hostname)): Path<(String, String)>) -> Result
362371
Ok(Png(decoded))
363372
}
364373

365-
async fn handle_java_ping(Path(address): Path<String>) -> Result<Json<MCPingResponse>, Failure> {
374+
async fn handle_java_ping(
375+
Path(address): Path<String>,
376+
CfConnectingIp(ip): CfConnectingIp,
377+
) -> Result<Json<MCPingResponse>, Failure> {
378+
info!(edition = "java", path = "api", target = address, on_behalf = ?ip, "Pinging server");
366379
Ok(Json(ping_java(address).await?))
367380
}
368381

369-
async fn handle_bedrock_ping(Path(address): Path<String>) -> Result<Json<MCPingResponse>, Failure> {
382+
async fn handle_bedrock_ping(
383+
Path(address): Path<String>,
384+
CfConnectingIp(ip): CfConnectingIp,
385+
) -> Result<Json<MCPingResponse>, Failure> {
386+
info!(edition = "bedrock", path = "api", target = address, on_behalf = ?ip, "Pinging server");
370387
Ok(Json(ping_bedrock(address).await?))
371388
}
372389

@@ -394,6 +411,10 @@ pub enum Failure {
394411
StatusReqwestFailed(#[from] reqwest::Error),
395412
#[error("JSON processing error")]
396413
JsonProcessingFailed(#[from] serde_json::Error),
414+
#[error("Could not convert header to string")]
415+
HeaderToStr(#[from] axum::http::header::ToStrError),
416+
#[error("Could not convert string to IP address")]
417+
AddressParse(#[from] std::net::AddrParseError),
397418
#[error("Status lock poisoned. Please try again in 5 minutes.")]
398419
LockPoisoned,
399420
#[error("No server address specified!")]
@@ -414,7 +435,10 @@ impl IntoResponse for Failure {
414435
Self::ConnectionFailed(_) | Self::TimedOut => StatusCode::OK,
415436
Self::StatusReqwestFailed(_) => StatusCode::BAD_GATEWAY,
416437
Self::JsonProcessingFailed(_) | Self::LockPoisoned => StatusCode::INTERNAL_SERVER_ERROR,
417-
Self::NoHostname | Self::UnknownEdition => StatusCode::BAD_REQUEST,
438+
Self::NoHostname
439+
| Self::UnknownEdition
440+
| Self::AddressParse(_)
441+
| Self::HeaderToStr(_) => StatusCode::BAD_REQUEST,
418442
};
419443
error!(error = ?self, "Error processing request");
420444
(status, Extension(Arc::new(self)), Body::empty()).into_response()
@@ -503,3 +527,23 @@ impl IntoResponse for Png {
503527
(headers, self.0).into_response()
504528
}
505529
}
530+
531+
pub struct CfConnectingIp(pub IpAddr);
532+
533+
#[axum::async_trait]
534+
impl<S> FromRequestParts<S> for CfConnectingIp {
535+
type Rejection = Failure;
536+
537+
async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
538+
static NAME: HeaderName = HeaderName::from_static("cf-connecting-ip");
539+
540+
let Some(ip_hdr) = parts.headers.get(&NAME) else {
541+
warn!("Cloudflare did not send cf-connecting-ip");
542+
return Ok(Self(IpAddr::V4(Ipv4Addr::UNSPECIFIED)));
543+
};
544+
545+
let ip_str = ip_hdr.to_str()?;
546+
let ip = IpAddr::from_str(ip_str)?;
547+
Ok(Self(ip))
548+
}
549+
}

0 commit comments

Comments
 (0)