Get user by query string in Nodejs - node.js

I'm trying to get user by id or by some parameters but the response always be all the users. I use the get method without any query just the test api without any authentication.
code :
router.get('/:id', async (req, res) => {
const user = await User.findById(req.query.id);
if (!user)
return res.status(404).send("The user with the given ID was not found.");
res.send(user);
});
url: http://localhost:4000/api/user?id=5e6e8159fd64bf27042a8838
the response always get all user
any help plz

#main.c is right. What you want to do is req.params.id,
req,query is used when you need to extract query properties like
/:id?sort=asc&discount=50
Then you can do req.query.sort or req.query.discount

What I can understand from your code is your route looks like router.get('/:id').
This means the URL should be something like /user/{id}.
The URL you are firing which is /user?id={id} might not be hitting this route as it does not have {id} route param in it.
The actual URL that'd hit this route is -
http://localhost:4000/api/user/5e6e8159fd64bf27042a8838.
And the way you should read id is request.params.id
I suspect /user route is pointing to get all users API which is why you are getting all users in response.

Related

NodeJS/ExpressJS : Access URL of the post request

In a project I'm working on, I need to access the parameters of the url in the backend.
I tried this based on what I found on the internet, but it doesnt seem to work.
//url = "/getDocs?num=15"
router.get("/getDocs", function(req,res,next){
console.log(req.body.num);
res.redirect("/documents");
}
Please help
In url it seems you are using query string which can be accessed as: request.query.num
If you are passing only params in url like getDocs/:num value then it can be accessed as: request.params.num
Simple way of doing this is querying the req object with the property name:
router.get("/getDocs", function(req,res,next){
const name = req.query.name;
res.redirect("/documents");
}
If you sending as a part of route, you can use this:
router.get("/getDocs/:id", function(req,res,next){
const id = req.params.id;
res.redirect("/documents");
}
For more details check here.

What to do when NodeJS rest api is sendind status 404 while using parameters?

I am having a strange problem while writing my api. I am using Nodejs and express. The problem occurs when i try to use GET with parameters.
This is my routes code
router.get('/addFriends/:email', (req, res, next) =>{
const email = req.params.email;
UserSchema.find({email: email}, { "friendsPending.emailSender": 1, _id : 0}, (err, data) =>{
if(err){
res.status(404).send(err);
}else{
res.status(200).send(data[0]);
}
});
});
This is my call in Postman : /users/addFriends?email=a
When running this call, server returns 404 status. It happened even when i tested it with another get call.Any comments are appriciated, however other POST and GET calls work normally (they use body not parameters). Thanks
You mixed query params and url params. To make your example working, you need to use /addFriends/my-email#gmail.com instead of /users/addFriends?email=a.
If you need to send emails via query params (everything after ?) use req.query in your controller instead of req.params.email.
This route definition:
router.get('/addFriends/:email', ...);
expects a URL that looks like this:
/addFriends/someEmail
And, you would use req.params.email to refer to the "someEmail" value in the URL path.
Not what you are trying to use:
/addFriends?email=a
If you want to use a URL such as (a URL with a query parameter):
/addFriends?email=a
Then, you would have a route definition like this:
router.get('/addFriends', ...);
And, then you would refer to req.query.email in the route handler. Query parameters (things after the ? in the URL) come from the req.query object.
In Express, route definitions match the path of the URL, not the query parameters.
when you use /addFriends/:param you force the router to match any request tha have a part in path as :param.For example:
/users/addFriends/toFavorates // will **match**
/users/addFriends/toFavorates?email=a // will **match**
/users/addFriends?email=a // will **not** match
if you want to make :param as optional part of url path put a ? after it
/addFriends/:param?
it will tell express route that :param is an optinal part. See this question
express uses path-to-regexp for matching the route paths. read the documentation for more options

How to set Routes for APIs

I am building an API to manage meetups with nodeJS. I have build an endpoint with the route "/meetups/:id/" to fetch a specific meetup record by its id. And then I want to fetch all the upcoming meetup records and I tried to use "/meetups/upcoming/" but when I query it, I get the not found error (404). It seems like the second route is not recognised.
Here is the code defining the two routes
the request from postman
Any help on how can I handle that?
Thanks.
Route is '/api/v1/meetups/upcoming/all'. Move res.status outside the map function.
EDIT: you'll have to change the route which has to be different from api/v1/meetups/:id. Reason is when route '/api/v1/meetups/upcoming' is requested express sees it as the same route as before and takes 'upcoming' as the parameter.
app.get("/api/v1/meetups/upcoming/all", function(req, res) {
var today = new Date();
var upcomings = db.meetups.map(function(meetup) {
if(meetup.happeningOn > today) {
return meetup;
}
});
res.status(200).send({
status: 200,
data: upcomings
});
});
You need to move the res.status piece outside of the const upcomings definition.

Render a file along with username into the url after form was submitted using express

I have a nodeJS application which takes user information from a form and saves to a mongoDB database using mongoose.
example:
router.post('/', (req, res) => {
newUser.save()
}
I've seen other websites which updates the url after the form is submitted with what I guess is a query string of the user and adds to the end of the url.
Example: http://stackoverflow.com/profile/Jon%Doe
Not sure how to update a url with user information after the form was submitted.
I tried to render a file:
router.req('/', (req, res) => {
res.render('profile' + username) //username is a variable of the user
}
but that only looks for a url with a username. Thinking I have to update the ejs template files with the username somehow.
To change the URL after a form post, you would use res.redirect() to redirect the browser to a new URL. The browser will then request that new url and you would need to have a route for that new URL in order to return the desired page content.
router.post('/', (req, res) => {
// other code here to process form data
newUser.save(..., function(err) {
if (err) {
console.log(err);
res.sendStatus(500);
} else {
// build new URL here
res.redirect(newURL);
}
});
}
If you then want to display the username in the page that you redirect to, you would use an EJS template that has a place in it for the user name and you would fetch the username from wherever you put it in the URL and feed that to the res.render() for the template so that EJS would insert the user name in the proper place.
If you're doing some kind of login, then you may want to do the whole process differently. You may want to create a user session object (probably with express-session) on the server and keep the username in there so then anytime you want to render a page, the username can be fetched from the server-side session object rather than putting it in the URL. This is probably a bit more foolproof.

Hows should I structure middleware to verify an ID exists in an external service in a Node/Express app?

I've currently written middleware to verify an ID exists in an external services (Salesforce). I initially wrote it when it was a single use app, but now I'm trying to make it work with different routes, so I want it to be fairly generic.
I don't even know if middleware is the right way to go, or if I should just call the function before saving the specific form.
I've got a form where someone puts in some information about a project, and the salesforce ID. For background, the salesforce ID is actually an auto-increment number, and I need to convert that to the actual salesforce system ID before I use jsForce to create a new object linked to that ID.
My route looks like this:
router.post('/invoice/add', ensureLoggedIn, invoiceController.validateInvoice, catchErrors(sfdc.validateSFID), catchErrors(invoiceController.saveInvoice))
So, I've got a middleware that does this:
exports.validateSFID = async(req, res, next) => {
const salesforceProjectNumber = req.body.SF_Opportunity
const sfResult = await conn.search(`FIND ... long query`, (err, result) => {
if (err || result.searchRecords.length !== 1) {
req.flash('error', 'Unable to find a Salesforce Job with that ID number.')
console.error(`ERROR: ${req.user.displayName} errored when looking up job number ${salesforceProjectNumber}.`)
return result
}
})
if (sfResult.searchRecords.length > 0) {
req.body.salesforce_Opportunity_id = sfResult.searchRecords[0].Id //Create a generic variable to hold the salesforce opportunity so it works regardless of the custom object name
res.locals.Opportunity_Clean_Name = sfResult.searchRecords[0].Name
}
next()
}
The query rarely throws an error, but in this case, an error is basically returning !1 records.
When that happens, I want to flash a message on the screen saying the ID wasn't found, but keep the form filled in.
When an ID is found, I want to proceed to save it and NOT display the form fields anymore.
This middleware needs to work regardless of the form I'm using, I want to be able to pipe in the middleware from any form that might require a user to enter a salesforce job as a field.
Any thoughts on how best to handle it all?
You can use your middleware by using app.use() function
app.use((req, res, next) => {
// Every time a request has made, this middleware will fire
console.log('Howdy');
})

Resources