Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions crates/modelrelay-cloud/src/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ async fn download_redirect() -> Redirect {
Redirect::temporary("/#download")
}

async fn not_found(request: Request) -> impl IntoResponse {
let path = request.uri().path().to_owned();
pub(super) async fn not_found(_request: Request) -> impl IntoResponse {
let body = r#"<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;text-align:center;padding:2rem">
<h1 style="font-size:6rem;font-weight:800;color:#7c3aed;line-height:1;margin:0">404</h1>
<h2 style="font-size:1.5rem;font-weight:600;margin:1rem 0 .5rem">Page Not Found</h2>
Expand All @@ -100,7 +99,7 @@ async fn not_found(request: Request) -> impl IntoResponse {
StatusCode::NOT_FOUND,
Html(modelrelay_web::templates::page_shell(
"404 — Not Found",
&path,
"/",
body,
false,
)),
Expand Down Expand Up @@ -430,7 +429,7 @@ async fn health(State(state): State<Arc<CloudState>>) -> (StatusCode, Json<Value

#[cfg(test)]
mod tests {
use super::desktop_asset_suffix;
use super::{desktop_asset_suffix, not_found};

#[test]
fn maps_known_platforms_to_asset_suffixes() {
Expand All @@ -447,4 +446,28 @@ mod tests {
assert_eq!(desktop_asset_suffix("freebsd"), None);
assert_eq!(desktop_asset_suffix("MACOS"), None);
}

#[tokio::test]
async fn not_found_does_not_self_canonicalize() {
use axum::body::Body;
use axum::http::Request as HttpRequest;
use axum::response::IntoResponse;
let req = HttpRequest::builder()
.uri("/nonexistent-xyz")
.body(Body::empty())
.unwrap();
let resp = not_found(req).await.into_response();
let bytes = axum::body::to_bytes(resp.into_body(), usize::MAX)
.await
.unwrap();
let html = String::from_utf8(bytes.to_vec()).unwrap();
assert!(
!html.contains("/nonexistent-xyz"),
"404 page must not emit the missing URL (found canonical/og:url pointing to it)"
);
assert!(
html.contains("canonical\" href=\"https://modelrelay.io/\""),
"404 page should canonicalize to home"
);
}
}
12 changes: 11 additions & 1 deletion crates/modelrelay-desktop/src/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! background checks are silent on "no update" and surface errors only in logs.

use serde::Serialize;
use tauri::{AppHandle, Emitter, Manager, Runtime};
use tauri::{AppHandle, Emitter, Runtime};
use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogKind};
use tauri_plugin_updater::{Update, UpdaterExt};

Expand Down Expand Up @@ -43,6 +43,11 @@ impl UpdateSummary {
}

/// Look up whether a newer version is available. Does not download or install.
///
/// # Errors
///
/// Returns an error string if the updater plugin cannot be initialized or the
/// remote update check fails (network, signature, or parse errors).
pub async fn fetch_update_summary<R: Runtime>(app: &AppHandle<R>) -> Result<UpdateSummary, String> {
let current = app.package_info().version.to_string();
let updater = app.updater().map_err(|e| e.to_string())?;
Expand All @@ -58,6 +63,11 @@ pub async fn fetch_update_summary<R: Runtime>(app: &AppHandle<R>) -> Result<Upda
///
/// Emits `updater-progress` events to the frontend with `{downloaded, total}`
/// fields so a progress bar can be shown.
///
/// # Errors
///
/// Returns an error string if the updater cannot be initialized, no update is
/// available, or the download/install step fails.
pub async fn download_and_install<R: Runtime>(app: &AppHandle<R>) -> Result<(), String> {
let updater = app.updater().map_err(|e| e.to_string())?;
let Some(update) = updater.check().await.map_err(|e| e.to_string())? else {
Expand Down