813fb896ff
Pulls three pattern groups into shared helpers so a rename or wire-format tweak edits one file instead of 10+: - BulkAction enum in doctate-common replaces the "close"/"analyze"/"reset" string literals that were duplicated between the bulk handler and 3 attack/CSRF test files. FromStr preserves the exact "Unbekannte Aktion" error shape; the handler match is now exhaustive over the enum. - join_url helper in doctate-common absorbs 7 identical trim_end_matches+format! call sites across client-core, client-desktop, server/transcribe (ollama, whisper), and server/analyze (llm). - server/tests/common/artefacts.rs re-exports ONELINER_FILENAME (doctate-common), DOCUMENT_FILE + ANALYSIS_INPUT_FILE (doctate-server::analyze), and CLOSE_MARKER (doctate-server::paths) so test files reference the canonical name instead of inlining literals. Also lifts client-desktop local duplication: - paths.rs: project_path helper collapses 4 identical ProjectDirs chains - main.rs: or_die helper replaces 4 eprintln!+exit(1) blocks - app.rs: named RecordingContext struct replaces (Uuid, String) tuple at 3 sites around the ffmpeg-flush finalization path Verification: 397 tests pass (baseline was 389; +8 for new unit tests on BulkAction and join_url), 0 failed, 4 ignored (unchanged). clippy clean.
56 lines
1.7 KiB
Rust
56 lines
1.7 KiB
Rust
//! Small URL-assembly helpers shared by every HTTP caller in the
|
|
//! workspace.
|
|
//!
|
|
//! All clients (desktop, server-internal, server-to-Ollama/Whisper)
|
|
//! end up building `{base_url}{path}` where `base_url` comes from
|
|
//! config and may or may not carry a trailing slash. The raw
|
|
//! `format!("{}{}", base.trim_end_matches('/'), path)` pattern was
|
|
//! duplicated in seven call sites; centralizing it here keeps any
|
|
//! future rule (enforce a leading slash on the path, tolerate
|
|
//! `http://host/` with a path segment, normalize percent-encoding)
|
|
//! in one place.
|
|
|
|
/// Join a base URL with an absolute path, normalizing any trailing
|
|
/// slash on the base. The path is expected to start with `/`; no
|
|
/// validation is performed — callers already pass constants like
|
|
/// [`crate::UPLOAD_PATH`].
|
|
///
|
|
/// Examples:
|
|
/// - `join_url("http://h", "/a")` → `"http://h/a"`
|
|
/// - `join_url("http://h/", "/a")` → `"http://h/a"`
|
|
/// - `join_url("http://h//", "/a")` → `"http://h/a"`
|
|
pub fn join_url(base: &str, path: &str) -> String {
|
|
let mut out = String::with_capacity(base.len() + path.len());
|
|
out.push_str(base.trim_end_matches('/'));
|
|
out.push_str(path);
|
|
out
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn no_trailing_slash_on_base() {
|
|
assert_eq!(join_url("http://h", "/a"), "http://h/a");
|
|
}
|
|
|
|
#[test]
|
|
fn single_trailing_slash_on_base() {
|
|
assert_eq!(join_url("http://h/", "/a"), "http://h/a");
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_trailing_slashes_on_base() {
|
|
assert_eq!(join_url("http://h///", "/a"), "http://h/a");
|
|
}
|
|
|
|
#[test]
|
|
fn nested_path() {
|
|
assert_eq!(
|
|
join_url("https://example.com/", "/api/upload"),
|
|
"https://example.com/api/upload"
|
|
);
|
|
}
|
|
}
|