Dirnei / node-red-contrib-zigbee2mqtt-devices

Node-red nodes for controlling and managing zigbee devices managed by zigbee2mqtt
MIT License
30 stars 7 forks source link

Fixed failed to load device #117

Closed Andreas-Huber closed 2 years ago

Andreas-Huber commented 2 years ago

Fixed failed to the load device list when Node-RED UI hosted on non-default URL.

Running the Node-RED admin interface on another URL seems relatively common. The root URL can easily be changed within the Node-RED settings.js file.

/** By default, the Node-RED UI is available at http://localhost:1880/
* The following property can be used to specify a different root path.
 * If set to false, this is disabled.
*/
httpAdminRoot: '/admin',

But our requests from the front end failed, as we did not consider this possibility. This pull request fixes this problem by making the URLs relative and most importantly testing the current and desired behavior.

I tested various URLs with a Standalone NodeRED installation: http://localhost:1880/ http://localhost:1880/admin http://localhost:1880/test/editor

I also tested it within Home Assistant as suggested in Issue #105: http://homeassistant.local:8123/a0d7b954_nodered/dashboard

All those URLs work now.

Why did we make this mistake in the first place?

Node-RED uses express to host the admin interface. When listening to a get request we use what seems to be an absolute URL. Using a relative URL z2m/devices/... does not work with express - the request will return result in a 404 response. So probably we assumed it only works with absolute URLs. I looked a bit into express. As it turns out even though the URL starts with a / prefix, it is always relative to the application or route. For us that means, when the admin interface and therefore the admin express application is set to listen to /admin, calls to the requests as specified below will be received under /admin/z2m/devices/....

// file: _api.js
module.exports = function (RED) {
    const utils = require("./lib/utils.js");

    // This URL is relative to the httpAdmin express application
    RED.httpAdmin.get("/z2m/devices/:broker/:deviceType/:vendor/:model", function (req, res) {
        try {
            var response = {
                success: false,
                message: "",
                devices: []
            };
            ...

The only necessary change was, to make the web requests relative to the admin interface and not absolute. Since the admin interface is a single-page application that only uses anchors for the flows, making requests to z2m/devices fixes the problem.

I also had a look at how this kind of configuration requests are done in the node-red/node-red-nodes and they implemented it as I did now.

Issues