Route parameters in Express JS - javascript

I am using Express JS to handle a route http://localhost:3000/location which allows a mix of parameters and fixed endpoints. For example:
http://localhost:3000/location is the root for the route, which renders a view for a list of locations.
http://localhost:3000/location/map renders a view for a list of the locations drawn on a web map.
http://localhost:3000/location/:id contains a parameter for the ID of a location given in the URL and when called, renders a view for the details of the given location that comes from a database query.
'use strict';
var path = require('path');
var express = require('express');
var router = express.Router();
/* GET route root page. */
router.get('/', function(req, res, next) {
// DO SOMETHING
});
/* GET the map page */
router.get('/map', function(req, res, next) {
// DO SOMETHING
});
/* GET individual location. */
router.get('/:id', function(req, res, next) {
// DO SOMETHING
});
module.exports = router;
Is this a best practise for handling a route with mixed fixed values and parameterized parameters?
More specifically, how to properly handle the problem that when I called "http://localhost:3000/location/SOMETHINGWRONG", for example, http://localhost:3000/location/:id was triggered which led to a database query error because "SOMETHINGWRONG" was not an integer and could not pass?

You can restrict a rule with regex in your route, for example, if you only expect to receive whole numbers, you can use something like this:
router.get('/:id(\\d{12})', (req, res) => {
//...
});
Enter the method if you meet the rule, where "id" is a number with 12 characters
Validate only numbers:
app.get('/:id(\\d+)', function (req, res){
//...
});

To have more control over the exact string that can be matched by a route parameter, you can append a regular expression in parentheses (()).
ex: Your Id is an integer with a maximum length of 10 characters
/* GET individual location. */
router.get('/:id([0-9]{1,10})', function(req, res, next) {
// DO SOMETHING
});

Related

Express.js - Allow infinite subroutes, but at least one

I want to allow any subroute after /example/....
Example of valid URLs:
/example/one
/example/one/two
/example/one/two/three
But doing this:
server.get('/example/*', (req, res) => {
// ...
})
Is also allowing /example without any subroute. And I want to avoid this. How can I do it? Is there any way without using regex?
Thank you so much!
You could simply define two routes - one for /example and another for all /example-subroutes, you need to make sure the order is correct though:
app.get('/example', (req, res) => {
// render default page
});
app.get('/example/*', (req, res) => {
// do other stuff
});

Issue with multiple routes in one file - only two out of three work, the last one won't work

I'm working on making an API using express and MySQL. I'm having issues with my routes. I have it in a separate folder, requiring the different controller files and exporting the router at the end. Here's the issue. The last router.get function will not work. I can swap it and whatever is last will not work. I'll get back an empty array. I'm at a loss as to what can be wrong. Here's my code, the routes file:
const express = require('express');
const router = express.Router();
const getEmployeesController = require('../controllers/getEmployees');
const getEmployeesByIdController = require('../controllers/getEmployeesById');
const getEmployeesByFirstNameController = require('../controllers/getEmployeesByFirstName');
router.get('/', getEmployeesController.getEmployees);
router.get('/:id', getEmployeesByIdController.getEmployeesById);
router.get('/:first_name', getEmployeesByFirstNameController.getEmployeesByFirstName);
module.exports = router;
The 'first_name' router worked when it was second, after the '/', but now it won't. Same with the 'id', worked when its second, but not when it's third.
Here's the controller function, one as an example:
const mysql = require('mysql')
const pool = require('../mysql/connection')
const { handleSQLError } = require('../mysql/error')
const getEmployeesById = (req, res) => {
let sql = "SELECT ?? FROM ?? WHERE ?? = ?"
sql = mysql.format(sql, ['*', 'employees', 'emp_no', req.params.id])
pool.query(sql, (err, rows) => {
if (err) return handleSQLError(res, err)
return res.json(rows);
})
}
module.exports = { getEmployeesById };
/:first_name and /:id match the exact same URLs so only the first one you register is going to get all the matching URLs. They both match /anything.
You really can't define routes like that. There's no way Express knows which route handler you want to use with /anything is the requested URL.
Instead, you need to define a route structure where those two types of URLs are different and you can design a route handler that will uniquely catch each one. I personally don't ever use top level wildcard routes like this because they match every top level URL and they prohibit you using top level URLs for any other purpose in your site.
Instead, you might change your URL design to do this:
router.get('/id/:id', ...)
router.get('/firstname/:firstname', ...);
Then, it would be completely clear from the URL what type of resource was being requested and each route would match only the appropriate URLs.

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 read parameters from URL in a specific way with express JS

I created a server with the express package, and I'm trying to read in a specific way the parameters from the URL.
The URL goes like this: http://127.0.0.1:8080/screen=3 (no '?' as the sign for parameters).
I need to save the number of the screen in a variable.
I tried this:
var express = require('express');
var app = express();
app.get('/screen:sceenNum', function (req, res) {
var temp = req.sceenNum;
res.send(temp); //for checking on the browser
});
I also tried this, but he must get '?' in the URL:
app.get('/', function(req, res) {
var screenNum = req.param('screen');
res.send(screenNum);
});
Can anyone please have a solution?
Thank you
You can access route/url parameters with the req.params object.
So a route like /screen:screenNum would accept urls like /screen3 and you would access 3 via req.params.screenNum.
Similarly, if you want to use the equals, just add that: /screen=:screenNum and the number is accessed the same.

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