Problem
The HTTP reverse proxy used by shopify app dev intercepts OPTIONS requests
and never forwards them to the target application. This breaks CORS preflight
for any cross-origin call made from UI extensions (e.g. Customer Account
extensions calling the app backend through the Cloudflare tunnel).
The root cause is in packages/app/src/cli/utilities/app/http-reverse-proxy.ts:
the proxy forwards every method but does not handle OPTIONS specially, and
http-proxy silently drops the preflight — the request never reaches the
user's app, so no CORS headers are returned.
Expected behavior
An OPTIONS preflight request to the tunnel URL should either:
- be forwarded to the target app so it can respond with its own CORS headers, or
- be answered at the proxy level with correct CORS headers.
Actual behavior
The OPTIONS request gets a response with no CORS headers (no
Access-Control-Allow-Origin, etc.). The browser then blocks the actual
request. The request never appears in the app's logs.
Reproduction
- Run
shopify app dev (any backend — Express, Remix, etc.)
- From an extension (or curl):
curl -i -X OPTIONS \
-H "Origin: https://extensions.shopifycdn.com" \
-H "Access-Control-Request-Method: GET" \
https://<tunnel>.trycloudflare.com/any-path
- Response has no CORS headers → browser blocks the follow-up request.
Opening the tunnel directly with cloudflared tunnel --url … works fine,
confirming the issue is in the CLI's reverse proxy, not Cloudflare.
Impact
Any extension that makes a cross-origin fetch to the app backend during local
dev is affected. Common case: Customer Account UI extensions calling app API
routes.
Related
Environment
- OS: macOS
- Shopify CLI: 3.x
- Node: 22.x
Problem
The HTTP reverse proxy used by
shopify app devintercepts OPTIONS requestsand never forwards them to the target application. This breaks CORS preflight
for any cross-origin call made from UI extensions (e.g. Customer Account
extensions calling the app backend through the Cloudflare tunnel).
The root cause is in
packages/app/src/cli/utilities/app/http-reverse-proxy.ts:the proxy forwards every method but does not handle OPTIONS specially, and
http-proxysilently drops the preflight — the request never reaches theuser's app, so no CORS headers are returned.
Expected behavior
An OPTIONS preflight request to the tunnel URL should either:
Actual behavior
The OPTIONS request gets a response with no CORS headers (no
Access-Control-Allow-Origin, etc.). The browser then blocks the actualrequest. The request never appears in the app's logs.
Reproduction
shopify app dev(any backend — Express, Remix, etc.)Opening the tunnel directly with
cloudflared tunnel --url …works fine,confirming the issue is in the CLI's reverse proxy, not Cloudflare.
Impact
Any extension that makes a cross-origin fetch to the app backend during local
dev is affected. Common case: Customer Account UI extensions calling app API
routes.
Related
the proxy)
Environment