atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0

Commit ba879f96510d

tarball

atagen <boss@atagen.co>2026-10-10 15:15 UTC

2 files changed+34-4
jelqd: decode gzip bodies in the ui replay

With the cock ring equipped and Accept-Encoding: gzip filled in, the page showed the compressed bytes as mojibake. The content-encoding header is still listed so the joke survives.
Modified file: src/http.rs+14 additions−4 deletions
@@ -2,7 +2,7 @@ use std::{
22 collections::HashMap,
33 convert::Infallible,
44 fmt::Write as _,
5- io::Write as _,
5+ io::{Read as _, Write as _},
66 sync::{Arc, Mutex},
77 time::Instant,
88 };
@@ -16,7 +16,7 @@ use axum::{
1616 response::{Html, IntoResponse, Redirect, Response},
1717 routing::any,
1818 };
19-use flate2::{Compression, write::GzEncoder};
19+use flate2::{Compression, read::GzDecoder, write::GzEncoder};
2020 use hyper_util::rt::TokioIo;
2121 use rand::Rng;
2222 use serde::Deserialize;
@@ -1231,9 +1231,19 @@ async fn ui_send(State(api): State<Router>, headers: HeaderMap, body: Bytes) ->
12311231 };
12321232 let Ok(response) = api.oneshot(request).await;
12331233 let (parts, body) = response.into_parts();
1234- let bytes = axum::body::to_bytes(body, 1 << 20)
1234+ let mut bytes = axum::body::to_bytes(body, 1 << 20)
12351235 .await
1236- .unwrap_or_default();
1236+ .unwrap_or_default()
1237+ .to_vec();
1238+ if parts.headers.get(header::CONTENT_ENCODING) == Some(&HeaderValue::from_static("gzip")) {
1239+ let mut decoded = Vec::new();
1240+ if GzDecoder::new(bytes.as_slice())
1241+ .read_to_end(&mut decoded)
1242+ .is_ok()
1243+ {
1244+ bytes = decoded;
1245+ }
1246+ }
12371247 let listed: Vec<(String, String)> = parts
12381248 .headers
12391249 .iter()
Modified file: tests/http.rs+20 additions
@@ -548,3 +548,23 @@ async fn a_pulled_muscle_is_a_true_excuse() {
548548 .ends_with("/7")
549549 );
550550 }
551+
552+#[tokio::test]
553+async fn the_ui_decodes_gzip_for_display() {
554+ let app = seeded_with(Floor::Bedroom, |run| run.items.ring = true);
555+ let envelope =
556+ r#"{"method": "GET", "path": "/runs/cafebabe", "headers": [["Accept-Encoding", "gzip"]]}"#;
557+ let shown = json(send(&app, "POST", "/ui/send", &[], envelope).await).await;
558+ assert!(
559+ shown["body"]
560+ .as_str()
561+ .unwrap()
562+ .contains("\"id\":\"cafebabe\"")
563+ );
564+ let encoding = shown["headers"]
565+ .as_array()
566+ .unwrap()
567+ .iter()
568+ .any(|h| h[0] == "content-encoding" && h[1] == "gzip");
569+ assert!(encoding);
570+}