refactor: share the HTTP request pieces between the fetch layers - #1647
Open
spydon wants to merge 4 commits into
Open
refactor: share the HTTP request pieces between the fetch layers#1647spydon wants to merge 4 commits into
spydon wants to merge 4 commits into
Conversation
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
Tr00d
approved these changes
Aug 5, 2026
The four fetch layers each rebuilt the same primitives. They now come from
`supabase_common`:
- `sendRequest`, which sends over the caller's `Client` or a one-off one.
Used by functions, storage's three send sites and the Iceberg catalog.
- `headerValue`, a case-insensitive header lookup.
- `setDefaultContentType`, which only sets `Content-Type` when the caller
did not, replacing storage's and functions' own case-insensitive checks.
- `responseMediaType`, replacing functions' manual parse of the response
content type and the Iceberg catalog's `contains('application/json')`.
- `tryDecodeJsonObject`, for error bodies that a proxy or gateway may
return as something other than a JSON object.
Two bugs fall out of the last one:
- Storage cast the decoded error body to `Map<String, dynamic>` inside a
`try`/`on FormatException`, so a JSON body that parsed but was not an
object (an array, say) escaped as a `TypeError` instead of a
`StorageException`.
- Postgrest wrapped both the decode and the `maybeSingle` handling in one
`try`/`catch (_)`, so the typed exception the handler rethrows for a real
error was swallowed and replaced by a generic one built from the raw body,
losing the reported code, details and hint.
Postgrest's own send site keeps managing its `Client` explicitly, since it
has to close a client it created even when the response body fails midway,
which `BaseRequest.send` does not do.
Part of #1572 (tier 3), under the v3 umbrella #1278.
Removing the catch-all around the postgrest error decode exposed the next
layer of the same problem: `PostgrestException.fromJson` cast `code` and
`hint` to `String` and required a `String` message, so an error body that is
a JSON object with different field types, say the `{"code": 502, "message":
"Bad gateway"}` a gateway returns, threw a `TypeError` out of the builder
instead of surfacing as a `PostgrestException`.
Both factories now read every field defensively, so any JSON object produces
an exception. `StorageException.fromJson` had the same casts and the same
exposure.
Part of #1572 (tier 3), under the v3 umbrella #1278.
spydon
force-pushed
the
breaking/shared-exponential-backoff
branch
from
August 5, 2026 15:15
c2b1b6c to
549c593
Compare
spydon
force-pushed
the
refactor/shared-http-fetch-pieces
branch
from
August 5, 2026 15:15
5a5a1fa to
c3cfc32
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tier 3 of #1572, last of four PRs. Stacked on #1646 (→ #1645 → #1644).
The tier 3 note said the fetch wrappers are shareable in pieces, not as one wrapper, since each is bound to its own exception type. These are the pieces, now in
supabase_common:sendRequest(request, {httpClient})httpClient != null ? httpClient.send(request) : request.send()in functions, storage (3 sites) and the Iceberg catalogheaderValue(headers, name)setDefaultContentType(headers, value)Content-Typeunless the caller already did" checksresponseMediaType(headers)(headers['Content-Type'] ?? headers['content-type'] ?? 'text/plain').split(';')[0].trim().toLowerCase()and the Iceberg catalog'scontentType.contains('application/json')tryDecodeJsonObject(body)supabase_commongains a dependency onhttp(^1.6.0, the constraint every other package already uses).Two bugs this surfaces
Each has a regression test that fails without the fix.
Postgrest swallowed typed errors for
maybeSingle(). The decode and themaybeSinglehandling shared onetry/catch (_):_handleMaybeSingleErrorreturns null data for the "0 rows" case and rethrows otherwise, but that rethrow landed in thecatch (_)and was replaced by a generic exception built from the raw body. So amaybeSingle()request that failed for a real reason lost itserrorCode,detailsandhint. Splitting the decode from the handling fixes it.A JSON error body with unexpected field types crashed. Removing that catch-all exposed the next layer of the same problem:
PostgrestException.fromJsoncastcodeandhinttoStringand required aStringmessage, so{"code": 502, "message": "Bad gateway"}— a shape gateways really do return — threw aTypeErrorout of the builder. BothfromJsonfactories now read every field defensively, so any JSON object yields an exception.StorageException.fromJsonhad the same casts and the same exposure.The matching storage bug, where a JSON error body that is not an object escaped as a
TypeError, is fixed in #1644; here its inline guard collapses intotryDecodeJsonObject.Not converted
Postgrest's own send site keeps managing its
Clientexplicitly. It has to close a client it created even when the response body fails midway, andBaseRequest.sendonly closes its internal client when the stream completes normally.gotrue and postgrest also keep setting
Content-Typeunconditionally rather than adoptingsetDefaultContentType: both always JSON-encode the body, so honouring a caller-provided content type there would mislabel the request rather than respect it.Testing
New
http_test.dartinsupabase_commoncovers each helper, plus the three regression tests described above.melos analyze,dcm analyzeandmelos formatclean;gotrue,postgrest,storage_client,functions_client,realtime_client,supabase,supabase_commonandsupabase_fluttersuites pass. Capability matrix symbol and drift checks pass.