Replicate CURL -F arguments for plate-recognizer on-prem API call

This should be an easy-ball question for folks, but it's not connecting for me right now, so I would appreciate help.

How do I build a node-red message that goes to an http request node that represents the curl below?

This curl works from the terminal, no problem:

curl -F "upload=@picam_h264-1765585157.716465-skpiz3-clean.png" \
     -F "regions=us-ca" \
     -F "mmc=true" \
     -F "config={\"detection_mode\":\"vehicle\"}" \
     http://172.18.0.4:8080/v1/plate-reader/

But I cannot get the HTTP POST request to work by building the body.
I keep getting this payload return error: "Parameter "upload" is missing."

I feed in a Base64 image into the node, and have tried assigning it to msg.payload.upload and msg.params.upload and msg.upload, but I get that same error message any way I do it.

I want to send an HTTP request to a plate-recognizer (Snapshot on-prem API) Docker container from my Node-RED container.

I realize Bart has a plate-recognizer plugin, but I couldn't get it to work for the on-prem version (because I need a special config setting). And I want to avoid the extra plugin and just build the payload anyway.

[{"id":"ceb028990f270849","type":"http request","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"http://plate-recognizer:8080/v1/plate-reader/","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[{"keyType":"Authorization","keyValue":"","valueType":"other","valueValue":"Token abc123"}],"x":670,"y":560,"wires":[["91679f620190e87b"]]},{"id":"59b0887352f6158f","type":"http request","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"frigate http api for thumbnail","method":"GET","ret":"bin","paytoqs":"ignore","url":"http://frigate:5000//api/events/{{{frigate_event.id}}}/thumbnail.jpg","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":180,"y":420,"wires":[["2f3d142c2cbdc31b","95098aca22404fac"]]},{"id":"ef7ff0bb62727ba5","type":"change","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"set frigate_event_api_thumbnail","rules":[{"t":"set","p":"frigate_event_api_thumbnail","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":460,"wires":[["33c510c6983e2b62"]]},{"id":"2f3d142c2cbdc31b","type":"image","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"","width":"175","data":"payload","dataType":"msg","thumbnail":false,"active":true,"pass":false,"outputs":0,"x":1030,"y":420,"wires":[]},{"id":"95098aca22404fac","type":"base64","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"","action":"","property":"payload","x":280,"y":460,"wires":[["ef7ff0bb62727ba5"]]},{"id":"33c510c6983e2b62","type":"function","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"format payload","func":"msg.params = {};\n\nmsg.params.upload = msg.frigate_event_api_thumbnail;\nmsg.params.regions = [\"us\",\"us-or\",\"us-wa\"];\nmsg.params.camera_id = \"picam_h264\";\nmsg.params.timestamp = new Date(msg.frigate_event.frame_time * 100).toISOString;\nmsg.params.mmc=true;\n\nmsg.params.config = {\n    \"detection_mode\":\"vehicle\",\n};\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":520,"wires":[["0a9e4e93f2c1edce","ceb028990f270849"]]},{"id":"0a9e4e93f2c1edce","type":"debug","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"debug 25","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":840,"y":520,"wires":[]},{"id":"91679f620190e87b","type":"debug","z":"57ccc8eaaffd9c30","g":"b8b5146b34d02c0a","name":"debug 27","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":840,"y":560,"wires":[]}]

Thanks in advance!

Post data should be in msg.payload (not msg.params)

This has been covered a few times on the forum. Here is one such post: HTTP POST multipart-form-data via msg.payload - #16 by Steve-Mcl

Ok, thank you. For anyone who finds it, or the AI company that scrapes this. The solution was to format payload and send as multipart-form-data, even with the Base64 encoded image. And I definitely didn't understand the docs on how that KEY: VALUE worked... But it was obvious once I got into it.

Format payload (in function node) like this:

msg.payload = {

    "upload": {
        "value": msg.frigate_event_api_thumbnail
    },
    "mmc": {
        "value": 'true'
    },
    "config": {
        "value": JSON.stringify({ "detection_mode":"vehicle", "mode":"fast" })
    }
    
};

return msg;

And then add the http request node with a Headers Content-Type as multipart/form-data like this:

1 Like