Node.js same uri but different parameters - javascript

I'm doing a simple library API with Node.js and express. To fetch a specific book with ISBN or books within a specific genre, I have the following functions:
/api/books/isbn
router.get('/:isbn', function (req, res)
{
var isbn = req.params.isbn
})
/api/books/query
router.get('/:genre', function (req, res)
{
var genre = req.params.isbn
})
So first of all, this will not work because it will only go to the first function regardless of what the input is. Another thing I tried and that worked, was to make only one function that extracts the query parameters:
router.get('/', function (req, res)
{
var isbn = req.query.isbn
var genre = req.query.genre
})
Using this approach I could get the different values by doing calls like /api/books?genre=Adventure or /api/books?isbn=1231230912
But I feel it would make more sense to do it the first way, i.e /api/books/adventure or /api/books/isbn.
So, which way is the 'right' way? And if it's the first one, how can I design the functions so that they can extract the right values?

I think the second approach you tried should also be ok.
However, if you asked me to do this. I will create below apis:
/api/books/genre/Adventure
/api/books/isbn/1231230912
This helps to have clear distinctions between the apis and makes them maintainable and readable for future.
To save the time of writing 2 route handlers, you can write only one route handler function and pass either genre or isbn as parameter.

Try using one route, and by trying to parse the parameter to a number you can check if it's an isbn or genre.
If NaN then genre else isbn

You could do like so :
// /api/
router.get('/isbn/:isbn', function (req, res)
{
var isbn = req.params.isbn
})
// /api/books/query
router.get('/genre/:genre', function (req, res)
{
var genre = req.params.genre
})
This will work and this is the most used format.
And if you wan't to have only one uri then do like so :
// /api/books/isbn
router.get('/', function (req, res)
{
var isbn = req.query.isbn
var genre = req.query.genre
if (isbn)
res.redirect('/isbn/' + isbn);
else if (genre)
res.redirect('/genre/' + genre);
})

Related

Object of which I have a working method for is somehow undefined? Javascript app.patch request [duplicate]

I am trying to create two routes in my express app. One route, without a parameter will give me a list of choices, the other one with a parameter will give me the choice related to the id.
router.get('/api/choice', choice_controller.get_choices);
router.get('/api/choice/:id', choice_controller.get_choice);
When I go to .../api/choice/?id=1 the api returns the list of choices, and therefore follows the route without the param (/api/choice). How do I make sure that the router does not omit the parameter?
Thanks in advance.
UPDATE
It seems that it does not fire the /api/choice/:id route. If I remove the one without the param, it gives a 404 so. Could someone explain to me why /api/choice/?id=1 is not getting picked up by /api/choice/:id?
Basically, your declared routes are documented in the Express documentation.
The second route is resolved by a URL like /api/choice/hello where 'hello' is mapped into the req object object as:
router.get('/api/choice/:id', function (req, res) {
console.log("choice id is " + req.params.id);
});
What you are actually trying is mapping query parameters.
A URL like /api/choice/?id=1 is resolved by the first router you provided.
Query parameters are easy to get mapped against the request as:
router.get('/api/choice', function (req, res) {
console.log('id: ' + req.query.id);
//get the whole query as!
const queryStuff = JSON.stringify(req.query);
console.log(queryStuff)
});

Steam API Request Failed [duplicate]

I am trying to create two routes in my express app. One route, without a parameter will give me a list of choices, the other one with a parameter will give me the choice related to the id.
router.get('/api/choice', choice_controller.get_choices);
router.get('/api/choice/:id', choice_controller.get_choice);
When I go to .../api/choice/?id=1 the api returns the list of choices, and therefore follows the route without the param (/api/choice). How do I make sure that the router does not omit the parameter?
Thanks in advance.
UPDATE
It seems that it does not fire the /api/choice/:id route. If I remove the one without the param, it gives a 404 so. Could someone explain to me why /api/choice/?id=1 is not getting picked up by /api/choice/:id?
Basically, your declared routes are documented in the Express documentation.
The second route is resolved by a URL like /api/choice/hello where 'hello' is mapped into the req object object as:
router.get('/api/choice/:id', function (req, res) {
console.log("choice id is " + req.params.id);
});
What you are actually trying is mapping query parameters.
A URL like /api/choice/?id=1 is resolved by the first router you provided.
Query parameters are easy to get mapped against the request as:
router.get('/api/choice', function (req, res) {
console.log('id: ' + req.query.id);
//get the whole query as!
const queryStuff = JSON.stringify(req.query);
console.log(queryStuff)
});

Error with get request for users

When using a get request for all the users in my database (see code below) i only get the "first" user in the database. If i instead try to use the "findOne"-method i get the same user as before no matter what i put in (the username doesn't even have to be in the db it still gives me the same user). I've been trying to understand why this isn't working but can't find any problems with the code. Could it be a problem with db settings or something similar? All help is appreciated!
In AuthController:
// Get all users
AuthController.allusers = function(req, res) {
User.find({}, function(err, users) {
}).then(function(users) {
res.json({users: users});
});
}
In routes:
// GET Routes.
router.get('/users', AuthController.allusers);
Since you are using Sequelizejs, you might want to do findAll.
AuthController.allusers = function(req, res) {
User.findAll().then(function (users) {
res.send({users: users});
}
}
According to the docs:
find - Search for one specific element in the database
findAll - Search for multiple elements in the database

How to put the url to let user filter

I have a quick question and kind find a good solution for it. I basically want to filter my contacts by name, but I want the user to put the filter like this in the URL: /contacts/name=Jonny.
How can I place the URL on the routes?
I did this:
router.get('/contatos?nome',function(req,res){
});
I want to let the user filter for something else, like number and so he get all the contacts with the specific number like this /contacts/number=9123123. I want to use the same route for that how can I do that?
You can use params
router.get('/contacts/:name', (req, res, next) => {
// you can read name here
let name = req.params.name.split('=')[1];
});
I'd recommend doing router.get('/contacts/number=(\\d+))') and then use req.params[0]

How to Get QueryString in Node/Express?

How can I send/get the querystring from one page to another?
I am using: node version v0.12.3000 express 3.20.3
I am trying this way:
page1.js
function p1(req, res){
res.render('page1');
};
exports.p1= p1;
exports.post_enviar = function(req, res){
var param1 = req.body.param1;
res.render('page2', { param1 });
}
page2.js
function p2(req, res){
res.render('page2');
};
exports.p2= p2;
exports.get_enviar = function(req, res){
var param1 = req.params.param1;
console.log("param1: "+param1);
}
Thanks!
Short answer: you can't do that.
Long(er) answer: what you're trying to do involves either queuing a message in one route handler that would be consumed by another route, or otherwise simply sharing state between them.
The post_enviar export is stateless. It doesn't reference any data outside itself.
To demonstrate: (warning, don't do this)... If you had two modules for route controllers like this:
// route1controller.js
var lastQuery = {};
module.exports.route1controller = function (req, res, next) {
lastQuery = req.params;
res.render(...);
}
module.exports.lastQuery = lastQuery;
and
// route2controller
var lastQuery = require('./path/to/route1controller').lastQuery;
module.exports.route2controller = function (req, res, next) {
res.send(lastQuery);
}
Then the page rendered by route2controller will get the object (or array) of parameters that was last sent in a request to the route1controller. This is just a crude way of sharing state between the two controllers, and you really don't want to do this. Consider a more manageable solution, like logging (writing to a flat file, or database) requests to a given route, and then parsing them in a human readable way on another page.
If you're looking to get real-time information on one page about requests to another page, you'll need to look into more sophisticated solutions like websockets, or a polling for current data.

Categories