HTTP Request No Reply

Hi All,

I'm fairly new to Node-RED, so please bear with me...
I'm trying to set up a flow with a http-request node to send POST requests to an IP device on my network. However, I'm not getting a response back from the device. When I do a WireShark capture between the PC running NodeRED and my controller, I see that the controller gives a "403 Forbidden" error.

What really confuses me is that I've set up exactly the same flow on an Android device and that has no problem getting a response from the controller. Same network, same flow, same controller, just different host device.

Please advise me how I can troubleshoot this problem. It's really getting the best of a novice Node-RED user.

Thanks!

Hello @pcgopher,

I am a newbie too. I would suggest that you append a Debug node to display the response. You may have to set a value for User-Agent in the request payload. Browsers do it automatically and hence their requests are honored. The HTTP node does not and therefore when this nominal checking is performed at the server the HTTP 403 response is generated.

Regards.

Thanks for your reply!

I did append a Debug node and only get a " " as a response.

However, on the flow that works on the android device, I get '"<?xml version="1.0" ? ADAM-6260 status="OK" /ADAM-6260"' as a response.

Here is a bit of snippet that perhaps will help you to prep your request header prior to invoking the HTTP node:


msg.headers = {};
msg.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0';

Obviously, User-Agent illustrated is an example only. I use a Function node that precedes the HTTP node to prep the request as I have to build some additional parameters for the HTTP payload and not just the HTTP header.

Please take a look at my flow. Would you mind making the edits you suggested and re-post it.

[{"id":"28ff262d.27d912","type":"inject","z":"1fcf8288.513a9d","name":"Timer","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":true,"x":240,"y":180,"wires":[["2b91b135.7673e6"]]},{"id":"88e79510.a8f15","type":"debug","z":"1fcf8288.513a9d","name":"","active":true,"console":"false","complete":"false","x":1168.93408203125,"y":570.5867691040039,"wires":[]},{"id":"62c1567b.be7b2","type":"function","z":"1fcf8288.513a9d","name":"","func":"msg.payload = \"DO0=\"+context.global.heater1 + \"&DO1=\" + context.global.heater2 +\"&DO2=\"+context.global.heater3+\"&DO3=\"+context.global.heater4 +\"&DO4=\"+context.global.heater5 +\"&DO5=\"+context.global.heater6;\nreturn msg;","outputs":1,"noerr":0,"x":732.9931640625,"y":661.2639236450195,"wires":[["d7613b58.4abf48","7bbf16fa.ba3128"]]},{"id":"2b91b135.7673e6","type":"delay","z":"1fcf8288.513a9d","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":501.93408203125,"y":658.586799621582,"wires":[["62c1567b.be7b2"]]},{"id":"d7613b58.4abf48","type":"debug","z":"1fcf8288.513a9d","name":"","active":true,"console":"false","complete":"false","x":1168.93408203125,"y":670.5867691040039,"wires":[]},{"id":"7bbf16fa.ba3128","type":"http request","z":"1fcf8288.513a9d","name":"","method":"POST","ret":"txt","paytoqs":false,"url":"http://10.1.0.105/digitaloutput/all/value/","tls":"","persist":false,"proxy":"","authType":"basic","x":928.93408203125,"y":570.5867691040039,"wires":[["88e79510.a8f15"]]}]

OK, I will draft an alternate approach for you shortly. Rgds.

My changes:

  • Prepare the HTTP request payload

  • Use an arbitrary string for User-Agent

  • Change the HTTP method to GET and use payload as query parameters

[{"id":"76963223.f9f0cc","type":"inject","z":"f88b6022.f53bd","name":"Timer","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":true,"x":260,"y":1140,"wires":[["f90dfe23.61fa08"]]},{"id":"93b91cc3.fa59e","type":"debug","z":"f88b6022.f53bd","name":"","active":true,"console":"false","complete":"false","x":1188.93408203125,"y":1530.586769104004,"wires":[]},{"id":"2d59ea24.a3aa2e","type":"function","z":"f88b6022.f53bd","name":"","func":"//msg.payload = \"DO0=\"+context.global.heater1 + \"&DO1=\" + context.global.heater2 +\"&DO2=\"+context.global.heater3+\"&DO3=\"+context.global.heater4 +\"&DO4=\"+context.global.heater5 +\"&DO5=\"+context.global.heater6;\nmsg.payload = {\n \"DO0\":context.global.heater1,\n \"DO1\":context.global.heater2,\n \"DO2\":context.global.heater3,\n \"DO3\":context.global.heater4,\n \"DO4\":context.global.heater5,\n \"DO5\":context.global.heater6\n };\nmsg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0';\nreturn msg;","outputs":1,"noerr":0,"x":752.9931640625,"y":1621.2639236450195,"wires":[["b9a8c66b.e67758","2da677bd.ad1798"]]},{"id":"f90dfe23.61fa08","type":"delay","z":"f88b6022.f53bd","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":521.93408203125,"y":1618.586799621582,"wires":[["2d59ea24.a3aa2e"]]},{"id":"b9a8c66b.e67758","type":"debug","z":"f88b6022.f53bd","name":"","active":true,"console":"false","complete":"false","x":1188.93408203125,"y":1630.586769104004,"wires":[]},{"id":"2da677bd.ad1798","type":"http request","z":"f88b6022.f53bd","name":"","method":"GET","ret":"txt","paytoqs":true,"url":"http://10.1.0.105/digitaloutput/all/value/","tls":"","proxy":"","authType":"basic","x":948.93408203125,"y":1530.586769104004,"wires":[["93b91cc3.fa59e"]]}]

Just an adaption of what works for me. The key here is that the server will accept a GET and not insist on POST only for security reasons (again don't want to get into the weeds with a thesis here but just a word of caution in case my proposed changes don't work out for you otherwise we will have to explore the POST method).

Kind regards.

1 Like

Baqwas - I still don't get a response form the controller. I'm not sure the GET can work. I've attached a section from the manual on how the manufacture advises the setup to be

I really appreciate your time!

OK, I understand. Let me check the POST method for you. I'll need a bit more time for unrelated reasons. Rgds.

P.S. Brings back decade old memories when I used to mandate the use of POST and inhibit GET. Hoisted by my own petard as they say.

Hello pcgopher,

Can you try the following snippet (to check the POST method) after making changes to the DOn parameters (to set the context global values)? You may want to start with static values for these parameters unless impractical. Additionally, you may want to insert the string for ContentType in header in a manner similar to that used for User-Agent.

[{"id":"80aea113.0491c8","type":"inject","z":"abcc5f46.84c58","name":"Timer","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":true,"x":160,"y":160,"wires":[["ec48ae99.081be8"]]},{"id":"304cd64f.00b85a","type":"debug","z":"abcc5f46.84c58","name":"Debug: HTTP response","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":910,"y":160,"wires":[]},{"id":"465dfc62.fab69c","type":"function","z":"abcc5f46.84c58","name":"Prep request","func":"//msg.payload = \"DO0=\"+context.global.heater1 + \"&DO1=\" + context.global.heater2 +\"&DO2=\"+context.global.heater3+\"&DO3=\"+context.global.heater4 +\"&DO4=\"+context.global.heater5 +\"&DO5=\"+context.global.heater6;\nmsg.payload = {\n    \"DO0\": \"do1\",\n    \"DO1\": \"do2\",\n    \"DO2\": \"do3\",\n    \"DO3\": \"do4\",\n    \"DO4\": \"do5\",\n    \"DO5\": \"do61\",\n};\nmsg.headers = {\n        \"User-Agent\": 'Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0'\n}\nreturn msg;","outputs":1,"noerr":0,"x":490,"y":160,"wires":[["5652ebd4.e8a38c","e09eed87.4e046"]]},{"id":"ec48ae99.081be8","type":"delay","z":"abcc5f46.84c58","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":320,"y":160,"wires":[["465dfc62.fab69c"]]},{"id":"5652ebd4.e8a38c","type":"debug","z":"abcc5f46.84c58","name":"Debug: prep request","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":900,"y":380,"wires":[]},{"id":"e09eed87.4e046","type":"http request","z":"abcc5f46.84c58","name":"","method":"POST","ret":"txt","paytoqs":false,"url":"http://10.1.0.105/digitaloutput/all/value/","tls":"","proxy":"","authType":"","x":690,"y":160,"wires":[["304cd64f.00b85a"]]}]

Haven't really done anything much with your flow/code except for the HTTP request header. If there was a public facing URL that the vendor provides for test purposes then that would shorten the debug cycles.

Kind regards.

Hello pcgopher,

I used the authoritative recommendation at article to make the changes to the function. You may recognize the source.

Kind regards.

1 Like

Make sure to set the debug node to 'complete msg object' for its response.

Hi Baqwas, Here are the results...not much has changed.

11/22/2019, 5:29:12 PMnode: Debug: prep request

msg.payload : Object

{ DO0: "do1", DO1: "do2", DO2: "do3", DO3: "do4", DO4: "do5" … }

11/22/2019, 5:29:12 PMnode: Debug: HTTP responsemsg.payload : string[0]

" "

I'm not aware of any public facing URL that the vendor provides. I've worked closely with the vendor on this issue and they told me they're might be a bug in the Windows 10 version of Node-RED. But I've tried the same flow on a Linux system with the same results. However, it does work on Node-RED v. 10.0.14 on an Android device??

You need to change my arbitrary values to your required values. For example:

Change "do1" to context.global.heater1 and so forth. If you happen to know the static values for these, my preference would be start with these static values (sorry for recommending a dumb down approach but even on modern airplanes with FMS I look out of the window to see if the flaps are down during takeoff).

Personally, I don't think there is any bug here. It is simply a matter of using the msg.payload object correctly. Sorry, I'm not able to demonstrate any progress. I'll scrounge around for some public facing end point to test the basic method but I feel that the current issue lies with my suggestion on the run-time values for the DOn parameters.

Let me know what you think.

What is the HTTP response code? 2xx or 4xx?

Kind regards.

I'll repeat myself:

Make sure to set the debug node to 'complete msg object' for its response.

This is the only way to see what response headers you will get and a 403 will definitely show up.

Backman2 - Where can I find this setting. I looked for this yesterday, but didn't see it.

double click the debug node, change the output field.

Thanks for that! Here are the results:

11/23/2019, 7:04:32 AMnode: Debug: prep request
msg : Object
object
topic: ""
payload: object
DO0: "context.global.heater1"
DO1: "context.global.heater2"
DO2: "context.global.heater3"
DO3: "context.global.heater4"
DO4: "context.global.heater5"
DO5: "context.global.heater6"
_msgid: "44ba30e4.27ffa"
headers: object
User-Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
11/23/2019, 7:04:32 AMnode: Debug: HTTP responsemsg : Object
object
topic: ""
payload: ""
_msgid: "44ba30e4.27ffa"
headers: object
server: "ADAM-6000/8.1.0019"
connection: "close"
x-node-red-request-node: "578e04e6"
statusCode: 403
responseUrl: "http://10.1.0.105/digitaloutput/all/value/"
redirectList: array[0]

Baqwas -

The HTTP response code is 403. I think this is a strange error to get for this server, because I can easily access it with my browser by typing in only it's IP address.

I changed the DOn parameters to the values you indicated, and posted my results above.

Hello pcgopher,

The HTTP 403 error cannot be resolved by the payload change that I am suggesting below but just for my understanding would it be possible to replace "context.global.heater1" with a static value string temporarily until the access issue is resolved?

Also, I don't see the ContentType value in the request header you have posted? Did you make the change for that along the following lines:

 msg.headers = {'ContentType':'application/x-www-form-urlencoded'};

Kind regards.