rstrouse / nodejs-poolController-dashPanel

A dashboard panel for tagyoureit/nodejs-poolController
33 stars 20 forks source link

Reverse proxy support #44

Closed putnam closed 2 years ago

putnam commented 2 years ago

I just upgraded my whole setup to use v7.5 and dashPanel. Like many people I keep all my services gated through an nginx reverse proxy with a subdirectory for each thing. For example, I previously had my pool settings at myhouse.net/pool/.

As long as services are written with the possibility of a reverse proxy in mind, this works fine, or in some cases you need to specify what folder to prepend to various URLs for things to work.

The static assets themselves look OK and are using relative URLs so that's fine. There may be other problematic areas though. Just on a quick glance the file dashboard.js repeatedly refers to "/config/serviceUri" instead of "config/serviceUri" -- is there a need for the static path here or can you drop the slash? Alternatively, a simple config option to prepend a string to all URIs would avoid any issues with relative paths.

rstrouse commented 2 years ago

I removed the leading slashes from the service urls at the call level. I am not that familiar with nginix and what patterns it needs but perhaps removal of the leading slashes will alleviate your issues so go ahead and pull dashPanel and lets see if this handles your issues.

Also note that if you check the Use Proxy to njsPC Server it will reroute the service calls to njsPC through the dashPanel server.

putnam commented 2 years ago

Thanks, major progress! The static stuff is all loading correctly now and I can see that some of the data is being pulled correctly.

You're right that the proxy was useful -- since when reverse proxying with SSL you end up with mixed active content, it'll be blocked otherwise (unless you go through all the work of also reverse proxying the controller service).

Once I activated the proxy I found another spot that might need adjusting though

Line 255 in dashboard.js:

 o.socket = io(window.location.origin.toString(), { reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });

window.location.origin strips all subdirectories; when reverse proxied, your socket.io instance might be behind /some/path rather than at the origin.

You might be able to programmatically parse the URL the page is at (in case of reverse proxy), then take the parts after the hostname and include them as the resource parameter to your socket IO instance. I've seen people solve it both ways, but that would avoid a configuration setting. Maybe:

io(window.location.origin, {resource: window.location.pathname, ...})

It's been a while since I worked with socket io but that might work.

rstrouse commented 2 years ago

It seems resource isn't one of the socket client options but path is. The path for routing the socket should always be at the root of the origin url for routing with dashPanel.

I wonder if the following just simplifies the whole thing and makes a relative uri out of the root. o.socket = io('/', { reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });

Or maybe even o.socket = io('', { reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });

putnam commented 2 years ago

You're right, I was looking at ancient documentation from an old version.

https://socket.io/docs/v4/client-initialization/#custom-namespace https://socket.io/docs/v4/namespaces/

According to the current docs, if you leave the namespace blank, it'll default to "/" which would effectively be the root of the current hostname. So I don't think it'd work in that case. And I think the path parameter has to match on the server application so it probably isn't the right place (this was previously resource so I was wrong initially too)

So that leaves setting up the namespace with the "relative" root, something I'm not clear socket.io implicitly supports, but you might be able to do it by just providing the entire window.location, right? (i.e., https://myhostname.com/pool/ or http://192.168.1.100:5150/). This all is under the assumption that dashPanel is a single-page app, which it .. seems like it is right? (Sorry not up to speed on the whole code base)

putnam commented 2 years ago

Alright, I dug into the code just now. Easy fix that works:

In _initSockets, in the proxy case:

 o.socket = io(window.location.origin.toString(), { path: window.location.pathname + 'socket.io', reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });

The above works for me in reverse proxy config as well as the more basic domain:port config. Can you confirm as well?

rstrouse commented 2 years ago

Can you tell me if it serves the page for http://<ip>:<port>/messageManager.html for you. It does not for me.

rstrouse commented 2 years ago

Can I get you to try the following in your setup. o.socket = io(window.location.origin.toString(), { path: window.location.pathname.replace(/(.*\/).*/, '') + '/socket.io/', reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });

putnam commented 2 years ago

Yeah, I made the dumb assumption the whole app lived at / with no other pages, so that'd mess things up if using window.location.pathname

That regex is too greedy -- you probably want:

window.location.pathname.replace(/[^/]*$/, '') + 'socket.io'

This will keep everything up to the last filename in the path.

image

Also, you don't need the trailing slash after socket.io

putnam commented 2 years ago

Oh, and the reason messageManager is breaking for me is because you need a similar update in _initSockets in messageManager.js

And the page itself, messageManager.html is still using paths like "../../../" in the header like index.html was. Those need to be cleaned up the same way (looks like you just need to delete the leading bits since the files are located at the root anyway)

putnam commented 2 years ago

These are my local changes that seem to be working in both cases, FWIW.

I probably should have just sent a PR! Sorry.

diff --git a/pages/messageManager.html b/pages/messageManager.html
index eafdf6c..f048bc0 100644
--- a/pages/messageManager.html
+++ b/pages/messageManager.html
@@ -5,10 +5,10 @@
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Message Manager</title>
-    <script type="text/javascript" src="../socket.io-client/socket.io.js"></script>
-    <script type="text/javascript" src="../../jquery/dist/jquery.min.js"></script>
-    <script type="text/javascript" src="../../jquery-ui/jquery-ui.min.js"></script>
-    <script type="text/javascript" src="../../jquery-ui-touch-punch/jquery.ui.touch-punch.min.js"></script>
+    <script type="text/javascript" src="socket.io-client/socket.io.js"></script>
+    <script type="text/javascript" src="jquery/dist/jquery.min.js"></script>
+    <script type="text/javascript" src="jquery-ui/jquery-ui.min.js"></script>
+    <script type="text/javascript" src="jquery-ui-touch-punch/jquery.ui.touch-punch.min.js"></script>
     <script type="text/javascript" src="scripts/widgets.js"></script>
     <script type="text/javascript" src="scripts/controller.js"></script>
     <script type="text/javascript" src="scripts/uploader.js"></script>
@@ -16,9 +16,9 @@
     <script type="text/javascript" src="scripts/messages/messageList.js"></script>
     <script type="text/javascript" src="scripts/messages/message.js"></script>
     <script type="text/javascript" src="scripts/messages/doc/messageDoc.js"></script>
-    <link rel="stylesheet" type="text/css" href="../../jquery-ui/jquery-ui.css" />
-    <link rel="stylesheet" type="text/css" href="../../jquery-ui/jquery-ui.theme.css" />
-    <link rel="stylesheet" type="text/css" href="/font-awesome/css/all.css" />
+    <link rel="stylesheet" type="text/css" href="jquery-ui/jquery-ui.css" />
+    <link rel="stylesheet" type="text/css" href="jquery-ui/jquery-ui.theme.css" />
+    <link rel="stylesheet" type="text/css" href="font-awesome/css/all.css" />
     <link rel="stylesheet" type="text/css" href="themes/widgets.css" />
     <link rel="stylesheet" type="text/css" href="themes/vlist.css" />
     <link rel="stylesheet" type="text/css" href="themes/messageManager.css" />
@@ -64,4 +64,4 @@
         });
     </script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/scripts/dashboard.js b/scripts/dashboard.js
index 6a71365..dd94ef4 100644
--- a/scripts/dashboard.js
+++ b/scripts/dashboard.js
@@ -251,8 +251,8 @@
                 o.socket = io(o.apiServiceUrl, { reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });
             }
             else {
-                console.log({ msg: 'Connecting socket through proxy', url: window.location.origin.toString() });
-                o.socket = io(window.location.origin.toString(), { reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });
+                console.log({ msg: 'Connecting socket through proxy', url: window.location.toString() });
+                o.socket = io(window.location.origin.toString(), { path: window.location.pathname.replace(/[^/]*$/, '') + 'socket.io', reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });
             }
             o.socket.on('circuit', function (data) {
                 console.log({ evt: 'circuit', data: data });
diff --git a/scripts/messages/messageManager.js b/scripts/messages/messageManager.js
index f265ef2..009348a 100644
--- a/scripts/messages/messageManager.js
+++ b/scripts/messages/messageManager.js
@@ -56,7 +56,7 @@
             }
             else {
                 console.log({ msg: 'Connecting socket through proxy', url: window.location.origin.toString() });
-                o.socket = io(window.location.origin.toString(), { reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });
+                o.socket = io(window.location.origin.toString(), { path: window.location.pathname.replace(/[^/]*$/, '') + 'socket.io', reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, upgrade: true });
             }
             o.socket.on('controller', function (data) {
                 console.log({ evt: 'controller', data: data });
rstrouse commented 2 years ago

Yeah I probably should have tested the regex which would have been fine in a match.

No worries it is just as easy to make the changes locally. Git can be braindead or maybe it is just the keyboard operator.

rstrouse commented 2 years ago

Go ahead and pull dashPanel I integrated your changes.

putnam commented 2 years ago

Voila! Thank you!