Search code examples
multipartform-datanode-red

How to create multipart HTTP request in Node-RED


I'm trying to send a multipart request with the following form-data:

------WebKitFormBoundaryjFqPRXY6RQpdTRvE
Content-Disposition: form-data; name="file"; filename="Sample.csv"
Content-Type: application/vnd.ms-excel


------WebKitFormBoundaryjFqPRXY6RQpdTRvE
Content-Disposition: form-data; name="data"; filename="blob"
Content-Type: application/json

{"name":"Sample5","type":"Csv","firstRowIsHeader":true,"columns":[{ ... }]}
------WebKitFormBoundaryjFqPRXY6RQpdTRvE--

The above data is normally being created and sent by a web service.
I'm trying to replicate the exact same HTTP request from Node-RED.
JSON data is already prepared so it's just creation of the multipart request.

I've tried using node-red-contrib-http-multipart but I'm not really sure how to configure it.

[{"id":"e0fde1bd.e0aa","type":"httpInMultipart","z":"fc689d44.1c52","name":"","url":"/test/upload","method":"post","fields":"[ { \"name\": \"file\", \"maxCount\": 1}, { \"name\": \"data\", \"maxCount\": 1} ]","swaggerDoc":"","x":1390,"y":820,"wires":[["d109ed84.14d1d","8a39aaa0.6934c8","d0bc5b20.45f3a8"]]},{"id":"a2318dfd.bae7d","type":"http in","z":"fc689d44.1c52","name":"","url":"/test/send","method":"get","upload":false,"swaggerDoc":"","x":1380,"y":680,"wires":[["d7cfc418.89eb98"]]},{"id":"14c992f3.8652ad","type":"http response","z":"fc689d44.1c52","name":"","x":1750,"y":680,"wires":[]},{"id":"d109ed84.14d1d","type":"debug","z":"fc689d44.1c52","name":"","active":true,"console":"false","complete":"true","x":1570,"y":780,"wires":[]},{"id":"8a39aaa0.6934c8","type":"http response","z":"fc689d44.1c52","name":"","statusCode":"","headers":{},"x":1570,"y":860,"wires":[]},{"id":"1a646c83.8da7d3","type":"debug","z":"fc689d44.1c52","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1790,"y":780,"wires":[]},{"id":"d7cfc418.89eb98","type":"template","z":"fc689d44.1c52","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<form action=\"/test/upload\" method=\"POST\" enctype=\"multipart/form-data\">\n  <div>\n    <input type=\"file\" name=\"file\">\n    <input type=\"submit\" value=\"Submit\">\n  </div>\n</form>","output":"str","x":1580,"y":680,"wires":[["2971b104.12737e","14c992f3.8652ad"]]},{"id":"d0bc5b20.45f3a8","type":"change","z":"fc689d44.1c52","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t   \"file\": req.files.file[0].buffer,\t   \"data\": \"test\"\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1620,"y":820,"wires":[["1a646c83.8da7d3"]]},{"id":"2971b104.12737e","type":"debug","z":"fc689d44.1c52","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1730,"y":640,"wires":[]}]

Any kind of pointers on how to tackle the problem would be greatly appreciated.


Solution

  • It appears creating a multipart/form-data request directly on the HTTP request node is not yet supported. However, it's possible to manually create the multipart payload on a function node and feed it to the out-of-the-box HTTP request node.

    Basically, feed to the HTTP request node a payload like so (a snippet from flows.nodered):

    msg.headers = {
        "Content-Type": "multipart/form-data; boundary=------------------------d74496d66958873e"
    }
    
    
    msg.payload = '--------------------------d74496d66958873e\r\n'+
    'Content-Disposition: form-data; name="select"\r\n'+
    '\r\n'+
    'true\r\n'+
    '--------------------------d74496d66958873e\r\n'+
    'Content-Disposition: form-data; name="print"\r\n'+
    '\r\n'+
    'true\r\n'+
    '--------------------------d74496d66958873e\r\n'+
    'Content-Disposition: form-data; name="file"; filename="'+msg.filename+'"\r\n'+
    'Content-Type: application/octet-stream\r\n'+
    '\r\n'+
    msg.payload+'\r\n'+
    '--------------------------d74496d66958873e--\r\n';
    
    
    return msg;
    

    The format of the multipart payload is thoroughly discussed in discourse.nodered.
    A sample flow is also provided in flows.nodered.