In my MongoDB/Node backend I have a pretty standard function for adding a new language to the database via a POST request. It looks like this:
exports.add = async function(req, res) {
let request, doc;
request = new EndpointRequestController(req, res);
try {
doc = await request.save(Language, req.body);
} catch(err) {
return request.sendError('An error occurred while trying to find existing records.', err);
}
request.sendResponse(doc, res.status(201));
}
Currently, this is working - in that when the user passes a value in the body of the POST request, the new language is added to our languages collection.
What I'm trying to figure out is, why is this returning a "204" response, rather than the "201" status I'm explicitly sending here as part of the response? How can I edit this to send the "201" response?
You are sending response outside the await function... you need to put res.send inside await function
exports.add = async function(req, res) {
let request, doc;
request = new EndpointRequestController(req, res);
try {
doc = await request.save(Language, req.body);
res.status(201).send(doc)
} catch(err) {
return request.sendError('An error occurred while trying to find existing records.', err);
}
}
Related
This is a course quiz and this is the most basic information I need in order to create a React app. But while the endpoint URL is correct, the page "/products" returns a "400" error when I try to request the product list. The instructions I'm given are:
Obtain a list of products with
Route: /products
Body: Array
method: POST
{
"product-codes": [
"98798729",
"84876871",
"29879879",
]
}
My index.js
...
app.post(`/products`, async (req, res) => {
try {
const response = await axios.post(`${apiURL}/products`);
// console.log(response.data);
res.status(200).json(response.data);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
in Postman
I use http://localhost:4000/products
and pass a Body / Raw /JSON:
{
"product-codes": [
"98798729",
"84876871",
"29879879",
]
}
But I can't get in! I am not seeing something obvious because this is the entry point to a very long and complex quiz. Thanks
What I see from the code is a recursive long call.
app.post(`/products`, async (req, res) => {
try {
const response = await axios.post(`${apiURL}/products`); // calling the same end point
// console.log(response.data);
res.status(200).json(response.data);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
You should do something like this:
app.post(`/products`, async (req, res) => {
// do your logic
// when you pass body from postman on this endpoint
// you will receive the body here and save it to DB
// or do the manipulation and then send back the response
res.status(200).json(req.body.data);
});
I highly recommend you to first follow through some tutorials to understand how API works and how to create simple API using Node.js.
I am trying to store the response of an http request made using nodejs by request module but the problem is I can't acsess it after the request is completed in more details we can say after the callback
How I can add it
Here is what I tried till now
Tried to use var instead of let
Tried passing it to a function so that i can use it later but no luck
Here is my code can anyone help actually new to nodejs that's why maybe a noob question
var request = require('request')
var response
function sort(body) {
for (var i = 0; i < body.length; i++) {
body[i] = body[i].replace("\r", "");
}
response = body
return response
}
request.get(
"https://api.proxyscrape.com/?request=getproxies&proxytype=http&timeout=10000&country=all&ssl=all&anonymity=all",
(err, res, body) => {
if (err) {
return console.log(err);
}
body = body.split("\n");
sort(body);
}
);
console.log(response)
In this I am fetching up the proxies from this api and trying to store them in a variable called as response
var request = require("request");
var response;
async function sort(body) {
await body.split("\n");
response = await body;
console.log(response); // this console log show you after function process is done.
return response;
}
request.get(
"https://api.proxyscrape.com/?request=getproxies&proxytype=http&timeout=10000&country=all&ssl=all&anonymity=all",
(err, res, body) => {
if (err) {
return console.log(err);
}
sort(body);
}
);
// console.log(response); //This console log runs before the function still on process, so that's why it gives you undefined.
Try this code it works fine I just tested.
put the console log inside the function so you can see the result.
The console.log that you put actually runs before you process the data so that's why you are getting "undefined".
Actually, you will get the data after the sort Function is done processing.
I'm currently designing a oauth login system and I've encountered the following problem. I'm trying to redirect users back to the homepage once they have been logged in and session data has been set, but the res.redirect('/') throws NodeError: Cannot set headers after they are sent to the client. I cannot seem to get it to work. Below is the code which is causing the fault:
app.post(
"/auth/openid/return",
passport.authenticate("azuread-openidconnect", {
failureRedirect: "/login"
}),
function(req, res) {
let userProperties = req.user;
new Promise((resolve, reject) => {
MongoClient.connect(url, function(err, db) {
if (err) next(err);
let dbo = db.db("Lektier");
let query = {
oid: req.user.oid
};
dbo.collection("users").findOne(query, function(err, result) {
db.close();
if (result) {
let type = result.type;
resolve(type);
}
});
});
}).then(type => {
req.session.regenerate(function() {
req.session.user = userProperties.upn;
if (type == "teacher") {
req.session.teacheruser = userProperties.upn;
}
let names = userProperties.displayName.toString().split(" ");
req.session.FirstName = names[0];
req.session.LastName = names[1];
res.redirect("/");
});
});
}
);
Some help on the matter would be appreciated.
Whenever you see a message like this Cannot set headers after they are sent to the client, it means that the logic of your endpoint tried to send a response to the client and failed, because it actually already responded. res.redirect() of express actually sends some 3xx http status to the client and if you are saying that this method throws the error you're facing, something before it already sent a response.
I didn't find anything that could respond in the snippet you provided (besides the very res.redirect()), so I suggest you to look into your middleware. For example into passport authentication, since it is mentioned here.
I am trying to create a simple REST API with NodeJS and Express without any database. I have stored all of my data in JSON files.
The data is in the form of an array of objects.
I have paths like fund-name/:portId
so I am doing this:
const fundName = require('./json/fund-name.json');
app.get('/fund-details:portId', (req, res) => {
const portId = req.params.portId;
fundDetails.forEach(fund => {
if (fund.portId === portId) {
return res.json(fund);
}
return res.json([]);
});
});
when I hit the url http:localhost:3000/fund-details/1234, I get the following error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (/home/username/Desktop/data-server/node_modules/express/l
ib/response.js:767:10)
It works fine when I don't pass any path param to get all the funds.
Where am I going wrong??
This error is because you are using res.send() multiple time in single api call.
Correct way
if(a){
res.send()
}else{
res.send()
}
Wrong way
if(a){
res.send()
res.send()
}else{
res.send()
}
In your code.
app.get('/fund-details:portId', (req, res) => {
const portId = req.params.portId;
fundDetails.forEach(fund => {
if (fund.portId === portId) {
return res.json(fund); // many or single times here
}
return res.json([]); // and here when fund !==portId here
});
});
You can try
app.get('/fund-details:portId', (req, res) => {
const portId = req.params.portId;
var flag
var data = []
fundDetails.forEach(fund => {
if (fund.portId === portId) {
flag=true
data.push(fund)
}
});
if(flag){
res.send(data);
}else{
res.send()
}
});
The method res.json(fund) is called per each item in fundDetails and then a further res.json([]) method is called. This leads to your response being send back multiple times (which it shouldn't happen, only 1 response per a single api call should be used).
I suggest that you use an array and push back objects with the matching port id and then send the array back to the user when the operation is completed. To be honest, you don't even need the flag variable to check if funds exists or not since if they don't, you empty data array is sent back.
var data = [];
fundDetails.forEach(fund => {
if (fund.portId === portId)
data.push(fund);
});
res.json(data);
I've been trying to get the uber price estimates endpoint working, but I'm stuck on an error that leads me to a blank page saying, "Bad Request." The console also says "callback not a function" but I can't seem to find out what is wrong.
My route:
// Get an upfront fare before requesting a ride
app.get('/v1.2/estimates/price', function(request, response) {
// extract the query from the request URL
var query = request.query;
// if no query params sent, respond with Bad Request
if (!query || !query.lat || !query.lng) {
response.sendStatus(400);
} else {
uber.estimates.getPriceForRouteAsync( {
"product_id": "33de8094-3dc4-4ca9-8f67-243275f57623",
"start_latitude": "38.9597897",
"start_longitude": "-94.60699369999999",
"end_latitude": "39.010969",
"end_longitude": "-94.61509899999999"
})
.then(function(res) {
log(res);
})
.error(function(err) {
console.error(err);
});
}
});
Any help is appreciated.
Please check out the README for node-uber. The method does not take a JSON object but the arguments in the method call:
uber.estimates.getPriceForRouteAsync(38.9597897, -94.606994, 39.010969, -94.615098)
.then(function(res) { console.log(res); })
.error(function(err) { console.error(err); });
Also, the product ID is not needed as the /estimates/price endpoint returns an array of estimates for each product.