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

noVNC /websockify endpoint fails when web server is served with a path prefix #1737

Open
mahendrapaipuri opened this issue Dec 30, 2022 · 5 comments · May be fixed by #1745
Open

noVNC /websockify endpoint fails when web server is served with a path prefix #1737

mahendrapaipuri opened this issue Dec 30, 2022 · 5 comments · May be fixed by #1745
Labels

Comments

@mahendrapaipuri
Copy link

Describe the bug
When noVNC is served with a path prefix, say http://localhost:5900/pathprefix/vnc.html, the requests to websockets fail as URL is built without considering the path prefix. In my case, I am trying to integrate noVNC within JupyterLab environment using jupyter server proxy. When running on localhost, the integrated noVNC server runs at root http://localhost:8888/novnc_0/. noVNC is able to fetch all js related files by taking the /novnc_0/ prefix into account. But the endpoint /websockify does not take the path prefix into account and hence fails. I am attaching screenshot of browser console.

Looking at screenshot, the request that failed should be made to http://localhost:8888/novnc_0/websockify instead of http://localhost:8888/websockify.

To Reproduce

A simple reproducer can be serving noVNC via a nginx reverse proxy at the path prefix.

Expected behavior
noVNC taking base URL into account while building URL for websockify endpoint.

Screenshots
websockify

Client (please complete the following information):

  • OS: Ubuntu 20
  • Browser: Firefox
  • Browser version: 108

Server (please complete the following information):

  • noVNC version: 3553a451d8b9cf566232b7de2e764861c57a0e9a
  • VNC server: TigerVNC
  • WebSocket proxy: websockify

Additional context

By taking base URL into account in vnc.html and vnc_lite.html should fix the problem.

url += window.location.pathname + path;
@CendioOssman
Copy link
Member

We explored this in #1058, but failed to find something robust.

I wonder if we missed something in the reasoning there, though, as the browser is able to use relative URLs just fine.

@mahendrapaipuri
Copy link
Author

@CendioOssman Cheers for coming back. Ok, I see the issues from #1058. I ended up patching it for our use case as follows:

--- a/app/ui.js
+++ b/app/ui.js
@@ -180,7 +180,7 @@ const UI = {
         UI.initSetting('shared', true);
         UI.initSetting('view_only', false);
         UI.initSetting('show_dot', false);
-        UI.initSetting('path', 'websockify');
+        UI.initSetting('path', window.location.pathname.replace(/[^/]*$/, '').substring(1) + 'websockify');
         UI.initSetting('repeaterID', '');
         UI.initSetting('reconnect', false);
         UI.initSetting('reconnect_delay', 5000);

If you think, it would be too much of a hassle, feel free to close the issue.

vsilvar added a commit to vsilvar/noVNC that referenced this issue Jan 14, 2023
Fixes novnc#1737 and it should work for all of the different scenarios where the relative assets also work.
This includes, for example:
   - /
   - /vnc.html
   - /vnc/
   - /vnc/vnc.html

It won't work for:
 - /vnc (but the assets don't work either, so it's consistent)
 - or /vnc.html/ (but this results in a 404 by default anyway)
@vsilvar vsilvar linked a pull request Jan 14, 2023 that will close this issue
@bitdruid
Copy link

if i get it right websockify fails to connect? you have to catch it at the root dir:

server {
. . .
                location /subdir/novnc/ {
                        proxy_pass http://internal-IPv4:6080/;
                        proxy_set_header X-Forwarded-Port 443;
                        proxy_set_header X-Forwarded-Proto https;
                        proxy_redirect off;
                }
                location /websockify {
                        proxy_pass http://internal-IPv4/websockify/;
                        proxy_set_header Host $host;
                        proxy_http_version 1.1;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection $http_connection;
                }
. . .
}

note that it has to be /websockify and not /websockify/ !

@dafoo
Copy link

dafoo commented Apr 20, 2023

if i get it right websockify fails to connect? you have to catch it at the root dir:

server {
. . .
                location /subdir/novnc/ {
                        proxy_pass http://internal-IPv4:6080/;
                        proxy_set_header X-Forwarded-Port 443;
                        proxy_set_header X-Forwarded-Proto https;
                        proxy_redirect off;
                }
                location /websockify {
                        proxy_pass http://internal-IPv4/websockify/;
                        proxy_set_header Host $host;
                        proxy_http_version 1.1;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection $http_connection;
                }
. . .
}

note that it has to be /websockify and not /websockify/ !

This won't work if you have the same server host but different users, i.e.

...
location /user1/novnc {
  proxy_pass http://internal-IPv4-1:6080/;
...
location /user2/novnc {
  proxy_pass http://internal-IPv4-2:6080/;
...

In this example, more than 1 user will request /websockify and at most one will get the right internal IP. Is there a way to get all users the right internal IP?

@bitdruid
Copy link

if i get it right websockify fails to connect? you have to catch it at the root dir:

server {
. . .
                location /subdir/novnc/ {
                        proxy_pass http://internal-IPv4:6080/;
                        proxy_set_header X-Forwarded-Port 443;
                        proxy_set_header X-Forwarded-Proto https;
                        proxy_redirect off;
                }
                location /websockify {
                        proxy_pass http://internal-IPv4/websockify/;
                        proxy_set_header Host $host;
                        proxy_http_version 1.1;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection $http_connection;
                }
. . .
}

note that it has to be /websockify and not /websockify/ !

This won't work if you have the same server host but different users, i.e.

...
location /user1/novnc {
  proxy_pass http://internal-IPv4-1:6080/;
...
location /user2/novnc {
  proxy_pass http://internal-IPv4-2:6080/;
...

In this example, more than 1 user will request /websockify and at most one will get the right internal IP. Is there a way to get all users the right internal IP?

In this case i would consider using the token system. Websockify will connect the right port according to the requested token. I think if you are on the same host/same ipv4 this is the best solution. You do need just one proxypass directive in your site.conf

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

Successfully merging a pull request may close this issue.

4 participants