node-fetch send post body as form-data - node.js

I am trying to send a POST request with body as form-data since this seems to be the only way that works.
I tried this in Postman too and sending body as raw JSON didn't work.
So I tried doing the same with node-fetch but seems like body is being sent as JSON and I'm getting the same error as before (when using raw from Postman).
try{
const { streamId } = request.body;
const headers = {
"Authorization": INO_AUTHORIZATION_CODE,
// "Content-Type": "multipart/form-data; boundary=<calculated when request is sent>"
"Content-Type": "application/json"
}
const url = `https://www.inoreader.com/reader/api/0/stream/contents/${streamId}`;
const body = {
AppId: INO_APP_ID,
AppKey: INO_APP_KEY
}
const resp = await fetch(url, {
method: 'POST',
body: JSON.stringify(body),
// body: body,
headers: headers
});
const json = await resp.text();
return response.send(json);
} catch(error) {
next(error);
}
Only setting body as form-data works:

You need to use the form-data package as mentioned in their doc
so your code will be
const FormData = require('form-data');
const form = new FormData();
form.append('AppId', INO_APP_ID);
form.append('AppKey', INO_APP_KEY);
const resp = await fetch(url, {
method: 'POST',
body: form
});

Usar:
const form = new URLSearchParams();
form.append('AppId', INO_APP_ID);
form.append('AppKey', INO_APP_KEY);

Related

Converting image URL to .png file using NodeJS

I am currently working on an application which takes in image URLs in this format:
https://replicate.delivery/pbxt/Y45OPyjFe92FLqemk1Mmsr69gzruylefj5SxKqJInMmxCyABB/out-0.png
And need to send it to an API to check if it is explicit content. The issue is that the API only accepts .png or .jpg files and not an image URL. How can I convert this image URL into a sendable file?
This is what their docs say:
const axios = require('axios').default;
const fs = require("fs");
const FormData = require("form-data");
const form = new FormData();
form.append("providers", 'amazon, google');
form.append("file", fs.createReadStream("🖼️ path/to/your/image.png"));
const options = {
method: 'POST',
url: 'https://api.edenai.run/v2/image/explicit_content',
headers: {
authorization: 'Bearer 🔑 Your_API_Key',
'Content-Type': 'multipart/form-data; boundary=' + form.getBoundary()
},
data: form
};
axios
.request(options)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
});
However, I do not have the path to the file and instead solely the image URL. Any help would be greatly appreciated!
You need to make an extra request to get the image first, keep it in memory (alternatively, you could save the file and then read it with fs), and then make another request, which sends the image to the checking endpoint.
With axios, you can get the image as a stream, and then just pass it along with form-data.
Try this:
// get image as a stream
const getImgOptions = {
method: 'GET',
url: 'https://replicate.delivery/pbxt/Y45OPyjFe92FLqemk1Mmsr69gzruylefj5SxKqJInMmxCyABB/out-0.png',
responseType: 'stream'
};
let img;
try {
img = await axios.request(getImgOptions);
// got the image, now send it for checking
let uploadImg;
try {
const form = new FormData();
form.append("providers", 'amazon, google');
form.append("file", img.data);
const postImgOptions = {
method: 'POST',
url: 'https://api.edenai.run/v2/image/explicit_content',
headers: {
authorization: 'Bearer 🔑 Your_API_Key',
'Content-Type': 'multipart/form-data; boundary=' + form.getBoundary()
},
data: form
};
uploadImg = await axios.request(postImgOptions);
// do something with the result
console.log('check response: ', uploadImg.data);
} catch (error) {
console.error(error);
}
} catch (error) {
console.error(error);
}

Send post request with Axios with body and headers

I am working on a project where I need to create a short URL for a link using bitly.
I got success by using the request package of Nodejs.
This is what I have done so far.
const token = process.env.BITLY_ACCESS_TOKEN;
let headers = {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
};
var dataString = `{ "long_url": "${req.body.url}"}`;
const api_url = "https://api-ssl.bitly.com/v4/shorten";
var options = {
url: api_url,
method: "POST",
headers: headers,
body: dataString,
};
request(options, (error, body) => {
if (error) {
return res.status(404).send(error);
}
return res.render("index", { error: "", data: JSON.parse(body.body) });
});
my question is how can we use Axios instead of the request package because the request package is deprecated.
I tried but did not get success.
const token = process.env.BITLY_ACCESS_TOKEN;
let headers = {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
};
var dataString = `{ "long_url": "${req.body.url}"}`;
const api_url = "https://api-ssl.bitly.com/v4/shorten";
const response = await axios.post(
api_url,
{ long_url: req.body.url },
{
headers: headers,
}
);
return res.render("index", { error: "", data: response });
I am getting errors like the body is not defined.
Please help me. Thank you!
const response = await axios.post(api_url, dataString, {
headers: headers,
});
console.log(response.data);
return res.render("index", { error: "", data: response.data });

request-promise post request to axios request

Can you please help me convert the following request to axios request.
const request = require('request-promise');
const data = {name:'pte', age:30}
const options = {secret:'34444'}
const opp = {
method: 'POST',
uri: 'https://something',
headers: { 'content-type': 'application/json' },
options,
body: JSON.stringify(data),
};
return request(opp);
const axios = require('axios')
const url = 'https://something'
const data = { name : 'pte', age : 30 }
const options = {
headers : {
'content-type' : 'application/json'
}
}
axios.post(url, data, header)

POST File in AXIOS NodeJs

Post file as raw body in AXIOS NodeJS. I tried many ways to achieve this but none of them worked.
What i have tried ?
var file = fs.readFileSync("a.jpg");
var body = await axios({ method: 'POST', url : "myUrl", data : file });
var file = fs.readFileSync("a.jpg").toString();
var body = await axios({ method: 'POST', url : "myUrl", data : file });
var file = fs.readFileSync("a.jpg",{encoding:"utf8"}).toString();
var body = await axios({ method: 'POST', url : "myUrl", data : file });
var file = fs.readFileSync("a.jpg");
file = Buffer.from(file).toString('utf8')
var body = await axios({ method: 'POST', url : "myUrl", data : file });
var file = fs.createReadStream("a.jpg");
var body = await axios({ method: 'POST', url : "myUrl", data : file });
But none of them worked as i wanted.
Actual working example from JQuery AJAX in Browser
var fileupload = $("#inpFile")[0];
var file = fileupload.files[0];
$.ajax({
url: "https://hookb.in/b9gqlwbZeaT3DDogQ7Om",
type: 'POST',
success: function (response) {
DisplayMessage(response);
},
data: file,
contentType: false,
processData: false
});
Have you tried setting the content-type header?
Per Talg123 I found that if you set contentType to false in jQuery it might be equivalent to multipart/form-data.
client side:
async function main(){
try{
const buffer = new ArrayBuffer(8);
const data = new FormData();
const blob = new Blob([buffer],{type : 'multipart/form-data'});
data.append('data', blob);
const options = {
url: "https://hookb.in/b9gqlwbZeaT3DDogQ7Om",
method: 'POST',
headers: { 'content-type': 'multipart/form-data' },
data
};
let result = await axios(options);
console.log(result);
}catch(e){
console.error("error",e);
}
}
main()
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
server side per https://github.com/axios/axios/issues/1006#issuecomment-584840380
const axios = require('axios');
const FormData = require('form-data');
// Where buffer is a file
formData.append('file', buffer);
// Added a promise version like seen in earlier comments to get this
const contentLength = await formData.getLength();
await axios(`<ENDPOINT>`, {
method: 'POST',
baseURL: <BASE_URL>,
params: {
fileName: '<FILE_NAME>.png'
},
headers: {
authorization: `Bearer <TOKEN>`,
...formData.getHeaders(),
'content-length': contentLength
},
data: formData
});
js fiddle for image/jpeg
https://jsfiddle.net/bn7yLh61/

Spotify Api Auth unsupported_grant_type

I'm working on integrating spotify and I'm making my own api. I can't understand why my request is not working. It works fine in python but not when I use express.
I get this response body :
{"error":"unsupported_grant_type","error_description":"grant_type must be client_credentials, authorization_code or refresh_token"}
Express :
var http = require('http');
var express = require('express');
var bodyParser = require('body-parser');
var fetch = require('node-fetch');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }))
app.listen(80);
app.post('/v1/spotify/api/token', function(req, res) {
let body = req.body
let redirect_uri = body.redirect_uri
let code = body.code
let data = {
grant_type:'authorization_code',
redirect_uri:redirect_uri,
code:code
}
fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
'Authorization':'Basic *client_id:client_secret*',
'Content-Type':'application/x-www-form-urlencoded'
},
body: JSON.stringify(data)
}).then(r => r.json().then(data => res.send(data)))
});
Python:
r = requests.post("https://accounts.spotify.com/api/token",
data={
"grant_type":"authorization_code",
"redirect_uri":*redirect_uri*,
"code":*code*
},
headers = {
"Authorization": "Basic *client_id:client_secret*",
'Content-Type':'application/x-www-form-urlencoded'}
)
In your script of Node.js, data is sent as a string value. So how about this modification?
Modified script
Please modify the object of data as follows and try again.
// Below script was added.
const {URLSearchParams} = require('url');
const data = new URLSearchParams();
data.append("grant_type", "authorization_code");
data.append("redirect_uri", redirect_uri);
data.append("code", code);
fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
'Authorization':'Basic *client_id:client_secret*',
'Content-Type':'application/x-www-form-urlencoded'
},
body: data // Modified
}).then(r => r.json().then(data => res.send(data)))
Reference:
Post with form parameters of node-fetch
If this didn't work, I apologize.
I had to put the client_id and client_secret in the body and not in Authorization header.
try {
const body = {
grant_type: "client_credentials",
client_id: <YOUR_ID>,
client_secret: <YOUR_SECRET>,
};
const response = await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams(body),
});
console.log({ response });
} catch (err) {
console.log({ err });
}

Resources