-
Notifications
You must be signed in to change notification settings - Fork 33
feat: add raw requestor for calling arbitrary endpoints #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis PR introduces a new Changes
Sequence Diagram(s)sequenceDiagram
participant Client as OpenFgaClient
participant ApiClient as ApiClient
participant HTTP as HTTP Layer
participant Response as Response Parser
Client->>Client: raw_request(method, path, params...)
Client->>Client: Validate operation_name (required)
Client->>Client: Resolve path params (auto-fill store_id)
Client->>Client: URL-encode path params
Client->>Client: Build query string
Client->>Client: Serialize body (JSON if dict/list)
Client->>Client: Set default headers (Content-Type, Accept)
Client->>ApiClient: call_api(method, path, body, headers, query_params)
ApiClient->>HTTP: Execute HTTP request
HTTP->>ApiClient: Return HTTP response
ApiClient->>Response: Parse response body
Response->>Response: Try JSON decode, fallback to raw
Response->>Client: Return RawResponse(status, headers, body)
Client->>Client: Return RawResponse to caller
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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 |
840bc79 to
f4dec14
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
README.md (1)
4-4: Malformed badge URL - missing closing parenthesis.The Socket badge URL appears to be malformed. It's missing a closing parenthesis before the opening bracket for the link URL.
🔧 Suggested fix
-[ +[](https://socket.dev/pypi/package/openfga-sdk)
🤖 Fix all issues with AI agents
In `@openfga_sdk/sync/client/client.py`:
- Around line 1233-1234: The except block "except ApiException as e: raise" is
redundant and should be removed; locate the handler in
openfga_sdk/sync/client/client.py where ApiException is caught and simply delete
that except clause so the original ApiException will propagate naturally (leave
surrounding try/except structure and other exception handlers unchanged and
ensure indentation remains valid).
🧹 Nitpick comments (6)
openfga_sdk/client/models/raw_response.py (1)
49-63: Consider movingjsonimport to module level.The
jsonmodule is imported inside the method body (lines 50 and 58). Sincejsonis part of Python's standard library and always available, importing it at the module level (line 8-9 area) would be more idiomatic and slightly more efficient for repeated calls.♻️ Suggested refactor
Add import at the top of the file:
from dataclasses import dataclass from typing import Any +import jsonThen remove the inline imports in
json()andtext()methods.openfga_sdk/sync/client/client.py (2)
1139-1141: Consider validatingoptions["headers"]type before merging.The code assumes
options["headers"]is a dict when callingupdate(). For consistency with theset_heading_if_not_sethelper (lines 102-103) which handles non-dict headers values, consider adding a type check.♻️ Suggested defensive check
request_headers = dict(headers) if headers else {} if options and options.get("headers"): - request_headers.update(options["headers"]) + opt_headers = options.get("headers") + if isinstance(opt_headers, dict): + request_headers.update(opt_headers)
1196-1199: Header checks are case-sensitive but HTTP headers are case-insensitive.The checks
"Content-Type" not in request_headerswon't match if a user provides"content-type"(lowercase). This could result in duplicate headers with different casing.♻️ Suggested case-insensitive check
+ # Case-insensitive header check helper + request_headers_lower = {k.lower(): k for k in request_headers} + - if "Content-Type" not in request_headers: + if "content-type" not in request_headers_lower: request_headers["Content-Type"] = "application/json" - if "Accept" not in request_headers: + if "accept" not in request_headers_lower: request_headers["Accept"] = "application/json"test/sync/client/client_test.py (1)
4151-4454: Good raw_request coverage; consider 2 small edge-case tests.
- Assert that custom headers passed to
raw_request(..., headers=...)are actually forwarded (e.g., verifyX-Experimental-Featureis present in the mocked call headers).- Add a non-JSON response body case (e.g.,
content-type: text/plain) to validateRawResponse.text()/json()behavior when JSON parsing should fail.openfga_sdk/client/client.py (2)
1140-1143: Define header precedence + coerce header values to strings.Right now
options["headers"]overrides the explicitheadersargument (Line 1140-1143), and non-string values can slip in (your tests cover integer header values elsewhere). It’d be good to (a) document precedence, and (b) normalize values tostrbefore sending.
1209-1234: Tighten telemetry + response typing.
TelemetryAttributeimport inside the method is unused (Line 1211).TelemetryAttributes.fga_client_request_methodis set tooperation_name.lower()(Line 1213-1214). Please confirm this attribute is meant to hold the operation name vs the HTTP verb (since you already havemethod).- Response parsing should allow top-level JSON arrays too (currently annotated as
dict[str, Any], butjson.loads(...)can returnlist[Any]). Consider widening the type and aligningRawResponse.bodyaccordingly.Also applies to: 1242-1265
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
README.mdopenfga_sdk/api_client.pyopenfga_sdk/client/client.pyopenfga_sdk/client/models/__init__.pyopenfga_sdk/client/models/raw_response.pyopenfga_sdk/sync/api_client.pyopenfga_sdk/sync/client/client.pyopenfga_sdk/telemetry/attributes.pytest/client/client_test.pytest/sync/client/client_test.py
🧰 Additional context used
🧬 Code graph analysis (6)
openfga_sdk/client/models/__init__.py (1)
openfga_sdk/client/models/raw_response.py (1)
RawResponse(13-90)
openfga_sdk/sync/api_client.py (3)
openfga_sdk/rest.py (1)
getheaders(111-115)openfga_sdk/sync/rest.py (1)
getheaders(111-115)test/error_handling_test.py (1)
getheaders(31-32)
openfga_sdk/api_client.py (3)
openfga_sdk/rest.py (1)
getheaders(111-115)openfga_sdk/sync/rest.py (1)
getheaders(111-115)test/error_handling_test.py (1)
getheaders(31-32)
test/client/client_test.py (1)
openfga_sdk/client/models/raw_response.py (3)
RawResponse(13-90)json(33-65)text(67-90)
test/sync/client/client_test.py (2)
openfga_sdk/client/models/raw_response.py (3)
RawResponse(13-90)json(33-65)text(67-90)openfga_sdk/rest.py (6)
RESTClientObject(128-461)response(56-60)response(63-67)status(84-88)status(91-95)close(162-166)
openfga_sdk/client/client.py (6)
openfga_sdk/client/models/raw_response.py (2)
json(33-65)RawResponse(13-90)openfga_sdk/exceptions.py (2)
ApiException(118-298)FgaValidationException(36-61)openfga_sdk/sync/rest.py (5)
RESTResponse(27-125)data(70-74)data(77-81)status(84-88)status(91-95)openfga_sdk/telemetry/attributes.py (3)
get(97-104)TelemetryAttribute(14-16)TelemetryAttributes(19-369)openfga_sdk/api_client.py (2)
get_store_id(937-941)update_params_for_auth(771-810)openfga_sdk/sync/api_client.py (2)
get_store_id(937-941)update_params_for_auth(771-810)
🔇 Additional comments (17)
openfga_sdk/client/models/__init__.py (1)
26-26: LGTM!The
RawResponseimport and export follow the established pattern in this module. This correctly exposes the new model for downstream usage.Also applies to: 49-49
openfga_sdk/api_client.py (1)
420-423: LGTM!The change from
response_data.headerstoresponse_data.getheaders()ensures consistent header access and returns a properdict[str, str]that aligns with the newRawResponsemodel's expected header format.openfga_sdk/sync/api_client.py (1)
420-423: LGTM!Consistent with the async client change, ensuring both sync and async variants use the same
getheaders()method for header access.openfga_sdk/telemetry/attributes.py (1)
298-302: Good defensive fix for handling non-dict response bodies.The added
isinstance(response.body, dict)check properly guards againstAttributeErrorwhenbodyisbytes,str, orNone- which is possible with the newRawResponsemodel where body type isbytes | str | dict[str, Any] | None.README.md (2)
51-51: LGTM!Good addition to the table of contents for the new feature section.
1264-1400: Comprehensive documentation for the newraw_requestfeature.The documentation is well-structured with clear use cases and multiple examples covering:
- Basic POST requests
- Response handling (JSON parsing, accessing headers/status)
- GET requests with query parameters
- Path parameter substitution (explicit and automatic store_id)
The examples follow the existing documentation patterns in this README.
openfga_sdk/client/models/raw_response.py (1)
33-90: LGTM! The helper methods are well-implemented.The
json()andtext()methods handle all expected body types (dict, str, bytes, None) with appropriate error handling and fallbacks. The UnicodeDecodeError handling witherrors="replace"intext()is a good defensive pattern.openfga_sdk/sync/client/client.py (3)
1-4: LGTM! Imports are appropriate for the new functionality.The new imports (
json,urllib.parse,RawResponse,ApiException,RESTResponse) are all necessary for theraw_requestmethod implementation.Also applies to: 38-38, 46-46, 77-77
1146-1167: LGTM! Path parameter handling is well-implemented.The logic correctly:
- Auto-fills
store_idfrom configuration when not provided inpath_params- URL-encodes path parameter values for safety
- Validates that all placeholders are resolved before making the request
1243-1265: LGTM! Response body parsing handles all expected formats.The parsing logic correctly handles JSON responses (both string and bytes) with appropriate fallbacks for non-JSON content. The final
RawResponseconstruction properly captures status, headers, and body.test/client/client_test.py (5)
28-28: LGTM! Import is correctly placed.The
RawResponseimport is appropriately added alongside other model imports.
4170-4218: LGTM! Comprehensive test for POST request with body.This test verifies:
- RawResponse creation and properties (status, headers, body)
json()andtext()helper methods work correctly- The API is called with correct method, path, body, query params, and headers
4330-4379: LGTM! Validation error tests cover required scenarios.The tests properly verify that
FgaValidationExceptionis raised for:
- Missing
operation_name(required parameter)- Missing
store_idwhen path contains{store_id}- Missing path parameters when placeholders exist
4381-4413: LGTM! List query parameter expansion test.This test verifies that list values in
query_paramsare correctly expanded into multiple key-value pairs (e.g.,{"ids": ["id1", "id2", "id3"]}becomes[("ids", "id1"), ("ids", "id2"), ("ids", "id3")]).
4444-4475: LGTM! URL encoding test verifies special character handling.The test confirms that path parameters containing spaces and special characters (
value with spaces & special chars) are properly URL-encoded tovalue%20with%20spaces%20%26%20special%20chars.test/sync/client/client_test.py (1)
26-26: RawResponse import looks fine.openfga_sdk/client/client.py (1)
3-6: No issues with the new imports.Also applies to: 39-40, 46-51, 76-76
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
@rhamzeh @SoulPancake, please review and suggest if any changes are required. |
This adds the capability to call any FGA endpoint.
What problem is being solved?
How is it being solved?
What changes are made to solve it?
References
closes
Review Checklist
mainSummary by CodeRabbit
Release Notes
New Features
raw_requestmethod to OpenFgaClient for making custom HTTP requests to OpenFGA endpointsBug Fixes
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.