From 2948665ddfc4523a8bed833743e55ff8354f50f5 Mon Sep 17 00:00:00 2001 From: Peter Holloway Date: Wed, 10 Dec 2025 13:18:12 +0000 Subject: [PATCH 1/2] Template 404 page to account for public_address If the service is not hosted at the root of a domain, the links to the graphql and graphiql endpoints cannot be absolute. --- Cargo.lock | 52 ++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + Dockerfile | 11 +++---- src/main.rs | 25 ++++++++++++++-- {static => templates}/404.html | 4 +-- 5 files changed, 84 insertions(+), 9 deletions(-) rename {static => templates}/404.html (69%) diff --git a/Cargo.lock b/Cargo.lock index 109b47b..347658b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,6 +83,48 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" +[[package]] +name = "askama" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" +dependencies = [ + "askama_parser", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "serde", + "serde_derive", + "syn", +] + +[[package]] +name = "askama_parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow", +] + [[package]] name = "assert-json-diff" version = "2.0.2" @@ -318,6 +360,15 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "2.10.0" @@ -786,6 +837,7 @@ dependencies = [ name = "glazed" version = "0.0.0" dependencies = [ + "askama", "async-graphql", "async-graphql-axum", "axum", diff --git a/Cargo.toml b/Cargo.toml index f7a5b19..eb115f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ clap = { version = "4.5.48", features = ["derive"] } uuid = { version = "1.18.1", features = ["serde"] } tracing = "0.1.41" tracing-subscriber = "0.3.20" +askama = "0.14.0" [dev-dependencies] http-body-util = "0.1.3" diff --git a/Dockerfile b/Dockerfile index 450761a..48d0ffb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,15 +12,16 @@ RUN rustup target add x86_64-unknown-linux-musl && \ # This downloads and builds the dependencies early allowing built dependencies # to be cached. RUN mkdir src && echo 'fn main() {}' > src/main.rs -COPY Cargo.toml Cargo.lock ./ +COPY Cargo.toml Cargo.lock ./ -RUN --mount=type=cache,target=/usr/local/cargo/registry cargo build --release --target x86_64-unknown-linux-musl +RUN --mount=type=cache,target=/usr/local/cargo/registry cargo build --release --target x86_64-unknown-linux-musl -COPY static ./static -COPY src ./src +COPY ./static ./static +COPY ./src ./src +COPY ./templates ./templates RUN --mount=type=cache,target=/usr/local/cargo/registry < Result<(), Box> { .clone() .unwrap_or_else(|| Url::parse(&format!("http://{}", config.bind_address)).unwrap()); let schema = Schema::build(TiledQuery, EmptyMutation, EmptySubscription) - .data(RootAddress(public_address)) + .data(RootAddress(public_address.clone())) .data(client.clone()) .finish(); @@ -75,7 +76,11 @@ async fn serve(config: GlazedConfig) -> Result<(), Box> { .with_state(client) .fallback(( StatusCode::NOT_FOUND, - Html(include_str!("../static/404.html")), + Html( + NotFound::from_public_address(public_address.clone()) + .render() + .expect("Rendering to a string shouldn't fail"), + ), )) .layer(Extension(schema)); @@ -87,6 +92,22 @@ async fn serve(config: GlazedConfig) -> Result<(), Box> { .await?) } +#[derive(Template)] +#[template(path = "404.html")] +struct NotFound { + graphql_address: Url, + graphiql_address: Url, +} + +impl NotFound { + fn from_public_address(add: Url) -> Self { + Self { + graphql_address: add.join("graphql").unwrap(), + graphiql_address: add.join("graphiql").unwrap(), + } + } +} + async fn graphql_get_warning() -> impl IntoResponse { ( StatusCode::METHOD_NOT_ALLOWED, diff --git a/static/404.html b/templates/404.html similarity index 69% rename from static/404.html rename to templates/404.html index 8361539..bd71e94 100644 --- a/static/404.html +++ b/templates/404.html @@ -7,9 +7,9 @@

GraphQL interface to Tiled

Service is available at - /graphql. + /graphql. Playground is available for testing at - /graphiql + /graphiql

From 4599a0233f4455cc6bb623d66e2d8a324e701def Mon Sep 17 00:00:00 2001 From: Peter Holloway Date: Fri, 9 Jan 2026 13:37:57 +0000 Subject: [PATCH 2/2] Remove dependency on askama Bit of an overkill for two urls --- Cargo.lock | 52 ---------------------------------------------- Cargo.toml | 1 - src/main.rs | 32 ++++++++-------------------- templates/404.html | 4 ++-- 4 files changed, 11 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 347658b..109b47b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,48 +83,6 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" -[[package]] -name = "askama" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" -dependencies = [ - "askama_derive", - "itoa", - "percent-encoding", - "serde", - "serde_json", -] - -[[package]] -name = "askama_derive" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" -dependencies = [ - "askama_parser", - "basic-toml", - "memchr", - "proc-macro2", - "quote", - "rustc-hash", - "serde", - "serde_derive", - "syn", -] - -[[package]] -name = "askama_parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" -dependencies = [ - "memchr", - "serde", - "serde_derive", - "winnow", -] - [[package]] name = "assert-json-diff" version = "2.0.2" @@ -360,15 +318,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "basic-toml" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "2.10.0" @@ -837,7 +786,6 @@ dependencies = [ name = "glazed" version = "0.0.0" dependencies = [ - "askama", "async-graphql", "async-graphql-axum", "axum", diff --git a/Cargo.toml b/Cargo.toml index eb115f6..f7a5b19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ clap = { version = "4.5.48", features = ["derive"] } uuid = { version = "1.18.1", features = ["serde"] } tracing = "0.1.41" tracing-subscriber = "0.3.20" -askama = "0.14.0" [dev-dependencies] http-body-util = "0.1.3" diff --git a/src/main.rs b/src/main.rs index d3a8c9e..d4cc2c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -use askama::Template; use async_graphql::{EmptyMutation, EmptySubscription, Schema}; use axum::http::StatusCode; use axum::response::{Html, IntoResponse}; @@ -74,14 +73,7 @@ async fn serve(config: GlazedConfig) -> Result<(), Box> { ) .route("/asset/{run}/{stream}/{det}/{id}", get(download_handler)) .with_state(client) - .fallback(( - StatusCode::NOT_FOUND, - Html( - NotFound::from_public_address(public_address.clone()) - .render() - .expect("Rendering to a string shouldn't fail"), - ), - )) + .fallback((StatusCode::NOT_FOUND, not_found_page(&public_address))) .layer(Extension(schema)); let listener = tokio::net::TcpListener::bind(config.bind_address).await?; @@ -92,20 +84,14 @@ async fn serve(config: GlazedConfig) -> Result<(), Box> { .await?) } -#[derive(Template)] -#[template(path = "404.html")] -struct NotFound { - graphql_address: Url, - graphiql_address: Url, -} - -impl NotFound { - fn from_public_address(add: Url) -> Self { - Self { - graphql_address: add.join("graphql").unwrap(), - graphiql_address: add.join("graphiql").unwrap(), - } - } +fn not_found_page(public_address: &Url) -> Html { + let graphql = public_address.join("graphql").unwrap(); + let graphiql = public_address.join("graphiql").unwrap(); + Html(format!( + include_str!("../templates/404.html"), + graphql_address = graphql, + graphiql_address = graphiql + )) } async fn graphql_get_warning() -> impl IntoResponse { diff --git a/templates/404.html b/templates/404.html index bd71e94..3ca1c06 100644 --- a/templates/404.html +++ b/templates/404.html @@ -7,9 +7,9 @@

GraphQL interface to Tiled

Service is available at - /graphql. + /graphql. Playground is available for testing at - /graphiql + /graphiql