How you manually parse a raw request withtout using express.raw() - javascript

i'm implementing Stripe Webhooks and everything works fine but I'm having problems validating the payload when there are special characters(example, áéíóú). The code:
const endpointSecret = "whsec_xxx";
// stripe signature
const sig = headers['Stripe-Signature'][0]
const stripe = require('stripe')(
'sk_test_yyy'
);
//const buf = new Buffer(body, 'base64');
// let text = buff.toString('ascii');
try {
event = stripe.webhooks.constructEvent(body.text(), sig, endpointSecret);
} catch (err) {
response.setStatusCode(400);
throw err;
}
The thing is that i'm using Realm MongoDB HTTP EndPoints that don't support adding a body parser in the function. So What I have is just this:
exports = async function({ query, headers, body }, response) {
I can read the raw body using body.text() and this works fine in most cases, but not all.
What I Need is to emulate the JSON parsing when I declare the function like this:
app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {
This way always works. But I don't know how to manually parse the body in the same way that bodyparse does it.
Is there any way to achieve this?

Related

I'm unable to send a response to my react.js using http.get in node

I'm trying to get the temperature data from my node.js backend sent to react.js but i kept getting res.send is not a funtion
Sample code here
app.get("/gettemperature", (req, res) => {
const email = req.query.email;
let stmt = `SELECT * FROM users WHERE email=?`;
let todo = [email];
db.query(stmt, todo, (err, results, fields) => {
if (err) {
console.error(err.message);
}
if(results.length > 0 ){
let id = results[0].id;
let getID = `SELECT * FROM controlModules WHERE deviceowner=?`;
let getidData = [id];
db.query(getID, getidData, (err, resulta, fields) => {
if (err) {
console.error(err.message);
}
if(resulta.length > 0){
let lanip = resulta[0].ipaddress;
let url = "http://"+lanip+"/data";
http.get(url,(res) => {
let body = "";
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
try {
let json = JSON.parse(body);
const temp_actual = json.temperature.value;
console.log(temp_actual);
res.setHeader('Content-Type', 'application/json');
res.end(
JSON.stringify({
value: temp_actual
})
);
} catch (error) {
console.error(error.message);
};
});
}).on("error", (error) => {
console.error(error.message);
});
}
});
}
});
});
i really need to return/send/respond the temperature data to my front end but i'm getting said error, is there a different way to return data?
It looks like you are mixing up an HTTP server you wrote in Node (although you haven't shown any relevant code) and an HTTP client you also wrote in Node.
res is an argument received by the callback you pass to http.get and contains data about the response received by your HTTP client.
Meanwhile, somewhere else (not shown) you have a different variable also called res which is the object your HTTP server uses to send its response to the browser running your React code.
You are calling res.send and wanting res to be the latter but it is really the former.
Since you haven't shown us the HTTP server code, it is hard to say where that res is, but there is a good chance you have shadowed it and can solve your problem by using different names (e.g. client_res and server_res).
That said. I strongly recommend avoiding using the http module directly as the API follows out of date design patterns and isn't very friendly. Consider using fetch or axios for making HTTP requests and Express.js for writing HTTP servers.

Node.js PostgreSQL http - Uncaught error on UPDATE query

This is my server.js. I am creating a simple CRUD todo app.
I am making requests from another NodeJS script.
When I make a PUT request I found (by using breakpoints) that I get an uncaught error: source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression. Even though it is just a simple UPDATE query.
Any help is appreciated.
if (method == "PUT" && /\/todos\/(\S+)\/$/.test(url)) {
console.log("PUT request at", url);
const urlId = url.match(/\/todos\/(\S+)\/$/);
console.log(urlId);
try {
let jsonData = "";
req.on("data", chunk => {
jsonData += chunk;
});
req.on("end", async () => {
const data = JSON.parse(jsonData);
console.log([String(data["description"]), Number(urlId[1])]);
const updateTodo = await pool.query(
"UPDATE todo SET description = '$1' WHERE todo_id = $2 RETURNING *;",
[String(data["description"]), Number(urlId[1])]
); // ERROR
console.log(JSON.stringify(updateTodo));
res.setHeader("Content-Type", "application/json");
res.write(JSON.stringify(updateTodo["rows"]));
res.end();
});
} catch (err) {
console.error(err);
res.end();
}
}
Database -
CREATE DATABASE learn_restapi
CREATE TABLE todo(
todo_id SERIAL PRIMARY KEY,
description VARCHAR(255)
);
One thing I found is a bug report.
Finally, found the bug.
Rather than specifying the types in the description and todo_id in the UPDATE query, just passing them as strings work.
Also get rid of the single quotes from the query.
This is the updated async function:
req.on("end", async () => {
const data = JSON.parse(jsonData);
console.log([data["description"], urlId[1]]);
const updateTodo = await pool.query(
"UPDATE todo SET description = $1 WHERE todo_id = $2;",
[data["description"], urlId[1]]
);
res.setHeader("Content-Type", "application/json");
res.write(JSON.stringify("Todo was updated!"));
res.end();
});
I also got rid of the RETURNING statement from the query.
This seem to resolve the issue for me.

Long running Node REST API takes much time to respond

I have a Rest API in node.js that takes much time to respond because it sends a request to suppliers vendor and once the response is fully prepared then it returns the result what I want is as the result is being prepared it should be able to display it on the front react side. Thanks in advance for any help and your time
here is my controller
module.exports.search = async (req, res) => {
try {
let params = req.query;
params = _.extend(params, req.body);
const result = await modules.Hotel.Search.search(req.supplierAuth, params);
res.json(result);
} catch (e) {
global.cli.log('controller:hotels:search: ', e);
res.status(500).json({ message: e.message });
}
};
here is my front side service
export const getHotels = (filters, options = {}) => {
const queryString = new URLSearchParams(options).toString();
return post(`/api/hotels/search?${queryString}`, filters);
};
The best solution is to use streams and pipe() the results as they come into express's res object, similar to this guy's approach.
You'll have to modify the modules.Hotel.Search.search(....) and make that use streams.

Append a query param to a GET request?

I'm trying to make a simple API that calls another API that will return some information. The thing is, in order to connect to the second API, I need to attach query parameters to it.
So what I've tried to do so far is to use an axios.get in order to fetch the API. If I didn't need to add queries on top of that, then this would be really simple but I'm having a really hard time trying to figure out how to attach queries on top of my request.
I've created an object that pulled the original query from my end and then I used JSON.stringify in order to turn the object I made into a JSON. Then, from my understanding of Axios, you can attach params my separating the URL with a comma.
On line 6, I wasn't sure if variables would carry over but I definitely can't have the tag var turned into the string "tag", so that's why I left it with the curly brackets and the back ticks. If that's wrong, then please correct me as to how to do it properly.
the var tag is the name of the query that I extracted from my end. That tag is what needs to be transferred over to the Axios GET request.
app.get('/api/posts', async (req, res) => {
try {
const url = 'https://myurl.com/blah/blah';
let tag = req.query.tag;
objParam = {
tag: `${tag}`
};
jsonParam = JSON.stringify(objParam);
let response = await axios.get(url, jsonParam);
res.json(response);
} catch (err) {
res.send(err);
}
});
response is SUPPOSED to equal a JSON file that I'm making the request to.
What I'm actually getting is a Error 400, which makes me think that somehow, the URL that Axios is getting along with the params aren't lining up. (Is there a way to check where the Axios request is going to? If I could see what the actual url that axios is firing off too, then it could help me fix my problem)
Ideally, this is the flow that I want to achieve. Something is wrong with it but I'm not quite sure where the error is.
-> I make a request to MY api, using the query "science" for example
-> Through my API, Axios makes a GET request to:
https://myurl.com/blah/blah?tag=science
-> I get a response with the JSON from the GET request
-> my API displays the JSON file
After looking at Axios' README, it looks like the second argument needs the key params. You can try:
app.get('/api/posts', async (req, res, next) => {
try {
const url = 'https://myurl.com/blah/blah';
const options = {
params: { tag: req.query.tag }
};
const response = await axios.get(url, options);
res.json(response.data);
} catch (err) {
// Be sure to call next() if you aren't handling the error.
next(err);
}
});
If the above method does not work, you can look into query-string.
const querystring = require('query-string');
app.get('/api/posts', async (req, res, next) => {
try {
const url = 'https://myurl.com/blah/blah?' +
querystring.stringify({ tag: req.params.tag });
const response = await axios.get(url);
res.json(response.data);
} catch (err) {
next(err);
}
});
Responding to your comment, yes, you can combine multiple Axios responses. For example, if I am expecting an object literal to be my response.data, I can do:
const response1 = await axios.get(url1)
const response2 = await axios.get(url2)
const response3 = await axios.get(url3)
const combined = [
{ ...response1.data },
{ ...response2.data },
{ ...response3.data }
]

NodeJs: can't write a file

I'm new in node, for practice i thought to develop a weather commandline application, but i found a problem with ajax request, i'm usually to use $.ajax of jquery but it doesn't works, ( I've tried to require jquery ). I've solved this problem with another module.
Now the problem is: when i try to print json information on the coords.json and next read it with read-json module there are some "\" & "\n" everywhere in the string, i've tried to replace it with regex and fs module but it doesn't re-write the file... why?
Here the full code:
// index.js
// modules
const program = require('commander');
const clear = require('clear');
const chalk = require('chalk');
const request = require('ajax-request');
const fs = require('fs');
const json = require('read-data').json;
const writeJson = require('write-json');
// Forecast.io Key
const key = "*************";
const freegeoip = "http://freegeoip.net/json/";
let latitude = 0,
longitude = 0 ;
// forecast.io api url
const url = `https://api.darksky.net/forecast/${key}/${latitude},${longitude}`;
// initialize myData with the freegeoip datas
let myData = request({
url: 'http://freegeoip.net/json/',
method: 'GET',
data: {
format: 'json'
},
}, function(err, res, body) {
writeJson('test.json', body, function(err) {
if (err) console.log(err);
});
});
fs.readFile('test.json', 'utf8', function (err,data) {
let result = data.replace(/[\\~#%&*<>?|\-]/g, '');
fs.writeFile('test.json', result, 'utf8', function (err) {
if (err) return console.log(err);
// if i do this is normal json
// console.log(result)
});
});
and the output in the file is:
// coords.json
"{\"ip\":\"**.**.**.**\",\"country_code\":\"IT\",\"country_name\":\"Italy\",\"region_code\":\"62\",\"region_name\":\"Latium\",\"city\":\"Rome\",\"zip_code\":\"00119\",\"time_zone\":\"Europe/Rome\",\"latitude\":**.*,\"longitude\":**.**\"metro_code\":0}\n"
but if i print it in console it's normal...
I really recommend that you use JSON.parse. It will parse your json and put it into a variable you can use:
fs.readFile('test.json', 'utf8', function (err,data) {
data = JSON.parse(data); // Yay you can use anything from the JSON
}
The \ are there to escape the quotes so that they don't end the string. They shouldn't affect anything, and are actually necessary. Have you tried it without the regex? That could be breaking things if it actually removes the .

Categories

Resources