How do I convert Express query parameters back into a string? - string

Express is great with req.query and creating an object of the query parameters. In this case, I just want those query parameters as a string. This is how I did it:
router.get('/*', (req, res) => {
const { originalUrl } = req;
console.log(originalUrl.slice(originalUrl.indexOf('?')));
But, I was wondering if there was a more direct or declarative way to do this. Surely this is not too uncommon of a task?

new URL("s://" + req.url).search gives you the query parameters, including the leading ?.

Related

how to add query parameters to router.get

Environment: MEAN tech stack
Hi, I want to add a query parameter to my router.get but I'm not sure how to define it.
Works like this right now:
http://test.com/path1/path2/1
router.get('/path1/path2/:userId', (req, res) => {
let route = `GET /path1/path2/${req.params.userId}`;
I just want to add a search query parameter, would it be something like this?
http://test.com/path1/path2/1?q=test
And how would that get defined in the router.get?
You do not need to add a query parameter to your route directly. Just keep /path1/path2/:userId.
Within your function you can then check, if a query parameter exists, here via req.query.q.
// http://test.com/path1/path2/1?q=test
router.get('/path1/path2/:userId', (req, res) => {
let route = `GET /path1/path2/${req.params.userId}`;
// If http://test.com/path1/path2/1, req.query.q is undefined
console.log(req.params.userId, req.query.q);
});
You use the req.query object to get query parameters.
So, for the URL http://test.com/path1/path2/1?q=test, you could get the query parameter like this:
router.get('/path1/path2/:userId', (req, res) => {
console.log(req.params.userId); // "1"
console.log(req.query.q); // "test"
});
Doc for req.query is here.
For this url http://test.com/path1/path2/1?q=test
access path params = req.params.userId.
access query params = req.query.q.
Read more from Express documentation
http://expressjs.com/de/api.html#req.query
http://expressjs.com/de/api.html#req.params

How to write url for request with params in express?

I want to make a get request for this type of url:
http://localhost:9000/data?start-time=1234124
I want to define route in ExpressJS:
app.get("/data",function(req,res){
})
How to set parameter start-time in url?
Thanks :)
Query string parameters are contained in the req.query object. If you want to get start-time, try this:
app.get("/data", function(req, res) {
let startTime = req.query['start-time'];
});

Single express route to capture all possible params combinations

I want my API to support filtering on the different properties of my mongodb model. The brute force way of which I would use:
app.get('/api/thing/:id', thing.getThingById);
app.get('/api/thing/:name, thing.getThingByName);
app.get('/api/thing/:name/:color', thing.getThingByNameAndColor);
etc. This approach is obviously terrible. How can I add a single route to capture multiple params so that I can return things using something like
exports.getThingByParams = function (req, res, next) {
var query = thingModel.find (req.params);
query.exec (function (err, things) {
if (err) return next (err);
res.send ({
status: "200",
responseType: "array",
response: things
});
});
};
Use the URL query string. It's a set of name/value pairs invented for precisely this use case. It still works great after all these years despite current trends the everything must be in the path portion of the URL instead of the query string because ???. Look at your route - it even says "API" in it. It doesn't need to abuse the path to be "pretty" according to hipsters.
app.get('/api/thing', thing.search);
exports.search = function (req, res, next) {
//Remember any ID values need to be converted from strings to ObjectIDs,
//and there's probably additional sanitization/normalization to do here
var query = thingModel.find (req.query);
query.exec (function (err, things) {
if (err) return next (err);
res.send ({
status: "200",
responseType: "array",
response: things
});
});
};
Then the url to find a red thing named candy would look like
/api/thing?color=red&name=candy
Yup, you can. Just use the most explicit route example:
app.get('/api/thing/:name/:color', thing.getThingByProperty);
and inside getThingByProperty simply test for req.params.YourParam (name or color) and decide what to do. If color is requested but not name, you send in the url as follows:
/api/thing/-/red.
Very common sighting to have null params in routes expressed as dash.
OR, different approach, better pattern more API like (RESTFul) is:
/api/thing/:id that's by id and to offer pattern support
and for different property search use:
/api/things/search?property1=value&property2=value
That way you respect the collection pattern in your API (/api/things) and put the search in the query to keep it flexible. Test inside the search callback for req.query.property1 or property and act accordingly

How to send integers in query parameters in nodejs Express service

I have a nodejs express web server running on my box. I want to send a get request along with query parameters. Is there any way to find type of each query parameter like int,bool,string. The query parameters key value is not know to me. I interpret as a json object of key value pairs at server side.
You can't, as HTTP has no notion of types: everything is a string, including querystring parameters.
What you'll need to do is to use the req.query object and manually transform the strings into integers using parseInt():
req.query.someProperty = parseInt(req.query.someProperty);
You can also try
var someProperty = (+req.query.someProperty);
This worked for me!
As mentioned by Paul Mougel, http query and path variables are strings. However, these can be intercepted and modified before being handled. I do it like this:
var convertMembershipTypeToInt = function (req, res, next) {
req.params.membershipType = parseInt(req.params.membershipType);
next();
};
before:
router.get('/api/:membershipType(\\d+)/', api.membershipType);
after:
router.get('/api/:membershipType(\\d+)/', convertMembershipTypeToInt, api.membershipType);
In this case, req.params.membershipType is converted from a string to an integer. Note the regex to ensure that only integers are passed to the converter.
This have been answered a long ago but there's a workaround for parsing query params as strings to their proper types using 3rd party library express-query-parser
// without this parser
req.query = {a: 'null', b: 'true', c: {d: 'false', e: '3.14'}}
// with this parser
req.query = {a: null, b: true, c: {d: false, e: 3.14}}
let originalType = JSON.parse(req.query.someproperty);
In HTTP, querystring parameters are treated as string whether you have originally sent say [0,1] or 5 or "hello".
So we have to parse it using json parsing.
//You can use like that
let { page_number } : any = req.query;
page_number = +page_number;
Maybe this will be of any help to those who read this, but I like to use arrow functions to keep my code clean. Since all I do is change one variable it should only take one line of code:
module.exports = function(repo){
router.route('/:id',
(req, res, next) => { req.params.id = parseInt(req.params.id); next(); })
.get(repo.getById)
.delete(repo.deleteById)
.put(repo.updateById);
}

Express.js routing with optional param?

I have two situations to get data from DB
To show normal data
http://exampleapp.com/task/{{taskId}}
To edit data via posting
http://exampleapp.com/task/{{taskId}}/?state={{app.state}}
Both url have the same http://exampleapp.com/task/{{taskId}} just a little bit different with last phrase ?state={{app.state}}
I use Express routing as followed:
app.get('/task/:taskId/(?state=:status(pending|cancel|confirmed|deleted))?', routes.task.show);
But I dont know why it does not work ?
For example error: Cannot GET /task/51d2c53f329b8e0000000001 when going to h**p://exampleapp.com/task/51d2c53f329b8e0000000001
Query strings cannot be defined in routes. You access query string parameters from req.query.
app.get('/task/:taskId', function(req, res) {
if (req.query.state == 'pending') { ... }
});
However, if you're modifying a task, this is not the appropriate way to do it. GET requests SHOULD be idempotent: the request SHOULD NOT modify state. That's what POST requests are for.
app.get('/task/:taskId', function(req, res) {
// show task info based on `req.params.taskId`
});
app.post('/task/:taskId', function(req, res) {
// set task `req.params.taskId` to state `req.body.state`
});
You could either have a <form> that posts to the task, or make an ajax request:
$.post('/task/1', { state: 'pending' }, function() { ... });
According to the Express API, you cannot mix RegExp routes with string routes.
You should do something like this (I'm assuming taskId is an integer):
app.get(/^\/task/([0-9]+)/(?state=:status(pending|cancel|confirmed|deleted))?, routes.task.show);
However, I don't see why you cannot only check if req.query.state is defined in your route. It's probably less error prone and easier:
app.get("/task/:taskId", function( req, res, next ) {
if (req.query.state) {
// Do things
}
next();
});
Your problem is that query strings are not considered in routing. You will either have to redesign your urls (ie, include the state into the url itself, instead of the query string) or check the query string in your route handler function.

Resources