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)
This commit is contained in:
parent
5dee5cc52b
commit
141f9ee32d
1 changed files with 37 additions and 2 deletions
39
src/api.rs
39
src/api.rs
|
|
@ -73,13 +73,26 @@ impl Api {
|
||||||
let body = resp.text().await.map_err(|e| e.to_string())?;
|
let body = resp.text().await.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
if !status.is_success() {
|
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
|
let auth_token = body
|
||||||
.lines()
|
.lines()
|
||||||
.find_map(|l| l.strip_prefix("Auth="))
|
.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();
|
.to_string();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
@ -195,6 +208,28 @@ impl Api {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn looks_like_html(body: &str) -> bool {
|
||||||
|
let trimmed = body.trim_start();
|
||||||
|
trimmed.starts_with("<!") || trimmed.to_ascii_lowercase().starts_with("<html")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn human_error(body: &str, status: u16) -> 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 {
|
fn plain_text_excerpt(html: &str, max_chars: usize) -> String {
|
||||||
// Very simple HTML stripper — remove tags, collapse whitespace
|
// Very simple HTML stripper — remove tags, collapse whitespace
|
||||||
let mut out = String::with_capacity(html.len());
|
let mut out = String::with_capacity(html.len());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue