code for tour.route.js :
app.get(tour_controller.getTourById)
tour_controller.js
getTourById = handler.getOne(TourModel);
handler.js
exports.getOne = (Model, popOptions) => {
catchAsync(async (req, res, next) => {
let query = Model.findById(req.params.id);
if (popOptions) {`your text`
query = query.populate(popOptions);
}
const docs = await query;
if (!docs) {
return next(
new apiError('No documents found with ID: ' + req.params.id, 404)
);
}
res.status(200).json({
status: 'succeed!',
data: docs,
});
});
};
problem that displays during npm start
I stuck here,
the same thing works for .post, .patch and .delete method but it shows error for .get method
You forgot to return
exports.getOne = (Model, popOptions) => {
return catchAsync(async (req, res, next) => {
// ...
});
};
Related
I am trying to pass data from one middleware to another. The data is then returned to the client in the next middleware. I, however, am unable to catch it in the send.call.
How can I catch the data and send it?
Thank you all in advance.
const myPreMiddleware = async (req, res, next) => {
req.myData = myData;
next();
};
const myPostMiddleware = (req, res, next) => {
let send = res.send;
res.send = async function (body) {
send.call(this, req.myData); // The data i NOT accessible here
};
console.log("req.myData : " + JSON.stringify(req.myData)); // The data is accessible here
next();
};
app.use(myPreMiddleware);
app.use(myPostMiddleware);
Try pass the variable that you want to pass to the next() callback
here some example that will hopefully help
function notFound(req, res, next) {
res.status(404);
const error = new Error(`Not Found - ${req.originalUrl}`);
next(error);
}
function errorHandler(err, req, res, next) {
const statusCode = res.statusCode !== 200 ? res.statusCode : 500;
res.status(statusCode);
res.json({
message: err.message
});
}
app.use(notFound);
app.use(errorHandler);
I'm following an tutorial where i am supposed to consume an mongoose API using express and display location information to the view. However I am getting an 404 error on the front end everytime i click the button that calls the API request. The source code for this tutorial can be found here. https://github.com/cliveharber/gettingMean-2/tree/chapter-07
Here is the API request handler on the server side:
const getLocationInfo = (req, res, callback) => {
const path = `/api/locations/${req.params.locationid}`;
const requestOptions = {
url: `${apiOptions.server}${path}`,
method: 'GET',
json: {}
};
request(
requestOptions,
(err, {statusCode}, body) => {
const data = body;
if (statusCode === 200) {
data.coords = {
lng: body.coords[0],
lat: body.coords[1]
}
callback(req, res, data);
} else {
showError(req, res, statusCode);
}
}
);
};
const locationInfo = (req, res) => {
getLocationInfo(req, res,
(req, res, responseData) => renderDetailPage(req, res, responseData)
);
};
The Render handler of the page i am trying to reach:
const renderDetailPage = (req, res, location) => {
res.render('location-info',
{
title: location.name,
pageHeader: {
title: location.name,
},
sidebar: {
context: 'is on Loc8r because it has accessible wifi and space to sit down with your laptop and get some work done.',
callToAction: 'If you\'ve been and you like it - or if you don\'t - please leave a review to help other people just like you.'
},
location
}
);
};
This is the Mongoose API controller that retrieves the location data from the database:
const locationsReadOne = (req, res) => {
Loc
.findById(req.params.locationid)
.exec((err, location) => {
if (!location) {
return res
.status(404)
.json({
"message": "location not found"
});
} else if (err) {
return res
.status(404)
.json(err);
}
res
.status(200)
.json(location);
});
};
This is the express routing code:
const express = require('express');
const router = express.Router();
const ctrlLocations = require('../controllers/locations');
const ctrlOthers = require('../controllers/others');
router.get('/', ctrlLocations.homelist);
router.get('/locations/:location._id', ctrlLocations.locationInfo);
And finally this is a snippet of the Pug code that contains the button which calls the get request to retrieve the location id:
each location in locations
.card
.card-block
h4
a(href=`/locations/${location_id}`)= location.name
+outputRating(location.rating)
span.badge.badge-pill.badge-default.float-right= location.distance
p.address= location.address
.facilities
each facility in location.facilities
span.badge.badge-warning= facility
Let me know if i need to provide additional information. Appreciate any help.
I'm having some problems using 2 middlewares inside the same function, already tried to search for all internet and didn't find a useful solution.
validator file
module.exports = {
create: async (req, res, next) => {
await celebrate(options.create)(req, res, next);
return res.status(500).json({ message: 'middleware 2'});
},
}
routes file
routes.post('/user', UserValidator.Create ,UserController.create);
The celebrate lib filters some basic validations like string lenght, null values, etc. And the celebrate() function returns another function with the (req, res, next) params.
When the celebrate returns the validation error, it stills continues to execute the code, so it tries to execute the next return and I get an error because the return has already been sent.
When using separate middlewares in the routes, it works normally:
routes.post('/user', celebrate(...), middleware2 ,UserController.create);
I also tried this way but the same thing happens, but now without an error, just returning the middleware2 result.
module.exports = {
create: async (req, res, next) => {
await celebrate(options.create)(req, res, () => {
return res.status(500).json({ message: 'middleware 2'});
});
},
Is there a way to fix this?
u should try this structure
// API
app.post('/something', Middleware.validate, Controller.create)
//Middleware
const validate = (req, res, done) => {
const errorArray = []
const body = req.body
// identifier is required, Validating as String, and length range.
if (!_.isString(body.identifier) || body.identifier.length < 2 || body.identifier.length > 10) {
errorArray.push({
field: 'identifier',
error: 70000,
message: 'Please provide only valid \'identifier\' as string, length must be between 2 and 10.'
})
}
if (!_.isEmpty(errorArray)) {
return errorArray
}
done()
}
module.exports = {
validate
}
// Controller
const create = function (req, res) {
return // your functionality
}
module.exports = {
create
}
I am working on firebase api for realtime database, I am using async await, but it is not working for that i have used try catch in node js, I can see i am getting status 0, so it invokes catch, but in catch i am getting error as null object, can anyone please help me why i am not getting proper error in that ? even my try code is correct still it invokes catch, here i have added my whole code, can anyone please look in my code, and help me to resolve this error ? i am getting this response,
Response :
{"status":0,"data":{}}
API :
export const check_await = functions.https.onRequest(async (req, res) => {
try {
if (req.method === 'POST') {
const body_data = req.body;
const db = admin.database();
const org_id = body_data.company_id;
const highfive_id = body_data.highfive_id;
const ref = db.ref("organizations/" + org_id + "/highfive/" + highfive_id);
const snapshot = await ref.on("value");
const data = snapshot.val();
cors(req, res, () => { return res.send({ 'status': 1, 'data': data, 'msg': 'High five feed record get successfully' }); });
} else {
cors(req, res, () => { return res.send({ 'status': 0, 'msg': "Only POST method is allowed" }); });
}
} catch (error) {
cors(req, res, () => { return res.send({ 'status': 0, 'data': error }); });
}
});
Finally i resolved the issue, i need to use once instead of on, here is my full code of it,
export const check_await = functions.https.onRequest(async (req, res) => {
try {
if (req.method === 'POST') {
const body_data = req.body;
const db = admin.database();
const org_id = body_data.company_id;
const highfive_id = body_data.highfive_id;
const ref = db.ref("organizations/" + org_id + "/highfive/" + highfive_id);
const snapshot = await ref.once("value");
const data = snapshot.val();
cors(req, res, () => { return res.send({ 'status': 1, 'data': data, 'msg': 'High five feed record get successfully' }); });
} else {
cors(req, res, () => { return res.send({ 'status': 0, 'msg': "Only POST method is allowed" }); });
}
} catch (error) {
cors(req, res, () => { return res.send({ 'status': 0, 'data': error.message }); });
}
});
I have myRoute.js with a route (GET) defined and I want to call an api endpoint from another route (api.js), and I'm not sure what the right way to do this is. The api.js route is working properly (image and code below).
api.js
router.get('/getGroups/:uid', function(req, res, next) {
let uid = req.params.uid;
db.getAllGroups(uid).then((data) => {
let response =[];
for (i in data) {
response.push(data[i].groupname);
}
res.status(200).send(response);
})
.catch(function (err) {
return err;
});
});
works as expected:
myRoute.js
I would like when a user goes to localhost:3000/USER_ID that the route definition gets information from the api. Psuedo code below (someFunction).
router.get('/:uid', function(req, res, next) {
let uid = req.params.uid;
let fromApi = someFunction(`localhost:3000/getAllGroups/${uid}`); // <--!!!
console.log(fromApi) ; //expecting array
res.render('./personal/index.jade', {fromApi JSON stringified});
});
Not sure if i understand you correct but anyway i will try to help. So you have an api like
router.get('/getGroups/:uid', function(req, res, next) {
let uid = req.params.uid;
db.getAllGroups(uid).then((data) => {
let response =[];
for (i in data) {
response.push(data[i].groupname);
}
res.status(200).send(response);
})
.catch(function (err) {
return err;
});
});
If you would like to reuse it you can extract a function from the code above like so:
async function getAllGroupsByUserId(uid){
const result = [];
try{
const data = await db.getAllGroups(uid);
for (i in data) {
result.push(data[i].groupname);
};
return result;
}
catch(e) {
return e;
}
}
And then reuse it in your api & anywhere you want:
router.get('/getGroups/:uid', async function(req, res, next) {
const uid = req.params.uid;
const groups = await getAllGroupsByUserId(uid);
res.status(200).send(groups);
})
Same you can do in your another route:
router.get('/:uid', async function(req, res, next) {
const uid = req.params.uid;
const fromApi = await getAllGroupsByUserId(uid); // <--!!!
console.log(fromApi) ; //expecting array
res.render('./personal/index.jade', {fromApi JSON stringified});
});
Seems like pretty clear :)
I would use fetch for this. You can replace someFunction with fetch, and then put the res.render code in a .then(). So, you would get this:
const fetch = require("node-fetch");
router.get('/:uid', function(req, res, next) {
let uid = req.params.uid;
fetch('localhost:3000/getAllGroups/${uid}').then(res => res.json()).then(function(data) {
returned = data.json();
console.log(returned); //expecting array
res.render('./personal/index.jade', {JSON.stringify(returned)});
});
});
A more robust way with error handling would be to write something like this:
const fetch = require("node-fetch");
function handleErrors(response) {
if(!response.ok) {
throw new Error("Request failed " + response.statusText);
}
return response;
}
router.get('/:uid', function(req, res, next) {
let uid = req.params.uid;
fetch('localhost:3000/getAllGroups/${uid}')
.then(handleErrors)
.then(res => res.json())
.then(function(data) {
console.log(data) ; //expecting array
res.render('./personal/index.jade', {JSON.stringify(data)});
})
.catch(function(err) {
// handle the error here
})
});
The ideal way would be to abstract your code into a method so you aren't calling yourself, as The Reason said. However, if you really want to call yourself, this will work.