Skip to content

chore(api): drop redundant matcher entry from CORS proxy#4492

Closed
saddlepaddle wants to merge 1 commit into
mainfrom
saddlepaddle/api-proxy-skip-server-to-server
Closed

chore(api): drop redundant matcher entry from CORS proxy#4492
saddlepaddle wants to merge 1 commit into
mainfrom
saddlepaddle/api-proxy-skip-server-to-server

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented May 13, 2026

Summary

apps/api/src/proxy.ts had two matcher entries:

```ts
matcher: [
"/((?!_next|ingest|monitoring|).)",
"/(api|trpc)(.
)", // ← fully covered by the line above
],
```

The second is redundant — the first wildcard already matches everything not in its exclusion list, including /api/* and /trpc/*. Next dedupes overlapping matchers so behaviour is identical, it's just dead config.

Dropping it leaves a single readable pattern.

Scope

Test plan

  • CI green
  • Browser sign-in / tRPC still works from app.superset.sh, admin.superset.sh, desktop renderer (CORS unchanged)
  • GitHub + Linear webhooks still deliver (still match the matcher exactly as before)

Summary by CodeRabbit

  • Bug Fixes

    • Fixed middleware routing so proxy/CORS middleware applies to the correct set of requests while explicitly skipping internal Next.js paths, ingest/monitoring routes, and common static assets.
  • Performance

    • Reduced unnecessary middleware execution on excluded paths to improve overall request handling.

Review Change Stack

@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 13, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 13, 2026

Greptile Summary

This PR narrows the Next.js middleware matcher in apps/api/src/proxy.ts to skip the CORS shim on four server-to-server endpoint groups (/api/auth/jwks, /api/auth/token, /api/github/webhook, /api/integrations/*/webhook), reducing Vercel middleware log volume without changing observable CORS behavior for browser callers.

  • The two-entry matcher array (broad negative-lookahead + /(api|trpc)(.*)) is collapsed into one regex with the new server-to-server prefixes embedded in the lookahead.
  • Browser-facing surfaces (tRPC, /api/auth/get-session, durable-stream handshakes, sign-in/out) still match the new pattern and continue to receive CORS headers.

Confidence Score: 4/5

Safe to merge — the CORS logic itself is unchanged and the excluded endpoints are verified server-to-server callers that never send Origin headers.

The matcher change correctly excludes the four server-to-server endpoint groups. The two minor concerns are the lack of word-boundary guards on api/auth/token and api/github/webhook (which could silently exclude future browser-facing endpoints sharing those prefixes) and the implicit drop of old matcher 2's extension-coverage for API paths. Neither affects current behavior.

apps/api/src/proxy.ts — the new exclusion regex is worth a second look for prefix-matching breadth.

Important Files Changed

Filename Overview
apps/api/src/proxy.ts Matcher narrowed to exclude four server-to-server endpoint groups from CORS middleware; two excluded prefixes lack word-boundary guards, and removing the second old matcher changes static-extension coverage for API paths.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Incoming /api/* request] --> B{Matches new middleware matcher?}
    B -- "Starts with _next / ingest / monitoring OR static file extension" --> C[Middleware skipped - no CORS headers]
    B -- "Starts with api/auth/jwks, api/auth/token, api/github/webhook, api/integrations/*/webhook" --> D[Server-to-server: Middleware skipped - no CORS headers]
    B -- "All other paths e.g. tRPC, /api/auth/get-session, durable streams" --> E[CORS middleware runs]
    E --> F{OPTIONS preflight?}
    F -- Yes --> G[204 + CORS headers]
    F -- No --> H[NextResponse.next + CORS headers set]
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/api/src/proxy.ts:77
The excluded prefixes `api/auth/token` and `api/github/webhook` use plain prefix matching with no path separator after them, so the lookahead also silently excludes any future path that merely starts with these strings. For example, a hypothetical browser-facing `api/auth/token-refresh` or `api/github/webhooks` endpoint would be matched by the exclusion and would never receive CORS headers — failing silently for cross-origin browser calls. Adding a trailing `/` (or `$`-anchoring where the path is a leaf) tightens the scope to exactly the intended endpoints.

```suggestion
		"/((?!_next|ingest|monitoring|api/auth/jwks|api/auth/token$|api/auth/token/|api/github/webhook$|api/github/webhook/|api/integrations/[^/]+/webhook|[^?]*\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest))).*)",
```

### Issue 2 of 2
apps/api/src/proxy.ts:77
Dropping the second old matcher `/(api|trpc)(.*)` changes CORS coverage for any API/tRPC path whose URL contains a static-file extension (e.g. `/api/bundle.js` or `/trpc/subscriptions.ndjson`). The old union would have applied CORS headers via the second rule; the new single matcher's extension exclusion wins, so those paths would receive no CORS headers. In practice this is theoretical since Next.js API routes and tRPC routers don't expose extension-suffixed paths, but it is a subtle semantic difference worth being aware of if new endpoint patterns are added.

Reviews (1): Last reviewed commit: "fix(api/cost): skip CORS middleware on s..." | Re-trigger Greptile

Comment thread apps/api/src/proxy.ts Outdated
matcher: [
"/((?!_next|ingest|monitoring|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
"/(api|trpc)(.*)",
"/((?!_next|ingest|monitoring|api/auth/jwks|api/auth/token|api/github/webhook|api/integrations/[^/]+/webhook|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 The excluded prefixes api/auth/token and api/github/webhook use plain prefix matching with no path separator after them, so the lookahead also silently excludes any future path that merely starts with these strings. For example, a hypothetical browser-facing api/auth/token-refresh or api/github/webhooks endpoint would be matched by the exclusion and would never receive CORS headers — failing silently for cross-origin browser calls. Adding a trailing / (or $-anchoring where the path is a leaf) tightens the scope to exactly the intended endpoints.

Suggested change
"/((?!_next|ingest|monitoring|api/auth/jwks|api/auth/token|api/github/webhook|api/integrations/[^/]+/webhook|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
"/((?!_next|ingest|monitoring|api/auth/jwks|api/auth/token$|api/auth/token/|api/github/webhook$|api/github/webhook/|api/integrations/[^/]+/webhook|[^?]*\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest))).*)",
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/api/src/proxy.ts
Line: 77

Comment:
The excluded prefixes `api/auth/token` and `api/github/webhook` use plain prefix matching with no path separator after them, so the lookahead also silently excludes any future path that merely starts with these strings. For example, a hypothetical browser-facing `api/auth/token-refresh` or `api/github/webhooks` endpoint would be matched by the exclusion and would never receive CORS headers — failing silently for cross-origin browser calls. Adding a trailing `/` (or `$`-anchoring where the path is a leaf) tightens the scope to exactly the intended endpoints.

```suggestion
		"/((?!_next|ingest|monitoring|api/auth/jwks|api/auth/token$|api/auth/token/|api/github/webhook$|api/github/webhook/|api/integrations/[^/]+/webhook|[^?]*\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest))).*)",
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread apps/api/src/proxy.ts Outdated
matcher: [
"/((?!_next|ingest|monitoring|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
"/(api|trpc)(.*)",
"/((?!_next|ingest|monitoring|api/auth/jwks|api/auth/token|api/github/webhook|api/integrations/[^/]+/webhook|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Dropping the second old matcher /(api|trpc)(.*) changes CORS coverage for any API/tRPC path whose URL contains a static-file extension (e.g. /api/bundle.js or /trpc/subscriptions.ndjson). The old union would have applied CORS headers via the second rule; the new single matcher's extension exclusion wins, so those paths would receive no CORS headers. In practice this is theoretical since Next.js API routes and tRPC routers don't expose extension-suffixed paths, but it is a subtle semantic difference worth being aware of if new endpoint patterns are added.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/api/src/proxy.ts
Line: 77

Comment:
Dropping the second old matcher `/(api|trpc)(.*)` changes CORS coverage for any API/tRPC path whose URL contains a static-file extension (e.g. `/api/bundle.js` or `/trpc/subscriptions.ndjson`). The old union would have applied CORS headers via the second rule; the new single matcher's extension exclusion wins, so those paths would receive no CORS headers. In practice this is theoretical since Next.js API routes and tRPC routers don't expose extension-suffixed paths, but it is a subtle semantic difference worth being aware of if new endpoint patterns are added.

How can I resolve this? If you propose a fix, please make it concise.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a6b26db6-4013-4b1a-a32d-2f6f4d86a80f

📥 Commits

Reviewing files that changed from the base of the PR and between e4e6c40 and 2a2e15b.

📒 Files selected for processing (1)
  • apps/api/src/proxy.ts
💤 Files with no reviewable changes (1)
  • apps/api/src/proxy.ts

📝 Walkthrough

Walkthrough

The PR broadens the middleware config.matcher in apps/api/src/proxy.ts, replacing the previous /(api|trpc)(.*) matcher with a negative-lookahead pattern that excludes Next internals (/_next), /ingest, /monitoring, and common static asset extensions.

Changes

CORS / proxy matcher

Layer / File(s) Summary
Matcher replacement
apps/api/src/proxy.ts
export const config.matcher changed from `"/(api

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through routes both near and far,
I nudged the matcher, trimmed each star,
Skipped _next, ingest, monitoring too,
Static files pass by, the middleware few.
Hooray — lighter hops for requests anew!

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore(api): drop redundant matcher entry from CORS proxy' accurately describes the main change: removing a redundant matcher entry that was fully covered by an existing pattern.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the change rationale, scope, and test plan. However, it does not follow the provided template structure with sections like 'Type of Change', 'Testing', etc.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch saddlepaddle/api-proxy-skip-server-to-server

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 13, 2026

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

The proxy.ts middleware had two matcher entries:

  "/((?!_next|ingest|monitoring|<asset-exts>).*)"
  "/(api|trpc)(.*)"

The second is fully covered by the first — Next's matcher dedupes
overlapping patterns so behaviour is unchanged, it's just dead config.
Dropping it leaves a single, easier-to-read pattern.

No CORS or routing changes; chat-attachments stays local-only per Avi's
follow-up decision, so the matcher doesn't need finer-grained scoping.
@saddlepaddle saddlepaddle force-pushed the saddlepaddle/api-proxy-skip-server-to-server branch from e4e6c40 to 2a2e15b Compare May 13, 2026 06:12
@saddlepaddle saddlepaddle changed the title fix(api/cost): skip CORS middleware on server-to-server endpoints chore(api): drop redundant matcher entry from CORS proxy May 13, 2026
@saddlepaddle
Copy link
Copy Markdown
Collaborator Author

Misread the ask — going to land the endpoint removal in a fresh PR instead. Closing this.

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