drogonframework / drogon

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows
MIT License
11.44k stars 1.1k forks source link

WebSockets not forwarded #2006

Open Mis1eader-dev opened 5 months ago

Mis1eader-dev commented 5 months ago

Describe the bug Using drogon::app().forward(...) to forward WebSockets does not work. Tried by having it forward with "http://..." prefix as host, and it is able to establish a WebSocket connection, but can't maintain the connection or send/receive messages, it ends up disconnecting with this logged in the terminal on the forwarder's side:

20240418 14:04:08.810934 UTC 178355 ERROR More responses than expected! - HttpClientImpl.cc:616

As for the receiver, it only gets the new WebSocket connection established, and nothing else after that point.

Also tried forwarding with "ws://..." prefix as host, and it is unable to establish any WebSocket connections.

To Reproduce Steps to reproduce the behavior:

  1. Create a server with a WebSocket endpoint /ws, listening on port 9090.
  2. Create another server with a preRoutingAdvice that forwards to "http://127.0.0.1:9090", and itself listening on port 8080
  3. Make a WebSocket connection request to ws://127.0.0.1:8080/ws
  4. Observe its behavior

Expected behavior WebSockets should forward.

Desktop:

Additional context On a production server it is unable to connect at all.

Mis1eader-dev commented 5 months ago

In case others are looking to create a reverse proxy with WebSockets, use nginx in the meantime until this is resolved.

This is the nginx configuration you can use for inspiration:

server {
    listen 80;
    listen [::]:80;
    location / {
        proxy_pass http://127.0.0.1:9090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $http_connection;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_cache_bypass $http_upgrade;
    }
}

Change the proxy_pass to whatever your actual backend is listening on. And of course use https instead of http in production.

Baxulio commented 4 months ago

Hi dear colleges, this is really needed functionality, can anyone please add this feature? (i tried, but it's a little difficult for me)

Currently we have more than 100 devices and they are in our VPN. we need to connect them via websocket from one domain name. none of the proxy servers is applicable for our use case or requre certificate. Let'sencrypt also has limit of 50 certificates. wildcards also require 3rd party paid organizations, like cloudflare etc.

If this functionality existed in drogon, One could just orchestrate requests and proxy them dynamically to the endpoint needed.

Thank you!