Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: headers.getSetCookie is not a function #109

Open
olros opened this issue Apr 26, 2024 · 8 comments
Open

TypeError: headers.getSetCookie is not a function #109

olros opened this issue Apr 26, 2024 · 8 comments

Comments

@olros
Copy link

olros commented Apr 26, 2024

Hi! I'm testing the new Single Fetch behaviour in Remix, but I'm having trouble with headers.getSetCookie which seemingly isn't present when running on Vercel for some reason.

As noted in the changelog, I've enabled nativeFetch in installGlobals but the TypeError is still present. The error I get is this:

TypeError: headers.getSetCookie is not a function or its return value is not iterable
    at proxyResponseToResponseStub (/var/task/node_modules/.pnpm/@remix-run+server-runtime@2.9.1_typescript@5.4.5/node_modules/@remix-run/server-runtime/dist/single-fetch.js:292:25)
    at /var/task/node_modules/.pnpm/@remix-run+server-runtime@2.9.1_typescript@5.4.5/node_modules/@remix-run/server-runtime/dist/single-fetch.js:61:9
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 1)
    at async /var/task/node_modules/.pnpm/@remix-run+server-runtime@2.9.1_typescript@5.4.5/node_modules/@remix-run/server-runtime/dist/single-fetch.js:39:19
    at async callDataStrategyImpl (/var/task/node_modules/.pnpm/@remix-run+router@1.16.0/node_modules/@remix-run/router/dist/router.cjs.js:4169:17)
    at async callDataStrategy (/var/task/node_modules/.pnpm/@remix-run+router@1.16.0/node_modules/@remix-run/router/dist/router.cjs.js:3702:19)
    at async loadRouteData (/var/task/node_modules/.pnpm/@remix-run+router@1.16.0/node_modules/@remix-run/router/dist/router.cjs.js:3677:19)
    at async queryImpl (/var/task/node_modules/.pnpm/@remix-run+router@1.16.0/node_modules/@remix-run/router/dist/router.cjs.js:3522:20)
    at async Object.query (/var/task/node_modules/.pnpm/@remix-run+router@1.16.0/node_modules/@remix-run/router/dist/router.cjs.js:3416:18)

To reproduce, simply create a new Remix-project with npx create-remix@latest and put this in the _index.tsx-file:

export const loader = () => {
  return new Response(null, {
    headers: { "set-cookie": "_cookie_name=123; maxAge=1000000; SameSite=Lax" },
  });
};

export default function Index() {
  return <h1>Welcome to Remix</h1>;
}
`vite.config.ts`
import { vitePlugin as remix } from "@remix-run/dev";
import { installGlobals } from "@remix-run/node";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import { vercelPreset } from '@vercel/remix/vite';

installGlobals({ nativeFetch: true });

export default defineConfig({
  plugins: [
    remix({
      presets: [vercelPreset()],
      future: {
        unstable_singleFetch: true
      }
    }),
    tsconfigPaths(),
  ],
});

Then deploy to vercel.


Even without the new SingleFetch behaviour, using headers.getSetCookie still doesn't work. This can be reproduced by removing unstable_singleFetch from future in vite.config.ts, and changing the _index.tsx-file to this:

export const loader = () => {
  const res = new Response(null, {
    headers: { "set-cookie": "_cookie_name=123; maxAge=1000000; SameSite=Lax" },
  });
  console.log("getSetCookie", res.headers.getSetCookie); // -> getSetCookie  undefined
  console.log("getSetCookie values", res.headers.getSetCookie()); // -> TypeError: response.headers.getSetCookie is not a function
  return res;
};

export default function Index() {
  return <h1>Welcome to Remix</h1>;
}

Any help appreciated!

@coji
Copy link

coji commented Apr 27, 2024

I am having the same problem. It also occurs with loaders that only return json({}).

It is also reported in the issue of remix-run
remix-run#9324

Perhaps I should try to use nativeFetch on runtime, but since it is vercelPreset and not a custom server, I don't know what to do.

@Tsirimaholy
Copy link

I'm getting this error too. I tried to use node 20 if it solves the issue, but it's the same.
The server is not accessible (Just blank screen).
Mine is just a local dev environment.
I tried to dig deeper a little bit and there I see this line: https://github.com/remix-run/remix/blob/7b2fa032cd465c7f6e9c8d90471d6a544e0c08f6/packages/remix-server-runtime/single-fetch.ts#L350
Even the comments themselves acknowledge the presence of certain typing issues.
I want to contribute to solve this issue, but i'm not a yet great JS dev myself 😅 .

@coji
Copy link

coji commented Apr 28, 2024

It would be nice to be able to control it externally somehow so that the following part called after invoking serverless functions becomes installGlobals({ nativeFetch: true }), but I wonder how to do that.

installGlobals();

@michalmo
Copy link

michalmo commented May 16, 2024

So I've found a workaround using Object.defineProperty to set the globals and prevent changes to them, and by monkey-patching in an API that @ercel/remix relies on but isn't available in Headers when using nativeFetch.

Here's the gist https://gist.github.com/michalmo/d62e9a2e001183ec1df1bcac74980abb.

I call the installAndLockGlobals helper at the top level of app/entry.server.tsx (https://vercel.com/docs/frameworks/remix#using-a-custom-app/entry.server-file).

Hope this helps somebody :)

@cyberdude
Copy link

So I've found a workaround using Object.defineProperty to set the globals and prevent changes to them, and by monkey-patching in an API that @ercel/remix relies on but isn't available in Headers when using nativeFetch.

Here's the gist https://gist.github.com/michalmo/d62e9a2e001183ec1df1bcac74980abb.

I call the installAndLockGlobals helper at the top level of app/entry.server.tsx (https://vercel.com/docs/frameworks/remix#using-a-custom-app/entry.server-file).

Hope this helps somebody :)

Thank you sooo much!! You saved me a couple of headaches

@cyberdude
Copy link

@brophdawg11 Do you have an update regarding these or how can we help? Seems that this is an issue on the Vercel Side of things since locally is running ok

@brophdawg11
Copy link

brophdawg11 commented Jun 28, 2024

If Vercel needs a polyfill and doesn't have a fetch implementation, they will need to let you call installGlobals({ nativeFetch: true }) to get a single-fetch compatible polyfill (see #109 (comment)). remix-serve does this conditionally based on the flag https://github.com/remix-run/remix/blob/main/packages/remix-serve/cli.ts#L103

@Ehesp
Copy link

Ehesp commented Aug 5, 2024

Although the installGlobals({ nativeFetch: true }) fix solves this, I'm unable to use fetcher.submit from Remix, getting the error:

TypeError: RequestInit: duplex option is required when sending a body.
    at new Request (/var/task/website/node_modules/undici/lib/web/fetch/request.js:537:15)
    at createRemixRequest (file:///var/task/website/build/server/nodejs-eyJydW50aW1lIjoibm9kZWpzIn0/server-index.mjs:61:10)
    at Server.default (file:///var/task/website/build/server/nodejs-eyJydW50aW1lIjoibm9kZWpzIn0/server-index.mjs:80:19)

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

No branches or pull requests

7 participants