UIBUILDER and URL case sensitivity

I have some uibuilder instances where I use mixed-case in the URL publish point. E.g. "myTarget" When entering the correct URL, everything works as expected. If a user enters the URL with non-matching case (e.g. "mytarget", "MYTARGET", etc) the HTML (and presumably .js too) loads but the uibuilder websocket fails to make a connection to NodeRED.

There is some "difference of case-sensitivity behaviour" between the websocket vs the general http engine. I'm not clever enough to know exactly which component is responsible for what - maybe the http is served by the NodeRED engine rather than the uibuilder node.

Is there a setting in either uibuilder or NodeRED which forces URL case-sensitivity? I'd prefer that mismatching case results in complete failure to load the page, rather than the current "partially loaded but broken websocket" behaviour.

Annuello.

Interesting. Not come across that before and I'll admit that I've not tried it.

A quick test shows that socket.io makes the first part of the handshake (over http) just fine. But then it fails to "upgrade" the connection to websockets. It gets a response from the server:

{"code":1,"message":"Session ID unknown"}

So it seems that the issue is that Node-RED's web servers are case insensitive but the websocket connection in Socket.IO isn't.

I'll have to investigate whether it is possible to make Node-RED's web servers case sensitive. I'll also do a bit of research around Socket.IO case sensitivity.

May not be too helpful to you right now, but my recommendation is to avoid upper case in web URL's completely. Use - as a separator instead. You may, for example, hit other issues with proxy servers or when using Windows-based servers vs Linux-based ones.


By the way, the w3c specs on URL's say that the PATH element SHOULD be considered case-sensitive but the scheme and domain are not. So it actually seems to be Node-RED's web servers in error here.

Hi again. Done some research. To make case-sensitive routing apply to Node-RED you could try adding 'case sensitive routing': true, to the httpServerOptions in settings.js - however, I've not yet tested this and I don't know whether it will consistently work due to how ExpressJS works. If it doesn't work (try it on an http-in/-out pair first before trying with uibuilder where I think it won't work), you will need to put in a request to the Node-RED devs to have an option added. This thread shows some of the complexities: node.js - nodejs express - case sensitive URL's - Stack Overflow.

For uibuilder itself, I will look to see if I can add a suitable flag to a future release, some while back, I split the ExpressJS handling for uibuilder into multiple separate routers for better isolation and config. I will need to add a flag to each of them. Shouldn't be too hard to do but obviously would be a breaking change to simply enforce it.

A new version of uibuilder is in preparation (v6.6) so I can try to include it in that. I'll consider changing the default in the next major release as a breaking change.

Also worth noting that the same issue applies to Dashboard. If you have Dashboard on its default path of /ui/, trying to access as /UI/ loads the page outline but results in a blank page. In fact, it won't even load the socket.io client library. I will raise as an issue.

I gave this a try and it works, both with an initial http-in/-out pair as well as uibuilder URLs. (I don't use Dashboard.) With the above param set as described and a non-matching URL is requested, NodeRED/ExpressJS responds with "Cannot GET /myNonMatchingCase", which is the behaviour I was initially expecting/hoping for. :+1:

So I guess the issue can be described as two different things:

  • ExpressJS default values do not following the SHOULD recommendation of the W3C. Given that case-sensitivity is not a MUST, we probably can't technically call it a bug. However, there is already a parameter available to change this behaviour. I agree that this departure from the recommended behaviour should at least be documented somewhere in NodeRED, with the step needed to make it conform to the SHOULD behaviour.
  • SocketIO does not tolerate non-matching case when ExpressJS is configured for case-insensitivity. Given the SHOULD re case sensitivity, SocketIO not obliged to handle the non-matching case.

Thank you for your quick investigation, pointing me to a workable solution, and raising the core issue with the NodeRED team.

Annuello.

1 Like

Glad that worked, I must admit, I didn't think it would.

Good to know though. I'll probably still add the parameter to uibuilder and I'll update the docs since you can use a dedicated ExpressJS instance for uibuilder. So I need to document the equivalent parameter in the uibuilder section of settings.js.

Glad I could help.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.

Please note that UIBUILDER v7 has case sensitive URL's and routing turned on by default - if you are using its custom server feature - to match both W3C guidelines and Socket.IO.

2 Likes