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

Websockets fail with HTTPS and http/2 if there is a reverse proxy on the line. #1653

Closed
LaKing opened this issue Jan 22, 2021 · 12 comments
Closed

Comments

@LaKing
Copy link

LaKing commented Jan 22, 2021

ViteJS fails to upgrade to websockets when using HTTPS and http/2 and there is a reverse proxy between the server and the browser.

Reproduction

Create a new container and install a blank new ViteJS project.

npm init @vitejs/app test --template vue
cd test
npm install
npx vite --https --host my-test.mydomain.com --port 8443

Install a reverse proxy, and tell it to use your container, and a test domain. For example haproxy on rpm based systems:

dnf -y install haproxy

Set /etc/haproxy.cfg to this minimal config:

frontend port8443
    bind *:8443 ssl crt /etc/haproxy/certificate.pem alpn h2,http/1.1
    default_backend default

backend default
    server my-test 10.0.0.4:8443 ssl verify none alpn h2,http/1.1

.. where 10.0.0.4 is the IP of your container with the vitejs instance.

certificate.pem should be a certificate valid for a domain. Use this domain in /etc/hosts to map to the ip of the haproxy server.

Once it's all set up, open the domain in the browser. Vite will load, ... but then, it will go into an endelss loop trying to reconnect.
The broswer's inspector will have a message, its a bit hard to catch:

Logs

In chrome, observe:

[vite] connecting...
client:200 WebSocket connection to 'wss://my-test.mydomain.com:8443/' 
failed: Error during WebSocket handshake: Unexpected response code: 404
(anonymous) @ client:200

In firefox:

[vite] connecting...
Firefox can’t establish a connection to the server at wss://my-test.mydomain.com:8443/.

Workaround

Use only http/1.1 - in haproxy, remove alpn h2,http/1.1 on both sides.
However, this might be not an option for people using hosting services.

System Info

  • vite version: vite/2.0.0-beta.36
  • Operating System: Fedora 32 / 33
  • Node version: tested with v12.19.0, v12.20.1 and v14.14.0
  • Package manager (npm/yarn/pnpm) and version: npm 6.14.8, 6.14.10
@yyx990803
Copy link
Member

Honestly I have no idea how to fix this, so PR welcome.

@bompus
Copy link
Contributor

bompus commented Jan 27, 2021

I did some digging, and from what I am reading, I believe to use websockets with http2 in node, you'd have to use http2 instead of http with the allowHTTP1:true option. The http2 module probably adds some overhead, and I didn't test this at all. I'm just adding some information for someone to look at in the future :)

Refs:
https://github.com/websockets/ws/issues/1458
https://github.com/shellscape/webpack-plugin-serve/pull/184
https://github.com/shellscape/webpack-plugin-serve/pull/186

@LaKing
Copy link
Author

LaKing commented Jan 27, 2021

@bompus
The code includes this option. Look at line 26 ...

@TrungRueta
Copy link

i dont know much about protocol but i got issue with same place hmr websocket when try play middlewareMode + http2. i posted other issue maybe your issue and mine is same root.
#1807

@airhorns
Copy link
Contributor

@bompus I think your issue would be solved by #1992, but that's different than this issue. @LaKing does haproxy need any other config to properly proxy websocket connections? The 404 status code is really suspect.

@LaKing
Copy link
Author

LaKing commented Feb 14, 2021

@airhorns, no special settings needed for websockets. The haproxy minimal conf works with websockets, I tested it with node and a browser test

@xorik
Copy link

xorik commented Apr 8, 2021

It works perfectly in vue cli. It said:

It seems you are running Vue CLI inside a container. and after that websocket for HMR works perfectly, even if port on the proxy is different. E.g. I have https://some.server/ that proxies to http://localhost:8080.

But for the vite dev server, it totally ignores the port from URL, and uses port from the --port argument (3000 by default).
So I'm forced to do something like https://some.server:3000 (same port as on vite dev), to make it work.

Would be nice to have similar behavior with vue cli.

UPD this config helped with the issue:

  server: {
    hmr: {
      host: 'some.server,
      port: 443,
      protocol: 'wss'
    }
  }

@benatkin
Copy link

Adding @xorik's code to vite.config.js worked. If there's some way to automatically detect it, that would be nice.

@moisesbites
Copy link

moisesbites commented Sep 27, 2021

UPD this config helped with the issue:

  server: {
    hmr: {
      host: 'some.server,
      port: 443,
      protocol: 'wss'
    }
  }

This solved my reload problem behind haproxy in a docker node container. I'm using svelte.kit

// "@sveltejs/adapter-node": "^1.0.0-next.51",
// "@sveltejs/kit": "^1.0.0-next.174",
// "svelte": "^3.43.0",

@artalar
Copy link

artalar commented Mar 25, 2022

Same problem for gitpod. Thanks a lot to @xorik, server.hmr.host solves the problem.!

upd. Here is universal solution for gitpod:

// vite.config.js

let hmr = true;

if (process.env.GITPOD_WORKSPACE_CONTEXT) {
  hmr = {
    host: `3000-${process.env.GITPOD_WORKSPACE_ID}.${process.env.GITPOD_WORKSPACE_CLUSTER_HOST}`,
    port: 443,
    protocol: "wss",
  };
}

@gogoLJY
Copy link

gogoLJY commented May 10, 2022

I ran into the same problem that using the Whistle tool to reverse proxy an online address locally caused an infinite loop and HMR failure.

If you fill in port:443, Vite will refresh indefinitely, but removing the port:443 will send the requests (https://xxx.net/...whistle-path.5b6af7b9884e1165...///whistle.bifrost/cgi-bin/list?_=1650621054028) every few seconds, then the page will refresh(the timestamp of the request parameter _ will change),and the HMR will be disabled when you save.

here is my config:

server: {
  hmr: {
    port: 443,
    protocol: "wss",
  },
  port: 3001,
  proxy: {
    '/api/conf': {
        target: 'https://xxx.net/api/conf',
        changeOrigin: true,
    },
  },
}

@sapphi-red
Copy link
Member

Closing as #8650 fixed this. Please try 3.0.0-beta.1.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests