[start/devinxi] running https locally triggers TypeError: Headers.set: ":method" is an invalid header name.
Which project does this relate to?
Start
Describe the bug
Receive "TypeError: Headers.set: ":method" is an invalid header name." when running npm run dev with local https configured. It works fine in the main branch with vinxi.
Your Example Website or App
https://github.com/michaelreaton/tanstackstarthttpsbug
Steps to Reproduce the Bug or Issue
- Download my example repo (it uses barebones with https settings + certs added)
- npm install
- npm run dev
Expected behavior
As a user I expect to be able to run https locally and to be able to npm run dev with it.
Screenshots or Videos
Platform
Only tested on windows
Additional context
No response
I wonder if this could be related to #4141.
Using proxy: {} as mentioned in remix-run/remix#10445 seems to work, but I'm hopeful there will be a long term solution in the future.
Try this vite plugin:
import { IncomingMessage } from 'http';
import { Readable } from 'stream';
import { Plugin } from 'vite';
// Temporary, less than ideal hotfix until h3 support http2
function http2(): Plugin {
return {
name: 'http2',
configureServer(server) {
server.middlewares.use((req, _, next) => {
if (req.httpVersionMajor >= 2 && req.headers[':method']) {
const chunks: Buffer[] = [];
req.on('data', (chunk) => {
chunks.push(chunk);
});
req.on('end', () => {
const buffer = Buffer.concat(chunks);
const r = new Readable() as any;
const headers = Object.fromEntries(
Object.entries(req.headers).filter(
([key]) => !key.startsWith(':'),
),
);
headers.host = req.headers[':authority'] as string;
r.method = req.headers[':method'];
r.url = req.headers[':path'];
r.headers = headers;
r.push(buffer);
r.push(null);
Object.setPrototypeOf(req, IncomingMessage.prototype);
Object.assign(req, r);
next();
});
req.on('error', (err) => next(err));
} else {
next();
}
});
},
};
}
Try this vite plugin:
Thanks, it worked for me in dev.
I'm running into an issue with the http2 plugin workaround that @MoeedDar suggested & throwing notFound() functions on the server.
At time of writing, I'm on the latest release of TSS & am prepped for the upcoming version/alpha that removes the React Vite Plugin from the TSS plugin:
// vite.config.ts
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import basicSsl from "@vitejs/plugin-basic-ssl";
import viteReact from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
tanstackStart({
customViteReactPlugin: true,
}),
viteReact({
babel: {
plugins: [
[
"babel-plugin-react-compiler",
{
target: "19",
},
],
],
},
}),
http2(), // <---- Workaround Plugin as written above
basicSsl(), <---- SSL used for testing in dev
],
});
When trying to throw notFound() on the server, I get this weird issue where the initial response returns what looks to be the correct HTML & CSS, but something in the response causes the whole page to bomb.
import { createFileRoute, notFound } from "@tanstack/react-router";
export const Route = createFileRoute("/custom-not-found")({
loader: () => {
throw notFound();
},
component: RouteComponent,
notFoundComponent: () => <div>Custom not found</div>,
});
function RouteComponent() {
return <div>Hello "/custom-not-found"!</div>;
}
With JS disabled I get a white screen, with JS enabled I get a flash of the correct content, and then a white screen.
The good news is when deployed with actual SSL certs it works fine, it's just local dev that breaks everything everywhere. But the workaround breaks this behavior locally.
Hey folks, wanted to give an update on this after swapping to the Nitro V3 Alpha. The good news is now TSS isn't breaking local https, but the bad news is the Nitro V3 Plugin is:
import { devtools } from "@tanstack/devtools-vite";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import basicSsl from "@vitejs/plugin-basic-ssl";
import viteReact from "@vitejs/plugin-react";
import { nitro } from "nitro/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
devtools(),
basicSsl(),
nitro({
config: {
preset: "aws-lambda",
},
}),
tanstackStart(),
viteReact(),
],
server: {
host: "local.acme.com",
allowedHosts: ["local.acme.com],
},
});
Gives me an error of TypeError [ERR_HTTP2_INVALID_CONNECTION_HEADERS]: HTTP/1 Connection specific headers are forbidden: "keep-alive"
Adding in an empty proxy via this suggestion also fixed it: https://github.com/remix-run/remix/issues/10445#issuecomment-2649629039
server: {
proxy: {},
},
cc @pi0