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

HTTP2 Pseudo headers get rejected by Remix [\w Vite] #7867

Closed
1 task done
kazdegroot opened this issue Nov 1, 2023 · 5 comments
Closed
1 task done

HTTP2 Pseudo headers get rejected by Remix [\w Vite] #7867

kazdegroot opened this issue Nov 1, 2023 · 5 comments

Comments

@kazdegroot
Copy link

What version of Remix are you using?

2.2.0

Are all your remix dependencies & dev-dependencies using the same version?

  • Yes

Steps to Reproduce

  1. Use Vite plugin
  2. Enable https for Vite, by setting { server: { https: true } }
  3. Make sure there is something like a cert configured; e.g. using vite-plugin-mkcert
  4. Start dev server
  5. Visit site

Expected Behavior

Site works

Actual Behavior

Site throws the following error:

Unexpected Server Error

TypeError [ERR_INVALID_HTTP_TOKEN]: Header name must be a valid HTTP token [":authority"]

HTTPS in Vite will include HTTP2 by default, but also setting the server.proxy option (e.g. to {}), will fallback to just TLS. Everything works fine then.

@manzaloros
Copy link

manzaloros commented Nov 7, 2023

Hi, I'm having this same issue on running vite dev:

TypeError [ERR_INVALID_HTTP_TOKEN]: Header name must be a valid HTTP token [":authority"]
// vite.config.ts
import { unstable_vitePlugin as remix } from '@remix-run/dev';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import { SERVER_OPTION_KEY, SERVER_OPTION_CERT } from './setup-app-config.js';

export default defineConfig({
  plugins: [
    remix({
      ignoredRouteFiles: ['**/.*'],
      serverModuleFormat: 'esm',
      future: {},
    }),
    /*
      needed so Vite knows about tsconfig paths:
    */
    tsconfigPaths(),
  ],
  server: {
    port: 18267,
    https: {
      key: SERVER_OPTION_KEY,
      cert: SERVER_OPTION_CERT,
      rejectUnauthorized: false,
      requestCert: false,
    },
  },
});

It seems like the issue comes from node_modules/@remix-run/web-fetch/dist/lib.node.cjs, line 919.

The Vite config seems to be generating pseudo headers and theses shouldn't be passed to Node? The Remix team will need to address this in order for HTTPS 2 to work

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Nov 18, 2023

Thanks for raising the issue and providing contexts.
I investigated further based on a simple reproduction https://github.com/hi-ogawa/remix-reproduction-7867.

I think the issue goes like:

  • vite dev server includes http2 pseudo headers when delegating a request to remix middleware,
  • remix vite plugin injects polyfills for Request, Headers, etc... based on @remix-run/web-fetch package
  • remix re-instantiates Request object with original headers when executing loader
    return new Request(url.href, init);
  • however @remix-run/web-fetch doesn't allow pseudo header such as :authority

Two solution/workaround I came up with are: 1. remove node polyfill hi-ogawa/remix-reproduction-7867#1 or 2: filter out pseudo headers hi-ogawa/remix-reproduction-7867#2.
(+ also the one already mentioned user-side workaround server.proxy = {})

Interesting to note that, node's builtin Headers (since node 18, same as undici?) accept pseudo headers, but it throws in browser:

//// node repl
$ node
Welcome to Node.js v18.16.0.
Type ".help" for more information.
> new Headers({ ":method": "GET" })
HeadersList {
  cookies: null,
  [Symbol(headers map)]: Map(1) { ':method' => { name: ':method', value: 'GET' } },
  [Symbol(headers map sorted)]: null
}

//// browser devtools
> new Headers({ ":method": "GET" })
VM109:1 Uncaught TypeError: Failed to construct 'Headers': Invalid name
    at <anonymous>:1:1

There are other issues due to remix injecting Request polyfills #7819 (comment), so eventually removing polyfills might be a plan by remix team, but as a short term workaround, I'll put together a PR based on 2nd approach.

@ndthanhdev
Copy link

ndthanhdev commented Dec 6, 2023

A workaround for this issue is enabling server.proxy in vite.config, which will downgrade vite server to http/1.1.

server: {
	proxy: {
		// ...
	},
},

@pcattori
Copy link
Contributor

Fixed by #8062 and remix-run/web-std-io#55

@BrandonNoad
Copy link

A workaround for this issue is enabling server.proxy in vite.config, which will downgrade vite server to http/1.1.

server: {
	proxy: {
		// ...
	},
},

I ran into a similar issue when I switched to Remix Vite with the Cloudflare dev proxy and had to use the proxy: {} workaround above to solve it. I'm using v2.8.1 of all the Remix packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants