From 1e64377eff27a7943b59a36976bfe64b719372c6 Mon Sep 17 00:00:00 2001 From: Jonas Jesus Date: Wed, 20 May 2026 11:41:57 -0300 Subject: [PATCH] fix(vtex/proxy): manual redirect for share + vtexid auth endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VTEX cart-share endpoint (/api/io/_v/share/) responds 302 with a Set-Cookie restoring the orderForm, then redirects to /checkout?step=payment. The default redirect:"follow" in createVtexCheckoutProxy lets the fetch consume the 302 internally, so the intermediate Set-Cookie is dropped and the browser lands on an empty checkout. Same pattern affects the vtexid auth-redirect endpoints (/api/vtexid/pub/authentication/{redirect,finish}, /api/vtexid/oauth/redirect), which carry post-login cookies and a Location that often points back to the worker host — fetch follows it, Cloudflare sees a same-host subrequest loop and returns 404. Switch redirect mode to "manual" for these paths so the 302 + Set-Cookie flow through to the browser, which then follows the Location with the cookie applied. Existing Set-Cookie domain rewriting and Location rewriting (lines 390/404) already handle the response correctly. Repro: with the A/B worker active on a VTEX store, opening a cart-share URL like /api/io/_v/share/?step=payment opened /checkout with no orderForm. Reproduced on bagaggio; framework fix unblocks every store using createVtexCheckoutProxy without per-site worker-entry workarounds. Co-Authored-By: Claude Opus 4.7 --- vtex/utils/proxy.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/vtex/utils/proxy.ts b/vtex/utils/proxy.ts index bff7e04..c9f99ce 100644 --- a/vtex/utils/proxy.ts +++ b/vtex/utils/proxy.ts @@ -373,11 +373,25 @@ export function createVtexCheckoutProxy( const isCheckoutUI = url.pathname.startsWith("/checkout") || url.pathname.startsWith("/account"); const isLogout = url.pathname.startsWith("/api/vtexid/pub/logout"); + // Endpoints that respond 302 with Set-Cookie meant for the browser + // (cart-share restore, post-login redirects). With redirect:"follow" + // the fetch consumes the 302 and the intermediate Set-Cookie never + // reaches the user — e.g. /api/io/_v/share/ would land on + // /checkout?step=payment with an empty orderForm. Use manual redirect + // so the 302 + cookies are forwarded to the browser, which then + // follows the Location with the cookie applied. + const isRedirectingEndpoint = + url.pathname.startsWith("/api/io/_v/share/") || + url.pathname === "/api/vtexid/pub/authentication/redirect" || + url.pathname === "/api/vtexid/pub/authentication/finish" || + url.pathname.startsWith("/api/vtexid/oauth/redirect"); const init: RequestInit = { method: request.method, headers: fwd, - redirect: isCheckoutUI || isLogout ? "manual" : "follow", + redirect: isCheckoutUI || isLogout || isRedirectingEndpoint + ? "manual" + : "follow", }; if (request.method !== "GET" && request.method !== "HEAD") { init.body = request.body;