How to post body data using Fetch API? - javascript

Below is the curl command that gives back the response successfully upon importing and running in postman.
curl --request POST \
--data "grant_type=password" \
--data "username=test" \
--data "password=xyz1234" \
--data "scope=write" \
--data "client_id=test" \
--data "client_secret=test12" \
"https://example.com/access_token"
Below is how I am sending data using fetch api in my js code.
const response = await fetch ('https://example.com/access_token',
{
'credentials' : 'include',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ grant_type:'password',username:'test',password:'xyz1234',scope:'write',client_id:'test',client_secret:'test12'}),
})
However the equilavent curl which is generated after copying from chrome developer tools is below.
curl --request POST \
--data-raw '{"grant_type":"password","username":"test","password":"xyz1234","scope":"write","client_id":"test","client_secret":"test12"}'
"https://example.com/access_token"
I suspect that the body data is not constructed in the correct format. This may be leading to a 400 error code response. How should I send the data using fetch api equilavent to working curl command?

Looking at the curl your data does seem to be URL encoded. So as it's not expecting JSON don't serialize it to a JSON string.
const headers = new Headers({
"Content-Type": "application/x-www-form-urlencoded"
});
const urlencoded = new URLSearchParams({
"grant_type": "password",
"username": "test",
"password": "xyz1234",
"scope": "write",
"client_id": "test",
"client_secret": "test12",
});
const opts = {
method: 'POST',
headers: headers,
body: urlencoded,
};
fetch("https://example.com/access_token", opts);
EDIT
As #Kaiido mentioned in the comments. It is not necessary to set the Content-Type header explicitly as the browser will do that automatically, but I have done it here to show you that it should not be set to application/json but to application/x-www-form-urlencoded.

Related

YouTubeAPI: How to upload thumbnail (JS)

I tried uploading thumbnail on youtube using this guide: https://developers.google.com/youtube/v3/docs/thumbnails/set
I was able to successfully run it on postman using this curl:
curl --location --request POST 'https://www.googleapis.com/upload/youtube/v3/thumbnails/set?videoId=<video id>' \
--header 'Authorization: OAuth <token>' \
--header 'Content-Type: image/png' \
--form 'thumbnail=#"/C:/Users/user/Pictures/nami.PNG"'
However I have trouble translating that into js, what I did so far is:
// the "file" is the File from <input type="file"> - data on this looks ok
uploadThumbnail async (file) {
const formData = new FromData();
const formData.append('thumbnail', file, 'test.png');
await fetch.post('https://www.googleapis.com/youtube/v3/thumbnails/set', {
headers: {
Authorization: 'Oauth <token>',
'Content-Type': 'multipart/form-data' // I also tried using the file.type here (image/png)
},
query: {
videoId: <video id>
},
body: formData,
})
}
(to simplify the logic, I only manually typed the code above, so pardon if there are any typo.)
but this throws The request does not include the image content. I don't understand, I also tried converting the File into Blob, but same error.
As pointed out on the comments on my main post, I combined the answers and came up with this (this works!)
await fetch.post(`https://www.googleapis.com/upload/youtube/v3/thumbnails/set?videoId=${videoId}&uploadType=media`, {
headers: {
Authorization: 'Bearer <token>',
'Content-Type': file.type
},
body: file,
})
Mistakes are:
My endpoint is wrong and is missing uploads (this API is different from other youtube endpoints, so if you are reusing a variable base_url better check it out.
Using Oauth instead of Bearer.
There are no query in fetch
No need to convert and add the formData, pass the file directly instead.

cURL with -F Option into NodeJS with Axios

I'm attempting to convert this CURL command
curl -X POST "https://serverless-upload.twilio.com/v1/Services/ZS5798711f7bee1284df67427071418d0b/Assets/ZH4912f44da25f4b1a1c042a16a17f2eac/Versions" \
-F Content=#./mapping/mapping.json; type=application/json \
-F Path=mapping.json \
-F Visibility=private \
-u username:password
into a post request using the package axios,
I've tried
url = `https://serverless-upload.twilio.com/v1/Services/${service_uid}/Assets/${asset_uid}/Versions`
data = {
'Path': 'mapping.json',
'Visibility': 'private',
'Content': JSON.stringify(mapping),
'filename': 'mapping.json',
'contentType': 'application/json'
}
await axios.post(url, data, {
auth : {
user: `${accountSid}:${authToken}`
},
headers: {
'Content-Type': 'multipart/form-data',
}
}).then((r) => console.log(r));
but I'm unsure if this is malformed or not
Twilio developer evangelist here.
The Twilio Node library actually uses axios under the hood, you can see it in action in the RequestClient. We also have a stand-alone Serverless API client which is part of the Twilio Serverless Toolkit you can use, but it is written with got instead.
You can use the Serverless API module to save yourself the work of recreating this request.
If you decide to continue with axios, here are the changes you should make.
Auth
Authorization is done via the Authorization header, passing a base 64 encoded string made up of the account Sid and auth token.
headers: {
Authorization: 'Basic ' + Buffer.from(`${accountSid}:${authToken}`).toString('base64')
}
Data
When uploading an asset, it is done as multipart form data. To build up multipart data in Node.js you can use the form-data module. Something like this should work:
const FormData = require("form-data");
const form = new FormData();
form.append("Path", "mapping.json");
form.append("Visibility", "private");
form.append("Content", JSON.stringify(mapping));
form.append("filename", "mapping.json");
form.append("contentType", "application/json");
await axios.post(url, form, {
headers: {
Authorization: 'Basic ' + Buffer.from(`${accountSid}:${authToken}`).toString('base64'),
...form.getHeaders(),
},
}).then((r) => console.log(r));
Let me know how you get on with that.

Converting cUrl token call to axios

I am trying to authenticate and API by calling to a seperate server, receiving a token to store, which is then used to Auth and API.
At the moment I have a token hardcoded in, because every time I submit a request with axios it returns "error": "invalid_request"
This cUrl script works fine curl -v -X POST -u "username:password" -d "grant_type=client_credentials" https://thewebsite/token -H 'cache-control: no-cache' and I can connect with Postman when I imported and added Basic Auth. I have tried to copy all the settings in, so many different ways.
I need to create an axios instance that is then passed to another function for the actual POST operation:
const settings = {
baseURL,
timeout: 5000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'cache-control': 'no-cache',
},
auth: {
username: username
password: password
},
data: {
grant_type: 'client_credentials',
},
};
this.axiosInstance = axios.create(settings);
In Postman the response looks like this:
"access_token": string,
"expires_in": 3600,
"token_type": "bearer"
I feel like it is an obvious syntax error, like the details need to be sent as a param or a header.

"Invalid grant_type parameter or parameter missing" Mailchimp OAUTH token

I have tried various implementations to connect to the Mailchimp OAuth API. Below is my current code producing the error :
"Invalid grant_type parameter or parameter missing"
I have tried x-www-form-urlencoded content type, stringifying the body and changing the headers.
let body = {
"grant_type": "authorization_code",
"client_id": Meteor.settings.public.mailchimp.clientId,
"client_secret": Meteor.settings.private.mailchimp.secret,
"redirect_uri": Meteor.settings.public.mailchimp.redirect_uri,
"code": code,
}
HTTP.call("POST",
`https://login.mailchimp.com/oauth2/token`, {
data: body,
headers: {
"Content-Type": "application/json",
"Content-Encoding": "",
"User-Agent": "oauth2-draft-v10"
},
npmRequestOptions: {
"gzip": true //Required to read error
}
}
... Code continued
Their documentation doesn't state anything obvious I am missing http://developer.mailchimp.com/documentation/mailchimp/guides/how-to-use-oauth2/
There must be a header or something I am missing.
From the mail chimp docs example (here https://developer.mailchimp.com/documentation/mailchimp/guides/how-to-use-oauth2/):
curl --request POST \
--url 'https://login.mailchimp.com/oauth2/token' \
--data "grant_type=authorization_code&client_id={client_id}&client_secret={client_secret}&redirect_uri={encoded_url}&code={code}" \
--include
It wants URL form encoded post body not JSON.

data-Binary in request nodejs

I'm trying to upload a file to dropbox throug nodeJS.
This CURL request works.
curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer myToken" \
--header "Dropbox-API-Arg: {\"path\": \"/Homework/math/Matrices.txt\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}" \
--header "Content-Type: application/octet-stream" \
--data-binary #fileName
I don't know how to translate it into javascript code.
Here's what I've accomplished so far:
var request = require('request')
var headers = {
"Authorization": "Bearer " + dropboxToken,
"Dropbox-API-Arg": {
"path": "/"+fileName, //nome sul drive
"mode": "add",
"autorename": true,
"mute": false
},
"Content-Type": "application/octet-stream"
}
var options = {
url: 'https://content.dropboxapi.com/2/files/upload',
method: 'POST',
headers: headers,
}
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body)
}
});
How do I include the data-binary option in this request in order to select the file to upload?
Thanks.
you can create a readstream and then pipe it to request with your current headers and options like-
fs.createReadStream('/path/to/youfile').pipe(request.post(options).on('end', (done) => { console.log('success') }));
First, if you're trying to integrate with the Dropbox API in JavaScript, we recommend using the official Dropbox API v2 JavaScript SDK, as it will do most of the work for you:
https://github.com/dropbox/dropbox-sdk-js
Otherwise, if you don't want to use the SDK, you can make the requests yourself. In this case, the --data-binary parameter is the curl parameter for supplying the data for the request to curl. curl then takes that data and puts it in the request body, which is the correct way to supply file data for a Dropbox API v2 "content-upload" style endpoint, such as /2/files/upload.
So, you should check the documentation for the HTTP client you're using for information on how to set the request body. It looks like you're using the request node module, which appears to take a body option, where you can put the request data.

Categories

Resources