Skip to content

fix(build): return TUS OPTIONS locally#1579

Merged
riderx merged 4 commits intomainfrom
riderx/fix-options-upload-500
Feb 5, 2026
Merged

fix(build): return TUS OPTIONS locally#1579
riderx merged 4 commits intomainfrom
riderx/fix-options-upload-500

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Feb 5, 2026

Summary (AI generated)

  • handle TUS OPTIONS responses locally for build uploads
  • align TUS headers with shared constants to avoid proxying OPTIONS

Test plan (AI generated)

  • bun run lint:backend

Screenshots (AI generated)

  • N/A

Checklist (AI generated)

  • My code follows the code style of this project and passes
    bun run lint:backend && bun run lint.
  • My change requires a change to the documentation.
  • I have updated the documentation
    accordingly.
  • My change has adequate E2E test coverage.
  • I have tested my code manually, and I have provided steps how to reproduce
    my tests

Summary by CodeRabbit

  • Chores

    • Downgraded edge runtime Deno version.
    • Added a module import mapping for backend dependencies.
  • New Features

    • Improved upload endpoints: standardized protocol headers, consistent CORS/TUS OPTIONS responses, and simplified OPTIONS handling for uploads.

Copilot AI review requested due to automatic review settings February 5, 2026 00:10
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 5, 2026

Warning

Rate limit exceeded

@riderx has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 18 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Updates Supabase config Deno edge_runtime version (2 → 1) and changes TUS upload endpoint OPTIONS handling to return static, no-auth TUS CORS/capability responses; POST/HEAD/PATCH proxy behavior is unchanged. Adds an import-map entry for drizzle-orm/ in functions/deno.json.

Changes

Cohort / File(s) Summary
Configuration
supabase/config.toml
Changed [edge_runtime].deno_version from 21 (two occurrences); removed an extra trailing newline.
TUS Upload Handler
supabase/functions/_backend/public/build/index.ts
Added TUS-related constants and tusOptionsResponse helper; replaced proxied, auth-required OPTIONS handling with static, no-auth OPTIONS responses including Tus-Resumable, Tus-Version, Tus-Max-Size, Tus-Extension, and CORS headers. POST/HEAD/PATCH proxy endpoints retained.
Deno import map
supabase/functions/deno.json
Added import map entry "drizzle-orm/": "npm:/drizzle-orm@0.44.7/" to enable subpath imports for drizzle-orm.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client
participant EdgeFn as Edge Function
participant Builder
Client->>EdgeFn: OPTIONS /upload/:jobId
Note right of EdgeFn: new behavior
EdgeFn-->>Client: 200 + CORS & TUS headers (no auth)

mermaid
sequenceDiagram
participant Client
participant EdgeFn as Edge Function
participant Builder
Client->>EdgeFn: POST/HEAD/PATCH /upload/:jobId/*
EdgeFn->>Builder: Proxy request (with auth)
Builder-->>EdgeFn: Response
EdgeFn-->>Client: Proxy response

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐇 I hopped in quick with headers fine,

Tus-Options served, no auth in line,
Deno nudged back one small degree,
Drizzle paths now found with glee,
A rabbit cheers for tidy spree! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: handling TUS OPTIONS responses locally instead of proxying them, which aligns with the primary modification in the build/index.ts file.
Description check ✅ Passed The description covers the summary and test plan sections adequately, though the checklist items are unfilled and manual test reproduction steps are not detailed as required.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch riderx/fix-options-upload-500

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes the TUS OPTIONS request handling for build uploads by returning responses locally instead of proxying them to the builder service. This optimization aligns the implementation with the existing TUS file upload patterns and uses shared constants from files/util.ts.

Changes:

  • Added local TUS OPTIONS handlers for /build/upload/:jobId and /build/upload/:jobId/* endpoints
  • Imported TUS-related constants from files/util.ts for consistency
  • Removed the previous proxy-based OPTIONS implementation that forwarded requests to the builder

})

// TUS proxy endpoints - ALL methods proxied to builder with API key injection
const TUS_EXTENSIONS = 'creation,creation-defer-length,creation-with-upload,expiration'
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The TUS_EXTENSIONS constant is defined locally here but is identical to the one in files/files.ts:219. Consider extracting this to files/util.ts as a shared constant (e.g., export const TUS_EXTENSIONS = 'creation,creation-defer-length,creation-with-upload,expiration') to avoid duplication and ensure consistency across TUS implementations.

Copilot uses AI. Check for mistakes.
Comment on lines +106 to 114
// OPTIONS /build/upload/:jobId - TUS capabilities (no auth needed)
app.options('/upload/:jobId', (c) => {
return c.json(BRES, 200, tusOptionsResponse())
})

// OPTIONS /build/upload/:jobId/* - TUS capabilities (no auth needed)
app.options('/upload/:jobId/*', (c) => {
return c.json(BRES, 200, tusOptionsResponse())
})
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

Consider adding test coverage for the TUS OPTIONS endpoints. While the existing test file tests/tus-upload.test.ts covers TUS OPTIONS for the files module (line 123-132), there are no tests verifying that the build endpoints correctly return TUS OPTIONS responses. This is particularly important since the implementation differs from the files module (returns headers locally instead of proxying).

Suggested test case:

  • Verify OPTIONS /build/upload/:jobId returns correct TUS headers
  • Verify OPTIONS /build/upload/:jobId/* returns correct TUS headers
  • Verify 204 status code (after fixing the bug)
  • Verify no authentication is required for OPTIONS requests

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +113
return c.json(BRES, 200, tusOptionsResponse())
})

// OPTIONS /build/upload/:jobId/* - TUS capabilities (no auth needed)
app.options('/upload/:jobId/*', (c) => {
return c.json(BRES, 200, tusOptionsResponse())
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The usage of c.json() is incorrect here. Hono's c.json() method accepts two parameters: (object, statusCode), not three. For TUS OPTIONS responses, you should use c.newResponse() to set headers without a JSON body.

Looking at the existing TUS implementation in files/files.ts:211-220, the correct pattern is:

return c.newResponse(null, 204, {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': ALLOWED_METHODS,
  ...
})

Additionally, TUS OPTIONS responses should return HTTP 204 (No Content), not 200 with a JSON body. This aligns with the TUS protocol specification where OPTIONS is a preflight request that should return headers without content.

Suggested change
return c.json(BRES, 200, tusOptionsResponse())
})
// OPTIONS /build/upload/:jobId/* - TUS capabilities (no auth needed)
app.options('/upload/:jobId/*', (c) => {
return c.json(BRES, 200, tusOptionsResponse())
return c.newResponse(null, 204, tusOptionsResponse())
})
// OPTIONS /build/upload/:jobId/* - TUS capabilities (no auth needed)
app.options('/upload/:jobId/*', (c) => {
return c.newResponse(null, 204, tusOptionsResponse())

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +113
return c.json(BRES, 200, tusOptionsResponse())
})

// OPTIONS /build/upload/:jobId/* - TUS capabilities (no auth needed)
app.options('/upload/:jobId/*', (c) => {
return c.json(BRES, 200, tusOptionsResponse())
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

Same issue here - c.json(BRES, 200, tusOptionsResponse()) is incorrect. Should use c.newResponse(null, 204, tusOptionsResponse()) instead to properly return TUS OPTIONS headers with a 204 No Content response.

Suggested change
return c.json(BRES, 200, tusOptionsResponse())
})
// OPTIONS /build/upload/:jobId/* - TUS capabilities (no auth needed)
app.options('/upload/:jobId/*', (c) => {
return c.json(BRES, 200, tusOptionsResponse())
return c.newResponse(null, 204, tusOptionsResponse())
})
// OPTIONS /build/upload/:jobId/* - TUS capabilities (no auth needed)
app.options('/upload/:jobId/*', (c) => {
return c.newResponse(null, 204, tusOptionsResponse())

Copilot uses AI. Check for mistakes.
@riderx
Copy link
Copy Markdown
Member Author

riderx commented Feb 5, 2026

/tip @Judel777 $30 thanks for this

@algora-pbc
Copy link
Copy Markdown

algora-pbc bot commented Feb 5, 2026

🎉🎈 @Judel777 has been awarded $30 by Capgo! 🎈🎊

@riderx riderx force-pushed the riderx/fix-options-upload-500 branch from 9084a74 to 6e06129 Compare February 5, 2026 03:06
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Feb 5, 2026

@riderx riderx merged commit c5342ea into main Feb 5, 2026
11 checks passed
@riderx riderx deleted the riderx/fix-options-upload-500 branch February 5, 2026 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants