Skip to content

Commit c1c4496

Browse files
Seperate image URL for load speed
1 parent 61047ff commit c1c4496

File tree

4 files changed

+83
-32
lines changed

4 files changed

+83
-32
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ axum-extra = "0.9"
2222
serde_json = "1"
2323
thiserror = "1"
2424
tracing = "0.1"
25+
base64 = "0.22"
2526
tower = "0.4"
2627
vss = "0.1"
2728

src/main.rs

+76-27
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use axum::{
2424
Router,
2525
};
2626
use axum_extra::routing::RouterExt;
27+
use base64::{alphabet::Alphabet, engine::GeneralPurpose, prelude::BASE64_STANDARD, Engine};
2728
use bustdir::BustDir;
2829
use parking_lot::RwLock;
2930
use reqwest::{header::HeaderMap, redirect::Policy, Client};
@@ -103,6 +104,10 @@ async fn main() {
103104
.route_with_tsr("/ping/:edition/:hostname", get(ping_page))
104105
.route("/internal/ping-frame/:edition/:hostname", get(ping_frame))
105106
.route("/internal/ping-markup/:edition/:hostname", get(ping_markup))
107+
.route(
108+
"/internal/icon/:edition/:hostname/icon.:ext",
109+
get(ping_image),
110+
)
106111
.layer(axum::middleware::from_fn(cache_short))
107112
.fallback_service(serve_dir)
108113
.layer(axum::middleware::from_fn(csp))
@@ -186,6 +191,20 @@ async fn root(State(state): State<AppState>) -> RootTemplate {
186191
}
187192
}
188193

194+
#[derive(Template)]
195+
#[template(path = "api.html")]
196+
pub struct ApiTemplate {
197+
bd: Arc<BustDir>,
198+
root_url: Arc<str>,
199+
}
200+
201+
async fn api_info(State(state): State<AppState>) -> ApiTemplate {
202+
ApiTemplate {
203+
root_url: state.root_url,
204+
bd: state.bust_dir,
205+
}
206+
}
207+
189208
#[derive(Deserialize)]
190209
pub struct PingQuery {
191210
edition: String,
@@ -234,19 +253,11 @@ async fn ping_page(
234253
})
235254
}
236255

237-
async fn ping_generic(
238-
edition: String,
239-
hostname: String,
240-
state: &AppState,
241-
) -> Result<MCPingResponse, ErrorTemplate> {
242-
let ping = match edition.as_str() {
243-
"java" => ping_java(hostname).await,
244-
"bedrock" => ping_bedrock(hostname).await,
245-
_ => return Err(ErrorTemplate::from_failure(&Failure::UnknownEdition, state)),
246-
};
247-
let ping = match ping {
248-
Ok(v) => v,
249-
Err(e) => return Err(ErrorTemplate::from_failure(&e, state)),
256+
async fn ping_generic(edition: &str, hostname: String) -> Result<MCPingResponse, Failure> {
257+
let ping = match edition {
258+
"java" => ping_java(hostname).await?,
259+
"bedrock" => ping_bedrock(hostname).await?,
260+
_ => return Err(Failure::UnknownEdition),
250261
};
251262
Ok(ping)
252263
}
@@ -257,17 +268,23 @@ pub struct PingFrameTemplate {
257268
ping: MCPingResponse,
258269
bd: Arc<BustDir>,
259270
root_url: Arc<str>,
271+
edition: String,
272+
hostname: String,
260273
}
261274

262275
async fn ping_frame(
263276
State(state): State<AppState>,
264277
Path((edition, hostname)): Path<(String, String)>,
265278
) -> Result<PingFrameTemplate, ErrorTemplate> {
266-
let ping = ping_generic(edition, hostname, &state).await?;
279+
let ping = ping_generic(&edition, hostname.clone())
280+
.await
281+
.map_err(|v| v.as_error_template(&state))?;
267282
Ok(PingFrameTemplate {
268283
ping,
269284
root_url: state.root_url,
270285
bd: state.bust_dir,
286+
edition,
287+
hostname,
271288
})
272289
}
273290

@@ -277,32 +294,48 @@ pub struct PingElementTemplate {
277294
ping: MCPingResponse,
278295
bd: Arc<BustDir>,
279296
root_url: Arc<str>,
297+
edition: String,
298+
hostname: String,
280299
}
281300

282301
async fn ping_markup(
283302
State(state): State<AppState>,
284303
Path((edition, hostname)): Path<(String, String)>,
285304
) -> Result<PingElementTemplate, ErrorTemplate> {
286-
let ping = ping_generic(edition, hostname, &state).await?;
305+
let ping = ping_generic(&edition, hostname.clone())
306+
.await
307+
.map_err(|v| v.as_error_template(&state))?;
287308
Ok(PingElementTemplate {
288309
ping,
289310
bd: state.bust_dir,
290311
root_url: state.root_url,
312+
edition,
313+
hostname,
291314
})
292315
}
293316

294-
#[derive(Template)]
295-
#[template(path = "api.html")]
296-
pub struct ApiTemplate {
297-
bd: Arc<BustDir>,
298-
root_url: Arc<str>,
299-
}
300-
301-
async fn api_info(State(state): State<AppState>) -> ApiTemplate {
302-
ApiTemplate {
303-
root_url: state.root_url,
304-
bd: state.bust_dir,
305-
}
317+
async fn ping_image(Path((edition, hostname)): Path<(String, String)>) -> Result<Png, StatusCode> {
318+
const PREFIX_LEN: usize = "data:image/png;base64,".len();
319+
debug!(edition, hostname, "Serving icon");
320+
let ping = match ping_generic(&edition, hostname.clone()).await {
321+
Ok(v) => v,
322+
Err(e) => {
323+
error!(error = ?e, "Encountered error decoding icon");
324+
return Err(StatusCode::NOT_FOUND);
325+
}
326+
};
327+
let Some(icon) = ping.icon else {
328+
return Err(StatusCode::NOT_FOUND);
329+
};
330+
let cut_icon = icon.split_at(PREFIX_LEN).1;
331+
let decoded = match BASE64_STANDARD.decode(cut_icon) {
332+
Ok(v) => v,
333+
Err(e) => {
334+
error!(error = ?e, "Encountered error decoding icon");
335+
return Err(StatusCode::INTERNAL_SERVER_ERROR);
336+
}
337+
};
338+
Ok(Png(decoded))
306339
}
307340

308341
async fn handle_java_ping(Path(address): Path<String>) -> Result<Json<MCPingResponse>, Failure> {
@@ -358,6 +391,13 @@ impl IntoResponse for Failure {
358391
}
359392
}
360393

394+
impl Failure {
395+
#[must_use]
396+
pub fn as_error_template(&self, state: &AppState) -> ErrorTemplate {
397+
ErrorTemplate::from_failure(self, state)
398+
}
399+
}
400+
361401
#[derive(Serialize)]
362402
pub struct ErrorSerialization {
363403
error: String,
@@ -401,6 +441,15 @@ impl<T: Serialize> IntoResponse for Json<T> {
401441
}
402442
}
403443

444+
pub struct Png(pub Vec<u8>);
445+
446+
impl IntoResponse for Png {
447+
fn into_response(self) -> Response {
448+
let headers = [("Content-Type", "image/png")];
449+
(headers, self.0).into_response()
450+
}
451+
}
452+
404453
fn start_tracing() {
405454
let env_filter = tracing_subscriber::EnvFilter::builder()
406455
.with_default_directive(concat!(env!("CARGO_PKG_NAME"), "=info").parse().unwrap())

templates/ping-element.html

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{% let icon %}
22
{% match ping.icon %}
3-
{% when Some with (raw_icon) %}
4-
{% let icon = "{}"|format(raw_icon) %}
5-
{% when None %}
6-
{% let icon_cb = "/icon.png"|bust_dir(bd) %}
7-
{% let icon = "{}/icon.png?cb={}"|format(root_url, icon_cb) %}
3+
{% when Some with (raw_icon) %}
4+
{% let icon = "{}/internal/icon/{}/{}/icon.png"|format(root_url, edition, hostname) %}
5+
{% when None %}
6+
{% let icon_cb = "/icon.png"|bust_dir(bd) %}
7+
{% let icon = "{}/icon.png?cb={}"|format(root_url, icon_cb) %}
88
{% endmatch %}
99
<div class="server-response">
1010
<div class="server-response-stack">

0 commit comments

Comments
 (0)