Skip to content

fix(form-urlencoded): do not claim a content-type it did not encode - #914

Merged
yordis merged 1 commit into
masterfrom
yordis/fix-form-urlencoded-double-content-type
Aug 19, 2026
Merged

fix(form-urlencoded): do not claim a content-type it did not encode#914
yordis merged 1 commit into
masterfrom
yordis/fix-form-urlencoded-double-content-type

Conversation

@yordis

@yordis yordis commented Aug 19, 2026

Copy link
Copy Markdown
Member
  • Tesla.Middleware.JSON and this middleware are meant to share one stack, but feat: support {:form,data} tagged body tuples #886 only wired up half of that handshake: JSON learned to decline form-tagged bodies, while nothing taught this middleware to decline a body JSON had already encoded.
  • The consequence is two content-type headers on every JSON request from any client that also has a single form-encoded operation, and a server is free to reject that.
  • Reordering the stack cannot avoid it, because this middleware has to stay after JSON: in front of it, a struct body reaches the catch-all and raises.
  • Deciding this in encodable?/1 makes the rule uniform across both middlewares, which is that a middleware claims the content-type precisely when it encoded the body.
  • One behavior change worth calling out: a body that is already a binary no longer receives a form content-type. That path was undocumented, the existing binary test only pinned the body and never the header, and Tesla.Middleware.JSON has behaved this way since 9514bd1.

Sharing a stack with Tesla.Middleware.JSON put two content-type headers on
every JSON request, which a server is free to reject.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis
yordis requested a review from a team as a code owner August 19, 2026 19:15
Copilot AI lite review requested due to automatic review settings August 19, 2026 19:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@cursor

cursor Bot commented Aug 19, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Behavior change for pre-encoded binary bodies (no form content-type anymore) could affect callers that relied on the old header; the fix is intentional and aligned with JSON middleware.

Overview
Tesla.Middleware.FormUrlencoded now treats an already-binary request body as non-encodable, matching Tesla.Middleware.JSON: the body is left as-is and no content-type header is set. That fixes clients using JSON then FormUrlencoded in one stack, where JSON had already encoded the body and set application/json but FormUrlencoded was still appending a second header.

The rule is enforced in encodable?/1 (binary → false) instead of only passing binaries through in encode_body/1. Tagged {:form_urlencoded, data} and map bodies still get encoded and the form content-type as before.

Docs describe the shared-stack behavior. Tests cover binary requests with no outgoing content-type and a JSON+FormUrlencoded stack asserting a single header for JSON vs tagged form bodies.

Reviewed by Cursor Bugbot for commit 10b2429. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added the bug label Aug 19, 2026
@yordis
yordis merged commit b250b50 into master Aug 19, 2026
12 checks passed
@yordis
yordis deleted the yordis/fix-form-urlencoded-double-content-type branch August 19, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants