From 141f9ee32dc231a2243a530c1e92dbad06ee2ed4 Mon Sep 17 00:00:00 2001 From: Jeena Date: Fri, 20 Mar 2026 12:21:01 +0000 Subject: [PATCH] fix: show human-readable login errors instead of raw HTML When the server returns an HTML response (wrong URL, redirect to a login page), the error dialog previously showed the full HTML body. Now detect HTML responses and show a short actionable message: - 404 with HTML: 'API endpoint not found. Check your server URL.' - 401/403 with HTML: 'Wrong username or password.' - 200 with HTML (no Auth= token): explain the endpoint is not FreshRSS - Non-HTML bodies are shown as-is (they are already readable) --- src/api.rs | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/api.rs b/src/api.rs index c9a0e71..312cd82 100644 --- a/src/api.rs +++ b/src/api.rs @@ -73,13 +73,26 @@ impl Api { let body = resp.text().await.map_err(|e| e.to_string())?; if !status.is_success() { - return Err(format!("Login failed ({}): {}", status, body.trim())); + let msg = human_error(&body, status.as_u16()); + return Err(format!("Login failed ({}): {}", status.as_u16(), msg)); } let auth_token = body .lines() .find_map(|l| l.strip_prefix("Auth=")) - .ok_or_else(|| "No Auth token in response".to_string())? + .ok_or_else(|| { + // The server returned 200 but not the expected API response — + // most likely the URL points to a web page, not a FreshRSS API. + if looks_like_html(&body) { + format!( + "The server at {} does not appear to be a FreshRSS \ + Google Reader API endpoint. Check your server URL.", + base + ) + } else { + format!("Unexpected response from server: {}", body.trim()) + } + })? .to_string(); Ok(Self { @@ -195,6 +208,28 @@ impl Api { } } +fn looks_like_html(body: &str) -> bool { + let trimmed = body.trim_start(); + trimmed.starts_with(" String { + if looks_like_html(body) { + match status { + 401 | 403 => "Wrong username or password.".to_string(), + 404 => "API endpoint not found. Check your server URL.".to_string(), + _ => format!("Server returned HTTP {status}. Check your server URL."), + } + } else { + let trimmed = body.trim(); + if trimmed.is_empty() { + format!("Server returned HTTP {status} with no message.") + } else { + trimmed.to_string() + } + } +} + fn plain_text_excerpt(html: &str, max_chars: usize) -> String { // Very simple HTML stripper — remove tags, collapse whitespace let mut out = String::with_capacity(html.len());