I would like to POST two data in multipart / form-data format using Node-RED.
(One for text data, one for voice data)
I set the function node and http request node as follows, but it does not seem to be POST.
I think that it is necessary to create a multi-part body and assign it to msg.body, but I do not know how to create a multi-part body of the voice data.
I do not know how to solve it, so someone would like to tell me.
function node
var request = global.get('requestModule');
var fs = global.get('fsModule');
msg.body = {};
msg.body = {
'apikey' : "**********",
'wav' : fs.createReadStream('/tmp/testtest.wav')
};
msg.headers = {};
msg.headers['Content-type'] = 'multipart/form-data';
return msg
http request(Property)
method ⇒ POST
URL ⇒ https://xxxxyyyzzz/
SSL/TLS ⇒ No
Basic ⇒ No
Output ⇒ JSON
The http request Node-Red core node support multipart/form-data POST out of the box.
Add a function node before your http request with this Function :
msg.headers = {};
msg.headers['Content-Type'] = 'multipart/form-data';
msg.headers['Accept'] = 'application/json';
msg.payload = {
'apikey': msg.apiKey,
'wav': {
value: msg.payload.invoice.file,
options: {
filename: 'testtest.wav',
contentType: 'audio/wav', // This is optionnal
}
}
}
return msg;
The http request node use Request nodejs library under the hood, and this one use form-data library for handling multipart, so all the options supported by these works.
The source code of the relevant part of http request handling multipart.
Related
I am trying to validate that an http POST request to an AWS Lamdbda function URL from a Twilio HTTP Request widget inside a Twilio Studio flow truly originated from Twilio. I am using the Node.js Twilio client library, which provides the validateRequest method to accomplish what I am after. The content-type header in the Twilio Studio flows HTTP Request widget is set to application/json
The problem is that I am passing in the "x-twilio-signature" header, the url, twilio auth token, and POST params to the validateRequest method and it always returns false. Below is the code snippet used to try and accomplish this.
const authToken = process.env.twilio_auth_token
const sid = process.env.twilio_account_sid
const client = require('twilio')
exports.handler = (event) =>
{
let twilioSignature = event.headers['x-twilio-signature']
let requestBody = event.body
let requestUrl = 'https://my-function-url.io/'
let requestIsValid = client.validateRequest(authToken, twilioSignature, requestUrl, requestBody)
if(requestIsValid){
console.log('valid request')
} else {
console.log('invalid request')
}
}
Seems like someone else had a similar issue in the past. I copied parts of the answer here:
The issue here is that query string parameters are treated differently to POST body parameters when generating the signature.
Notably part 3 of the steps used to generate the request signature says:
If your request is a POST, Twilio takes all the POST fields, sorts them by alphabetically by their name, and concatenates the parameter name and value to the end of the URL (with no delimiter).
Is it possible to PUT a file with Http Utils as multipart form encoded?
This is what I tried:
var response = $"{_baseUrl}{address}".PutBytesToUrl(File.ReadAllBytes(filePath), "image/jpeg", "*/*",
requestFilter: req =>
{
req.Headers["x-aws-acl"] = "private";
req.Headers["content_type"] = "image/jpeg";
req.Headers["X-Shopify-Access-Token"] = _accessToken;
});
The request goes through with 200 but the API (Shopify) doesn't have the image.
I tried running the request in postman and with postman the request works and shopify has the image after.
I used webhook.site to see what the different was in http utils and postman and it seems postman is sending multipart encoded form.
Here are http utils headers being sent that result in no image:
Here are postman headers:
Any way to get http utils to send the image as multipart form data?
To Upload Files as multipart/form-data you would need to use the UploadFile APIs which accepts an overload for specifying which HTTP Method to use, e.g:
var webReq = (HttpWebRequest)WebRequest.Create("http://example.org/upload");
webReq.Accept = MimeTypes.Json;
using var stream = uploadFile.OpenRead();
webReq.UploadFile(stream, uploadFile.Name, MimeTypes.GetMimeType(uploadFile.Name),
method:"PUT");
I have a node-express application.
There, I'm trying to make a call to an API which is responding an raw xlsx object as
'Content-Type' : 'application/octet-stream;charset=;UTF-8'
Code how I'm calling the API:
var unirest = require("unirest");
var reqClient = unirest("POST", "https://api.application.com/getExcel");
reqClient.headers({ "Authorization": "Bearer " + req.session.passport.user.token,
"content-type": req.headers['content-type'], "application/json"});
reqClient.type("json");
reqClient.send(JSON.stringify(requestbody));
reqClient.end(function(res) {
if (res.error) throw new Error(res.error);
console.log(res.body);
});
Now 2 things I'm trying to do actually with this data.
Write that into an excel file.
Below is the code how I'm trying it:
let data = res.body // res is the response coming from the API
let buf = Buffer.from(data);
excelfile = fs.createWriteStream("result.xlsx");
excelfile.write(buf);
excelfile.end();
Trying to send it to UI where the excelfile will get created.
Below is my code for that:
let data = res.body // res is the response coming from the API
let buf = Buffer.from(data);
response.write(buf); //response is the response to the request to ui
response.end();
So in both the cases the file is coming corrupted.
But the API response is prefect because, when it's directly getting consumed by the UI, xlsx file is generating properly.
When dealing with binary data, you have to set the encoding to null
reqClient.encoding(null)
reqClient.encoding(null)
reqClient.end(function(res) {
if (res.error) {
return response.status(500).send('error');
}
// res.body is now a buffer
response.write(res.body);
response.end();
});
Otherwise, the data is converted to UTF-8 and you can't convert from UTF-8 back to binary and get the same data, which is what you were doing:
Buffer.from(res.body)
The recommended approach is to use streams directly, I don't see a way of doing this in a simple way in unirest, I recommend using request or got, so you can .pipe directly to a file or express res
I'm trying to build a serverless Slackbot using Lambda function. I end up with an error while verifying the Request URL through the Slack event API. #slack/events-api is the dependency that I'm using to capture the slack events.
Here is my code.
const sls = require('serverless-http');
const { createEventAdapter } = require('#slack/events-api');
require('dotenv').config();
const { SLACK_SIGNING_SECRET } = process.env
const slackEvents = createEventAdapter( SLACK_SIGNING_SECRET || '' );
slackEvents.on('message', async event => {
console.log('received!')
});
module.exports.server = sls(slackEvents.requestListener());
This is the error that I'm getting while verifing the request url
Slack Request URL verification
Can someone help me with this?
Just ran into this exact issue, and took a look into http-handler.js in node-slack-events.
All we have to do is store the raw request body as rawBody before serverless-http parses it.
serverless-http lets you transform the request, before it is sent to the app—great opportunity for a fix:
module.exports.handler = serverless(app, {
request(request) {
request.rawBody = request.body;
},
});
I'm not sure how to solve your problem exactly, but I do know what's causing it.
The library you're using, serverless-http parses the JSON body sent by Slack. This causes an error to be thrown, because the slack-api-sdk expects to parse the raw request body itself.
Could you try removing serverless-http and just respond to the API Gateway event?
On my AWS lambda function i have access to an event json which holds a parameter called: body. the issue is this is a raw body string (not parsed into individual parameters).
{
input: {
body: "------WebKitFormBoundarys3wLu6HlaCBrIExe\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n------WebKitFormBoundarys3wLu6HlaCBrIExe\r\nContent-Disposition: form-data; name=\"media[]\"\r\n\r\nhthtth\r\n------WebKitFormBoundarys3wLu6HlaCBrIExe\r\nContent-Disposition: form-data; name=\"media[]\"\r\n\r\nlololol\r\n------WebKitFormBoundarys3wLu6HlaCBrIExe--\r\n"
}
}
I'd like to take that and turn into:
{
foo: 'bar',
media: [
"grgkoerpkge",
"twepgbopcib"
]
}
I'd prefer not to use some bloated express server just to parse a body string.
P.S. I've tried to use body-parser but it seems like it only works with express as a middleware
const {URLSearchParams} = require('url')
const sp = new URLSearchParams(event.body)
Encountered similar issue recently, as content-type in request was plain text format, I used querystring, built in module in node js to parse body string,
more about querystring
const querystring = require('querystring');
& in lambda handler,
var jsonData = querystring.parse(event.body);
Send it to your lambda as JSON.
Then, in your lambda (if you use lambda-proxy integration), parse it by using JSON.parse(event.body).
You'r passing the params by form or with the "Content-Type" in the header "application/x-www-form-urlencoded".
You shoukd pass it with "application/json"