Receive JSON response from POST request in Node.js - node.js

I'm trying to authorize using Spotify in NodeJS. This is my code:
app.get('/auth', function(req, res){
if(req.query.error){
res.redirect('/error');
};
var resdata;
const data = querystring.stringify({
'grant_type':'authorization_code',
'code': req.query.code,
'redirect_uri': 'https://<MYURL>/auth',
'client_id': process.env.ID,
'client_secret': process.env.SECRET
})
const options = {
hostname: 'accounts.spotify.com',
port: 443,
path: '/api/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
}
const authreq = https.request(options, authres => {
authres.on('data', d => {
resdata += d;
})
authres.on('end', d => {
res.send(resdata);
})
})
When I make the request, I get this response:
undefined{\"access_token\":\"<TOKEN>\",\"token_type\":\"Bearer\",\"expires_in\":3600,\"refresh_token\":\"<TOKEN>\",\"scope\":\"playlist-read-private user-modify-playback-state\"}
How do I turn this into JSON?
I want to do this in plain NodeJS, without any modules if possible.

Assign resdata to empty string like this instead of keeping it undefined.
var resdata = '';
And in your end listener change it to
authres.on('end', d => {
res.send(JSON.parse(resdata));
})

You could use JSON.parse(result.slice(9))
But there's probably a better way.

Related

how to use access token to call another post request?

I have this post request to get access token and its working fine but would like to know how can I use this access token to call another post request ? Or how do I use async or promises to use in this ?
Here is my code :
function getAccessToken() {
const querystring = require('querystring');
const https = require('https')
const postData = querystring.stringify({
'grant_type': 'client_credentials'
});
const options = {
"hostname":'api.xxx.com',
"method": "POST",
"path" : "/token",
"port" : 443,
"encoding": "utf8",
"followRedirect": true,
"headers": {
"Authorization": 'Basic ' + Buffer.from("client_id" + ':' + "client_secret").toString('base64'),
"Content-Type": 'application/x-www-form-urlencoded',
"Content-Length": Buffer.byteLength(postData),
},
'muteHttpExceptions': true
}
const body = []
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (chunk) => body.push(chunk))
res.on('end', () => {
const access_token = Buffer.concat(body).toString()
console.log(access_token)
})
})
req.on('error', error => {
console.error(error)
})
req.write(postData);
req.end()
}
getAccessToken();
You can save token in database,file or other memory database and use it in all requests in the Authorization header but depends on type of token,for example for set JWT token:
request.setHeader('Authorization', 'Bearer '+accessToken)
OR in option object:
options = {
host: '<URL>',
path: '<path of endpoint>',
port: '<portNumber>',
headers: {'Authorization', 'Bearer '+accessToken}
};
also for the async request to another endpoint, you can use Axios axios example:
const axios = require('axios').default;
const sendGetRequest = async () => {
try {
const resp = await
axios.get('https://jsonplaceholder.typicode.com/posts', {
headers: {
'authorization': 'Bearer YOUR_JWT_TOKEN_HERE'
}
});
console.log(resp.data);
} catch (err) {
// Handle Error Here
console.error(err);
}
};
sendGetRequest();

How to hide my API Key in a POST request?

I want to hide my API key when I am making a post request from my browser. I need to input a number plate and send the request to the API and the API responds me with details about it. I have managed to get this working with a GET request to another API by using nodeJS but I can't manage to make it work with a post request. Keep in mind the request needs information from my input field in the browser which is the registration number of the vehicle to send me information back about it.
Here is my function in my browser JS file.
const searchBtn = document.getElementById("search-btn")
function startFetch() {
let plate = document.getElementById("plate").value
let reg = {registrationNumber: `${plate}`}
fetch(`https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': `my key is here`,
},
body: JSON.stringify(reg),
})
.then(response => response.json())
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
};
searchBtn.addEventListener("click", startFetch);
Any help and method would be appreciated. Thanks in advance.
For anyone in the same boat. I have managed to achieve what I want.
Client side JS file:
function startFetch() {
let plate = document.getElementById("plate").value
let reg = {registrationNumber: plate}
fetch(`http://localhost:3000/v`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(reg),
})
.then(response => response.json())
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
};
And the backend using Express, NodeJS, body-parser and axios
require("dotenv").config()
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const axios = require('axios');
app.use(bodyParser.json());
app.use(express.static("src"))
//Env vars
const API_URL = process.env.API_URL
const API_KEY = process.env.API_KEY
app.post('/v', (req, res) => {
const body = req.body;
// Make a request to the backend API
axios.post(API_URL, body,
{
headers: {
"Content-Type": "application/json",
'x-api-key': API_KEY
}
}
)
.then((response) => {
// Return the response from the backend API to the client
res.send(response.data);
})
.catch((error) => {
// Handle any errors
res.status(500).send(error);
});
});
app.listen(3000, () => {
console.log('API proxy server is listening on port 3000');
});
You are already sending the body.
A very minor modification to you code:
function startFetch() {
let plate = "abc123";
let reg = { registrationNumber: `${plate}` };
fetch(`https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": `my key is here`,
},
body: JSON.stringify(reg),
}
);
}
startFetch();
You can see your api-key in the header (though you should never send secret via http):
Then in the body (in chrome they call it payload):

nodejs modio api "add modfile" failing to upload

Im trying to upload modfiles with the api but it keeps saying that Im not including filedata. Ive tried with fetch like in the docs but it just gives the same error. If I try http it just gives a list of the files as if it was a GET request.
var zip = `./mod.zip`; // it exists!
var body = {
//filedata: `#${zip}`,
filedata: fs.readFileSync(zip, `binary`),
//filehash: crypto.createHash('md5').update(fs.readFileSync(zip, `binary`)).digest('hex'),
//version: version,
//active: active,
//changelog: changelog,
//metadata_blob: meta,
};
var res = await fetch(`https://api.mod.io/v1/games/${config.modio.gameid}/mods/${config.modio.modid}/files`, { // actually HTTP
method: 'POST',
headers: {
'Authorization': `Bearer ${config.modio.token}`,
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
},
body: JSON.stringify(body),
});
//console.log(body.filedata);
res = await res.json();
if (res.error)
console.log(res.error);
else
console.log(res);
{
"error": {
"code": 422,
"error_ref": 13009,
"message": "Validation Failed. Please see below to fix invalid input:",
"errors": {
"filedata": "The filedata field is required when upload id is not present.",
"upload_id": "The upload id field is required when filedata is not present."
}
}
}
Yes, ive submitted a bug report to them already, twice. Now they are ghosting me. (I'll probably submit a link to this as well)
They replied!
Hi
As mentioned, you would need to send data using FormData, not JSON.
You can find details at https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
Thanks,
Danny King
Developer Relations Specialist
So, I remade my code
const https = require(`https`);
var crypto = require('crypto');
var FormData = require('form-data');
function ObjectToForm(obj = {}) {
var form = new FormData();
Object.keys(obj).forEach(key => {
var val = obj[key];
switch (typeof val) {
case `boolean`:
val = String(val);
break;
}
form.append(key, val);
});
return form;
}
if (fs.statSync(zip).size > 5368709120) return consolelog(`Zip bigger then 5gb`);
var body = {
filedata: fs.createReadStream(zip),
filehash: crypto.createHash('md5').update(fs.readFileSync(zip)).digest('hex'),
version: version,
active: active,
changelog: changelog,
metadata_blob: meta,
};
var form = ObjectToForm(body);
var options = {
hostname: 'api.mod.io',
port: 443,
path: `/v1/games/${config.modio.gameid}/mods/${config.modio.modid}/files`,
method: 'POST',
headers: {
'Authorization': `Bearer ${config.modio.token}`,
...form.getHeaders(),
'Accept': 'application/json',
},
};
var req = https.request(options, (res) => {
var data = [];
res.on('data', (d) => data.push(d));
req.on(`close`, () => {
var buffer = Buffer.concat(data);
var resp = JSON.parse(buffer.toString());
if (resp.error)
console.log(resp.error);
else if (res.statusCode == 201)
r(true);
});
});
req.on('error', (e) => {
console.log(`Error publishing:`);
console.log(e);
r(e);
});
form.pipe(req)
.on(`close`, () => req.end());
And it worked. Thanks King.

Sending form in post request using https library

I have to call an api, for which we are using request library.
const options = {
uri: 'https://abcd.com',
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer xxxxxxxxx'
},
form: {
'a':1,
'b':2
}
}
request(options, (e, res, data) => {});
How would I rewrite the same using node's https library.
I tried using https library's https.request() with 'POST' type and .write with form object. Didn't work.
Also changed Content-Type to application/x-www-form-urlencoded, didn't work either
This example is from the documentation using the request package ,the form takes a object consisting of key value pair from that of the form
request.post('http://service.com/upload', {form:{key:'value'}})
// or
request.post('http://service.com/upload').form({key:'value'})
// or
request.post({url:'http://service.com/upload', form: {key:'value'}},
function(err,httpResponse,body){ /* ... */ })
enter link description here
You can read the API docs at: https://nodejs.org/api/https.html
Below code should work fine:
const https = require('https')
const data = JSON.stringify({
'a':1,
'b':2
})
const options = {
hostname: 'example.com',
port: 443,
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Length': data.length
'Authorization': 'Bearer xxxxxxxxx'
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()

Cant read post from Fetch in node

I'm posting the data {id: "abc123", text: "sometext"} to a node API. Posting from a component with action call:
export function addTextToAPI(inputData) {
return(dispatch) => {
console.log(inputData),
dispatch(addText(inputData))
fetch(myapi, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
data: inputData
})
.then(res => res.json())
}
}
console.log(inputData) is {id: "abc123", text: "sometext"}
node:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.post('/addtest', (req, res) => {
console.log(req.body); // <= returns blank object {}
console.log(req.body.data); // <= returns undefined
console.log(req.query); // <= returns blank object {}
console.log("test added");
});
app.listen(3000);
I want to be able to read the inputData in req. How do I do that? I want to be able to read the inputData in req. How do I do that?
To post data you need to pass in a body param to fetch.
This should work:
export function addTextToAPI(inputData) {
return(dispatch) => {
console.log(inputData),
dispatch(addText(inputData))
fetch(myapi, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify(inputData)
})
.then(res => res.json())
}
}

Resources