fix(functions): honor a caller's Content-Type override regardless of casing - #2455
Conversation
@supabase/auth-js
@supabase/functions-js
@supabase/postgrest-js
@supabase/realtime-js
@supabase/storage-js
@supabase/supabase-js
commit: |
|
Hi @i-anubhav-anand, thank you so much for contributing to Supabase! 💚 This is a really nice catch, thanks for this PR! I have just two small nitpicks, both optional and neither blocking:
Neither of these changes what the PR does, and the fix itself looks good to me. Thank you again for taking the time to track this down and write it up so clearly. It is contributions like yours that keep these libraries solid. |
|
Also, please @i-anubhav-anand rebase with |
…casing
invoke() detected a caller-supplied Content-Type with a case-sensitive
hasOwnProperty('Content-Type') check, so a lowercase 'content-type' header
slipped through: the SDK auto-set its own Content-Type and JSON-stringified the
body, emitting a second, conflicting Content-Type header. Match the header name
case-insensitively, since HTTP header names are case-insensitive.
f96164e to
8e94d7a
Compare
|
Thanks @mandarini! 💚 Addressed both nitpicks:
Also rebased on |
This PR updates `@supabase/supabase-js` to v2.110.0. **Source**: supabase-js-stable-release --- ## Release Notes ## v2.110.0 ## 2.110.0 (2026-06-30) ### 🚀 Features - **repo:** drop Node.js 20 support ([#2482](supabase/supabase-js#2482)) ### ❤️ Thank You - Katerina Skroumpelou @mandarini ## v2.109.0 ## 2.109.0 (2026-06-30) ### 🚀 Features - **auth:** add custom_claims_allowlist to custom providers admin API ([#2473](supabase/supabase-js#2473)) - **realtime:** add postgres_changes filter builder, new operators and select ([#2463](supabase/supabase-js#2463)) - **storage:** expose purgeCache for buckets and single objects ([#2429](supabase/supabase-js#2429)) ### 🩹 Fixes - **functions:** honor a caller's Content-Type override regardless of casing ([#2455](supabase/supabase-js#2455)) - **realtime:** pin @supabase/phoenix and browser test CDN deps ([#2457](supabase/supabase-js#2457)) - **realtime:** add replication connection system message option ([#2470](supabase/supabase-js#2470)) - **storage:** keep sortBy defaults when list() is given a partial sortBy ([#2454](supabase/supabase-js#2454)) ### ❤️ Thank You - Anubhav Anand @i-anubhav-anand - Cemal Kılıç @cemalkilic - Claude Opus 4.8 (1M context) - Filipe Cabaço @filipecabaco - Katerina Skroumpelou @mandarini - Lenny - Rodrigo Mansueli @mansueli ## v2.108.2 ## 2.108.2 (2026-06-15) ### 🩹 Fixes - **auth:** preserve valid session on refresh failure and cooldown repeat failures ([#2436](supabase/supabase-js#2436)) - **realtime:** clarify httpSend() 404 error and server migration note ([#2444](supabase/supabase-js#2444)) - **release:** pin Deno and bound JSR publish to survive stranded-task hangs ([#2439](supabase/supabase-js#2439)) - **release:** restore JSR publish flags and enable for beta ([#2440](supabase/supabase-js#2440)) ### ❤️ Thank You - Katerina Skroumpelou @mandarini ## v2.108.1 ## 2.108.1 (2026-06-09) ### 🩹 Fixes - **ci:** forward DOGFOOD_APP_CLIENT_ID to dogfood workflow ([#2434](supabase/supabase-js#2434)) - **postgrest:** then typing ([#2349](supabase/supabase-js#2349)) ### ❤️ Thank You - Katerina Skroumpelou @mandarini - Vaibhav @7ttp This PR was created automatically. Co-authored-by: supabase-workflow-trigger[bot] <266661614+supabase-workflow-trigger[bot]@users.noreply.github.com>
This PR updates @supabase/*-js libraries to version 2.110.1. **Source**: supabase-js-stable-release **Changes**: - Updated @supabase/supabase-js to 2.110.1 - Updated @supabase/auth-js to 2.110.1 - Updated @supabase/realtime-js to 2.110.1 - Updated @supabase/postgest-js to 2.110.1 - Refreshed pnpm-lock.yaml --- ## Release Notes ## v2.110.1 ## 2.110.1 (2026-07-07) ### 🩹 Fixes - **auth:** defer init-time notifications until initializePromise resolves ([#2498](supabase/supabase-js#2498)) - **realtime:** suppress disconnected status from onHeartbeat consumers ([#2496](supabase/supabase-js#2496)) ### ❤️ Thank You - Katerina Skroumpelou @mandarini ## v2.110.0 ## 2.110.0 (2026-06-30) ### 🚀 Features - **repo:** drop Node.js 20 support ([#2482](supabase/supabase-js#2482)) ### ❤️ Thank You - Katerina Skroumpelou @mandarini ## v2.109.0 ## 2.109.0 (2026-06-30) ### 🚀 Features - **auth:** add custom_claims_allowlist to custom providers admin API ([#2473](supabase/supabase-js#2473)) - **realtime:** add postgres_changes filter builder, new operators and select ([#2463](supabase/supabase-js#2463)) - **storage:** expose purgeCache for buckets and single objects ([#2429](supabase/supabase-js#2429)) ### 🩹 Fixes - **functions:** honor a caller's Content-Type override regardless of casing ([#2455](supabase/supabase-js#2455)) - **realtime:** pin @supabase/phoenix and browser test CDN deps ([#2457](supabase/supabase-js#2457)) - **realtime:** add replication connection system message option ([#2470](supabase/supabase-js#2470)) - **storage:** keep sortBy defaults when list() is given a partial sortBy ([#2454](supabase/supabase-js#2454)) ### ❤️ Thank You - Anubhav Anand @i-anubhav-anand - Cemal Kılıç @cemalkilic - Claude Opus 4.8 (1M context) - Filipe Cabaço @filipecabaco - Katerina Skroumpelou @mandarini - Lenny - Rodrigo Mansueli @mansueli This PR was created automatically. Co-authored-by: supabase-workflow-trigger[bot] <266661614+supabase-workflow-trigger[bot]@users.noreply.github.com>
🔍 Description
What changed?
FunctionsClient.invoke()decided whether to auto-set aContent-Typeusing a case-sensitivehasOwnProperty('Content-Type')check. HTTP header names are case-insensitive, so a caller-supplied lowercasecontent-typewas not detected. This matches the header name case-insensitively before deciding to auto-set/serialize.Why was this change needed?
With a lowercase
content-type, the SDK fell into the auto-detect branch: it set its ownContent-Type: application/json, JSON-stringified the body, then merged the caller's header on top — producing two conflictingContent-Typeheaders and ignoring the caller's intent. The docs state you can override by passing your own Content-Type header.📸 Examples / Proof
Tests live in
test/spec/params.spec.tsinside the existingbody stringify with custom headersblock (reusing itscustomFetchharness). Onmasterthe lowercase case fails:The lowercase test also asserts the request body is still
'{"a":1}', locking in that the fix routes through the correct (JSON) serialization branch. The uppercase baseline is unchanged.🔄 Breaking changes
📋 Checklist
fix(functions): ...pnpm nx format📝 Additional notes
Rebased on
master. Addressed review: moved the tests intoparams.spec.ts(removed the standalone file) and added the request-body assertion for the lowercase case.