Skip to content

fix(ui): preserve multipart Content-Type in apiFetch (RAN-34)#78

Merged
aksOps merged 1 commit intomainfrom
fix/ran-34-multipart-uploads
Apr 24, 2026
Merged

fix(ui): preserve multipart Content-Type in apiFetch (RAN-34)#78
aksOps merged 1 commit intomainfrom
fix/ran-34-multipart-uploads

Conversation

@aksOps
Copy link
Copy Markdown
Contributor

@aksOps aksOps commented Apr 24, 2026

Summary

apiFetch was unconditionally defaulting Content-Type: application/json for any request that carried a body. That broke FormData uploads (and any other browser-managed body type) because the runtime could no longer attach the multipart boundary, so the Documents UploadModal posted an unparseable body to /api/upload.

  • Skip the JSON default for FormData, Blob, URLSearchParams, ReadableStream, ArrayBuffer, and typed-array bodies — the runtime owns the Content-Type for those (boundary, encoding, etc.).
  • Keep defaulting application/json for string bodies and always respect a caller-provided Content-Type.
  • Add regression tests in ui/src/lib/__tests__/api-client.test.ts that would fail if a multipart upload silently got a Content-Type: application/json injected, plus coverage for string-body defaulting and explicit-header passthrough.

Tracks RAN-34 (parent: RAN-7 reviewer finding).

Test plan

  • cd ui && npm test — 28 files / 92 tests pass, including 4 new apiFetch regression tests
  • cd ui && npm run typecheck — clean
  • cd ui && npm run build — clean
  • Manual smoke against /api/upload from the Documents modal once merged
  • Note: npm run lint is broken on main (eslint v10 needs eslint.config.js, repo has neither flat config nor .eslintrc.*). Out of scope for this PR.

apiFetch was unconditionally defaulting Content-Type to application/json
for any request with a body. That broke FormData uploads (and any other
browser-managed body) because the Fetch implementation no longer added
the multipart boundary, so the Documents UploadModal posted an
unparseable body to /api/upload.

- Skip the JSON default for FormData, Blob, URLSearchParams,
  ReadableStream, ArrayBuffer, and typed-array bodies; the runtime
  attaches the right Content-Type (with boundary, etc.) for those.
- Continue defaulting application/json for string bodies, and respect a
  caller-provided Content-Type without overriding it.
- Add regression tests in ui/src/lib/__tests__/api-client.test.ts that
  fail when FormData / Blob / URLSearchParams / ArrayBuffer / typed
  arrays receive a defaulted JSON Content-Type, plus coverage for
  string-body defaulting and explicit-header passthrough.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@aksOps aksOps enabled auto-merge (squash) April 24, 2026 17:59
@aksOps aksOps merged commit 45c44e4 into main Apr 24, 2026
12 checks passed
@aksOps aksOps deleted the fix/ran-34-multipart-uploads branch April 24, 2026 18:03
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