refactor(config): optimize backend URL resolution & local AI endpoint detection#2496
refactor(config): optimize backend URL resolution & local AI endpoint detection#2496manucian-official wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthrough
ChangesBackend URL Resolution Refactoring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/api/config.rs (1)
425-439:⚠️ Potential issue | 🟠 Major | ⚡ Quick winCanonicalize schemeless env URLs before returning them.
api_base_from_env()only trims and strips trailing slashes, so a baked value likeapi.tinyhumans.ai/openai/v1/chat/completionsis returned unchanged.effective_backend_api_url()repairs that later, buteffective_api_url()/effective_inference_url()do not, which turns the known schemeless env shape into malformed inference URLs such asapi.tinyhumans.ai/openai/v1/chat/completions/openai/v1/chat/completions. Please normalize env values to a parseable absolute URL here and add a regression test that exerciseseffective_inference_url()through the env fallback path.💡 Possible fix
+fn normalize_env_api_base_url(value: &str) -> String { + let normalized = normalize_api_base_url(value); + if normalized.is_empty() { + return normalized; + } + + url::Url::parse(&normalized) + .or_else(|_| url::Url::parse(&format!("https://{normalized}"))) + .map(|u| u.to_string().trim_end_matches('/').to_string()) + .unwrap_or(normalized) +} + pub fn api_base_from_env() -> Option<String> { // 1. Runtime — each key checked independently. for key in ["BACKEND_URL", "VITE_BACKEND_URL"] { if let Ok(v) = std::env::var(key) { - let url = normalize_api_base_url(&v); + let url = normalize_env_api_base_url(&v); if !url.is_empty() { return Some(url); } } } // 2. Compile-time fallback — baked by the CI pipeline into the binary. // Allows a shipped DMG / installer to resolve the correct environment // without any shell vars in the user's session. for v in compile_time_api_base_env_values().into_iter().flatten() { - let url = normalize_api_base_url(v); + let url = normalize_env_api_base_url(v); if !url.is_empty() { return Some(url); } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/api/config.rs` around lines 425 - 439, The api_base_from_env() path currently returns schemeless values (normalized only by normalize_api_base_url) which later produce malformed inference URLs; update api_base_from_env() to canonicalize any schemeless env URL into a parseable absolute URL (e.g. detect missing scheme and prepend "https://") before returning the value from the loop that calls normalize_api_base_url, so normalize_api_base_url(v) output is checked/converted to an absolute URL; reference functions: api_base_from_env(), normalize_api_base_url(), compile_time_api_base_env_values(), and ensure you add a regression test that sets a compile-time-like schemeless value and exercises effective_inference_url() (via effective_api_url()/effective_backend_api_url() fallback path) to assert the final inference URL is correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/api/config.rs`:
- Around line 425-439: The api_base_from_env() path currently returns schemeless
values (normalized only by normalize_api_base_url) which later produce malformed
inference URLs; update api_base_from_env() to canonicalize any schemeless env
URL into a parseable absolute URL (e.g. detect missing scheme and prepend
"https://") before returning the value from the loop that calls
normalize_api_base_url, so normalize_api_base_url(v) output is checked/converted
to an absolute URL; reference functions: api_base_from_env(),
normalize_api_base_url(), compile_time_api_base_env_values(), and ensure you add
a regression test that sets a compile-time-like schemeless value and exercises
effective_inference_url() (via effective_api_url()/effective_backend_api_url()
fallback path) to assert the final inference URL is correct.
This refactor significantly improves the maintainability, readability, and architectural separation of the backend URL resolution flow used by the gateway/config layer.
The update focuses on:
eliminating duplicated string sanitation logic,
isolating local AI endpoint detection concerns,
simplifying backend API resolution flow,
improving test structure consistency,
and introducing enterprise-grade inline documentation.
Key Improvements
Removed repeated:
as_deref().map(str::trim).filter(|s| !s.is_empty())
Introduced:
#[inline]
fn non_empty_str(s: &Option) -> Option<&str>
Benefits:
Centralized normalization logic
Reduced duplication across config resolution
Easier future validation changes
2. Extracted host_is_local
Separated loopback/private-host classification logic from:
looks_like_local_ai_endpoint()
Benefits:
Clear separation of concerns
Independent unit-testability
Improved readability (“reads like prose”)
Easier future CIDR/private-range expansion
3. Simplified effective_backend_api_url
Refactored nested conditional flow into early-return structure.
Before:
nested if/else
reverse control flow
duplicated fallback handling
After:
happy-path first
reduced nesting
deterministic fallback chain
clearer intent
Benefits:
Lower cognitive complexity
Cleaner execution flow
Easier debugging and future extension
4. Refactored env fallback resolution
Replaced imperative fallback handling:
if let Some(...) { ... }
with:
map(...).unwrap_or_else(...)
Benefits:
More idiomatic Rust
Reduced branching
Cleaner fallback semantics
5. Promoted LOCAL_AI_PORTS to module-level constant
Moved local AI port definitions into a documented module-level constant.
Added:
inline documentation
maintainable port table
centralized extension point
Benefits:
Better discoverability
Easier maintenance
Cleaner local AI classification flow
6. Enterprise-grade documentation overhaul
Added:
module-level architecture docs
ASCII resolution-flow diagram
detailed function-level docs
rationale comments for edge-case behavior
Coverage includes:
resolution order
environment fallback rules
Sentry/issue context
URL normalization rationale
hostname classification decisions
Benefits:
Faster onboarding
Easier reviewer comprehension
Long-term maintainability
7. Refactored test suite into data-driven structure
Simplified repetitive test cases into compact table-driven tests.
Benefits:
Less boilerplate
Easier extension
More maintainable assertions
Better readability
8. Normalized test naming conventions
Renamed:
looks_like_local_ai_* → local_ai_*
normalize_api_base_url_* → normalize_*
Benefits:
Shorter identifiers
Better consistency
Cleaner test output logs
Architectural Impact
This change does not alter public behavior intentionally.
The refactor improves:
internal config maintainability,
readability of URL resolution logic,
future extensibility for local AI runtimes,
and test/debug ergonomics.
No breaking API changes introduced.
Developer Experience Improvements
Easier onboarding for contributors
Reduced config-layer complexity
Cleaner debugging experience
More predictable fallback behavior
Better documentation discoverability
Notes
This refactor prepares the config/runtime layer for:
future multi-provider AI routing,
expanded localhost detection,
environment-aware backend failover,
and cleaner gateway abstraction boundaries.
Summary by CodeRabbit
Refactor
Tests