Skip to content

Feat/improve proxy strategy#81

Merged
touale merged 7 commits intomasterfrom
feat/improve-proxy-strategy
Feb 26, 2026
Merged

Feat/improve proxy strategy#81
touale merged 7 commits intomasterfrom
feat/improve-proxy-strategy

Conversation

@touale
Copy link
Copy Markdown
Owner

@touale touale commented Feb 26, 2026

Summary by CodeRabbit

  • New Features

    • Added /version endpoint returning server version.
    • Enhanced proxy configuration to support per-base-URL rules with path-based matching and a default whitelist of ["/*"].
  • Documentation

    • OAuth callback and proxy routes now excluded from generated API docs.
  • Tests

    • Added test coverage for the new /version endpoint.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 26, 2026

Warning

Rate limit exceeded

@touale has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 14 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between faa045b and d06c454.

📒 Files selected for processing (3)
  • src/framex/driver/ingress.py
  • src/framex/plugins/proxy/config.py
  • tests/test_config.py

Walkthrough

Configuration file removed; new /version endpoint added; route schema exposure controlled via include_in_schema; proxy plugin extended with per-base_url path rules and proxy_url_list normalization; tests and dependency bump updated.

Changes

Cohort / File(s) Summary
Configuration Cleanup
config.js
Removed Renovate configuration file exporting platform, labels, onboarding, hostRules, packageRules, lockFileMaintenance, ignoreDeps, and related settings.
API Versioning & Schema Control
src/framex/driver/application.py, src/framex/driver/ingress.py, tests/api/test_base.py
Added /version GET endpoint (reads settings.server.reversion, REVERSION env, or "unknown"); added include_in_schema: bool = True param to APIIngress.register_route and propagated to FastAPI route registration; added test for /version and adjusted health test description.
Proxy Plugin Enhancements
src/framex/plugins/proxy/config.py, src/framex/plugins/proxy/__init__.py
Introduced ProxyUrlRuleConfig and allowed proxy_urls to be list or dict; added proxy_url_list property, path-aware is_white_url(base_url, path), _match_rules, default white_list ["/*"]; proxy route registration now includes include_in_schema=False, iterates proxy_url_list, and logs target URL in tags.
Dependency Bump
pyproject.toml
Bumped Ray serve optional dependency from 2.53.0 to 2.54.0.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through code to add a view,

/version now tells what the server knew.
Paths and proxies, rules set right,
Hidden docs where routes take flight—
A tiny rabbit cheers tonight! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Feat/improve proxy strategy' directly relates to the main changes, which involve significant improvements to the proxy plugin configuration and functionality, including per-base_url rule matching, path-based filtering, and enhanced logging.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/improve-proxy-strategy

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 26, 2026

Codecov Report

❌ Patch coverage is 85.29412% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/framex/plugins/proxy/config.py 81.48% 2 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/framex/plugins/proxy/__init__.py (1)

45-60: ⚠️ Potential issue | 🟡 Minor

Bug: Logger message uses stale loop variable.

After the for url in settings.proxy_url_list loop completes, url holds only the last URL. If multiple proxy URLs are configured, the success message will incorrectly report only the final URL.

🐛 Proposed fix
-        for url in settings.proxy_url_list:
-            await self._parse_openai_docs(url)
+        for proxy_url in settings.proxy_url_list:
+            await self._parse_openai_docs(proxy_url)
+            logger.success(f"Succeeded to parse openai docs from {proxy_url}")

         if settings.proxy_functions:
             for url, funcs in settings.proxy_functions.items():
                 for func in funcs:
                     await self._parse_proxy_function(func, url)
         else:  # pragma: no cover
             logger.debug("No proxy functions to register")
-
-        logger.success(f"Succeeded to parse openai docs form {url}")

Note: Also fixes the typo "form" → "from".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/framex/plugins/proxy/__init__.py` around lines 45 - 60, In on_start, the
logger.success call uses the loop variable url which is stale after iterating
proxy_url_list; change the success log to reference the full list or a derived
value (e.g., join settings.proxy_url_list or use first/all URLs) instead of url
and fix the typo "form"→"from"; update the logger.success in the on_start method
of the proxy plugin to produce an accurate message (e.g., include ", parsed from
{', '.join(settings.proxy_url_list)}") so it doesn't rely on the loop variable.
🧹 Nitpick comments (4)
src/framex/driver/ingress.py (1)

29-36: Consider moving imports to module level.

The os import and settings import inside the function body add overhead on each call. If there are no circular import issues, consider moving them to the top of the file where other imports reside.

♻️ Proposed refactor

Move the import to module level:

+import os
+
 from framex.adapter import get_adapter
 from framex.consts import BACKEND_NAME
 from framex.driver.application import create_fastapi_application
 from framex.driver.auth import api_key_header, auth_jwt
 from framex.driver.decorator import api_ingress
 from framex.log import setup_logger
 from framex.plugin.model import ApiType, PluginApi
 from framex.utils import escape_tag, shorten_str
+from framex.config import settings

Then simplify the endpoint:

 `@app.get`("/version")
 async def version() -> str:
-    import os
-
-    from framex.config import settings
-
     return settings.server.reversion or os.getenv("REVERSION") or "unknown"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/framex/driver/ingress.py` around lines 29 - 36, The version endpoint
currently imports os and framex.config.settings inside the version() function
which adds per-request overhead; move "import os" and "from framex.config import
settings" to the module-level imports and then simplify the version() handler
(function name: version) to return settings.server.reversion or
os.getenv("REVERSION") or "unknown" directly without inline imports; ensure
there are no circular-import issues after relocating the imports.
src/framex/plugins/proxy/config.py (2)

44-53: Consider extracting the matching logic to reduce duplication.

The pattern matching logic here is similar to AuthConfig._is_url_protected in src/framex/config.py (lines 86-117). Both handle exact matches and prefix wildcards with /*. Consider extracting a shared utility function if this pattern appears elsewhere.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/framex/plugins/proxy/config.py` around lines 44 - 53, The duplicated
path-matching logic in ProxyConfig._match_rules and AuthConfig._is_url_protected
should be extracted into a shared utility (e.g., a function like
match_pattern(pattern: str, path: str) or match_rules(whitelist: list[str],
path: str) in a common utils/module) and both locations should call that
utility; update ProxyConfig._match_rules to delegate to the new helper and
refactor AuthConfig._is_url_protected to use the same helper so exact matches,
the "/*" global match, and prefix wildcard matches (rule.endswith("/*") and
path.startswith(rule[:-1])) behave identically. Ensure the helper is unit-tested
or used by existing tests and exported where needed.

55-61: Minor: Consider a custom exception class for clearer error handling.

The static analysis tool flags the inline error message (TRY003). While this is a low priority, using a dedicated exception or a shorter message would address it:

-        raise ValueError("proxy_urls must be a list or a dict")  # pragma: no cover
+        raise TypeError("Invalid proxy_urls type")  # pragma: no cover
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/framex/plugins/proxy/config.py` around lines 55 - 61, The property
proxy_url_list raises a generic ValueError for invalid proxy_urls; define a
custom exception (e.g., class ProxyConfigError(Exception)) in this module and
replace the ValueError in proxy_url_list with raising ProxyConfigError using a
concise message like "proxy_urls must be list or dict" to satisfy the static
analyzer and provide clearer error semantics.
tests/api/test_base.py (1)

10-13: Consider asserting the response body format.

The test only verifies the status code but doesn't validate that the response is a non-empty string. Since the endpoint can return settings.server.reversion, REVERSION env var, or "unknown", consider asserting the response body is at least a valid string:

 def test_get_version(client: TestClient):
     """Test the version endpoint."""
     r = client.get("/version")
     assert r.status_code == 200
+    assert isinstance(r.json(), str)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/api/test_base.py` around lines 10 - 13, The test test_get_version only
asserts status code; extend it to also validate the response body by asserting
that the returned value from client.get("/version") is a non-empty string (e.g.,
verify isinstance(r.text, str) and r.text.strip() != ""), so you catch cases
where the endpoint returns empty or unexpected content; update the assertions in
test_get_version to check both r.status_code == 200 and the non-empty string
condition.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/framex/plugins/proxy/__init__.py`:
- Around line 45-60: In on_start, the logger.success call uses the loop variable
url which is stale after iterating proxy_url_list; change the success log to
reference the full list or a derived value (e.g., join settings.proxy_url_list
or use first/all URLs) instead of url and fix the typo "form"→"from"; update the
logger.success in the on_start method of the proxy plugin to produce an accurate
message (e.g., include ", parsed from {', '.join(settings.proxy_url_list)}") so
it doesn't rely on the loop variable.

---

Nitpick comments:
In `@src/framex/driver/ingress.py`:
- Around line 29-36: The version endpoint currently imports os and
framex.config.settings inside the version() function which adds per-request
overhead; move "import os" and "from framex.config import settings" to the
module-level imports and then simplify the version() handler (function name:
version) to return settings.server.reversion or os.getenv("REVERSION") or
"unknown" directly without inline imports; ensure there are no circular-import
issues after relocating the imports.

In `@src/framex/plugins/proxy/config.py`:
- Around line 44-53: The duplicated path-matching logic in
ProxyConfig._match_rules and AuthConfig._is_url_protected should be extracted
into a shared utility (e.g., a function like match_pattern(pattern: str, path:
str) or match_rules(whitelist: list[str], path: str) in a common utils/module)
and both locations should call that utility; update ProxyConfig._match_rules to
delegate to the new helper and refactor AuthConfig._is_url_protected to use the
same helper so exact matches, the "/*" global match, and prefix wildcard matches
(rule.endswith("/*") and path.startswith(rule[:-1])) behave identically. Ensure
the helper is unit-tested or used by existing tests and exported where needed.
- Around line 55-61: The property proxy_url_list raises a generic ValueError for
invalid proxy_urls; define a custom exception (e.g., class
ProxyConfigError(Exception)) in this module and replace the ValueError in
proxy_url_list with raising ProxyConfigError using a concise message like
"proxy_urls must be list or dict" to satisfy the static analyzer and provide
clearer error semantics.

In `@tests/api/test_base.py`:
- Around line 10-13: The test test_get_version only asserts status code; extend
it to also validate the response body by asserting that the returned value from
client.get("/version") is a non-empty string (e.g., verify isinstance(r.text,
str) and r.text.strip() != ""), so you catch cases where the endpoint returns
empty or unexpected content; update the assertions in test_get_version to check
both r.status_code == 200 and the non-empty string condition.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd8d3e3 and b115a53.

📒 Files selected for processing (6)
  • config.js
  • src/framex/driver/application.py
  • src/framex/driver/ingress.py
  • src/framex/plugins/proxy/__init__.py
  • src/framex/plugins/proxy/config.py
  • tests/api/test_base.py
💤 Files with no reviewable changes (1)
  • config.js

@touale touale merged commit 7a72c67 into master Feb 26, 2026
8 of 9 checks passed
@touale touale deleted the feat/improve-proxy-strategy branch February 26, 2026 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant