Express require a query parameter - node.js

Let's say I have a route /ressource. I can call this route with a query parameter /ressource?param=ABCwhich I can retrieve in Node with:
app.get('/ressource', function (req, res) {
const parameter = req.query.param
})
Now, is there a predefined way I can require the parameter which throws an error for request to /ressource without ?param=ABC.

You can use req.query to get the query parameter and use next callback function to throw an error like
app.get('/ressource', function (req, res, next) {
if(!req.query.param) {
const err = new Error('Required query params missing');
err.status = 400;
next(err);
}
// continue
const parameter = req.body.param
})

In express, query is automatically parsed and put into the req.query object, not the req.param object.
So you can access it like this:
const parameter = req.query.parameter;
read req.query on expressjs docs.

There are no predefined way to.
You can choose to check it yourself inside the callback function:
if (!req.query.parameter) {
res.send('parameter is missing');
}
or to use a router middleware which would serve the same purpose

Related

mongoose throws internal server error when ID doesn't exist

mongoose findOne query throws Interal Server Error (500) when looking for a value that doesn't exists.
I'm pretty sure it should return null or empty array instead of throwing error.
Mongoose version: ^5.8.7
First attempt
router.get('/:myId', async(req, res, next) => {
const myId = req.params.myId;
await myDocument.findOne({ _id: myId }, (err, myData) => {
if (!myData) {
res.status(404).render('404');
} else {
res.render('myPage', myData);
}
}).exec()
});
second attempt
router.get('/:myId', async(req, res, next) => {
const myId = req.params.myId;
const myData = myDocument.findOne({_id: myId}).exec();
if (myData) {
//render normal page
}
// render 404 page
});
According to documentation, this should NOT happen.
Note: conditions is optional, and if conditions is null or undefined, mongoose will send an empty findOne command to MongoDB, which will return an arbitrary document. If you're querying by _id, use findById() instead.
Also tried to use findById() and find(). All cases the same happens.
It works perfectly when I pass a valid ID parameter.
How to search for data without throwing http error in case Id doesn't exists in collection?
router.get('/:myId', async(req, res, next) => {
You should check your route
You should try this code. First assign the ObjectId on top where are dependencies being called.
MongoDB id is not string. It is adviseble to pass the ObjectId.
const { ObjectId } = require('mongodb');
router.get('/:myId', async(req, res, next) => {
const myId = ObjectId(req.params.myId);
const myData = await myDocument.findOne({_id: myId}).exec();
if (myData) {
//render normal page
}
// render 404 page
});
The error was actually happening during the page render.
In fact, mongoose does NOT throws any error in this case.
I was trying to render a html page while setting ejs as View Engine.
Apparentely we can't mix things.

Pass parameter to middleware function and return result

So guys, what I want to accomplish and not manage to get is to write a function that performs a query against database as a middleware, using req and res objects, and also can be used in a socket connection, to pass parameters to it and not use the req and res objects. Also I want it to return the result of the query. I tried using a middleware wrapper
function myFunc(param1, param2){
return (req, res) => {
here query
}}
works when hitting the endpoint with or without args i send, but dosnt work when i call the function from somewhere else
When you call myFunc you get returned a new function. You need to invoke that funcion, something like
myFunc('value1', 'value2')()
This will cause an error since you have no request or response object. These are express objects.
A better way to re-use the database code would be to put it in a function and inject that function to the middlewere.
E.g.
function getArticleById(id) {
return db.query('select * from articles where id = $1', [id])
}
Then create a middlewhere that takes this function in as dependency
function makeMiddlewere (getArticleById) {
return (req, res) => {
return articleById(req.query.id).then(articles => {
res.json(articles)
})
}
}
Then in your code you can do
Normal way
getArticleById(5).then(articles => {
console.log(articles)
})
Create the middlwere an
const express = require('express')
const getArticleById = require('./articlebyid')
const makeMiddlewere = require('./makemiddlewere')
const middlwere = makeMiddlwere(getArticleById)
const app = express.app
app.get('/article', middlewere)

Pass object initialized via express middleware to next middleware

Below is my setup, I am trying to pass an object that is initialized in express middleware to a different middleware function. In my router, Invoke helper.getValues() and get an error that I cannot invoke function getValues of undefined
let helper; // no initial value
const getConfig = async () => {
config = await service.getConfig(configName);
helper = new Helper(config); // Helper is correctly initialized here
};
// declare a new express app
let app = express();
app.use(async function (req, res, next) {
try {
await getConfig(); // invoke the code that initializes my helper
next();
} catch (e) {
console.error(e);
}
});
app.use('/path', MyRouter(helper)); // Pass helper to router - it's undefined in router code
My Router Constructor looks like this
function MyRouter(helper) {
...
... const values = helper.getValues();
}
What is the correct way to pass the helper that is created in getConfig to my router?
Pass it via req or res depending on your intent.
If the data relates to the request such as the requesting user's identity, the session attributes, geoIP or parsed request body then attach it to the req object:
If the data relates to response processing such as variables used by templates/views or requested response format then attach it to the res object.
Assuming you want to pass it via req:
req.helper = await getConfig();
Then to use it:
function router (req, res) {
const values = req.helper.getValues();
// ...
}

How to get koa-router query params?

I haved used axios.delete() to excute delete in frontend ,code like below
Axios({
method: 'DELETE',
url:'http://localhost:3001/delete',
params: {
id:id,
category:category
}
})
And I used koa-router to parse my request in backend ,but I can't get my query params.
const deleteOneComment = (ctx,next) =>{
let deleteItem = ctx.params;
let id = deleteItem.id;
let category = deleteItem.category;
console.log(ctx.params);
try {
db.collection(category+'mds').deleteOne( { "_id" : ObjectId(id) } );
}
route.delete('/delete',deleteOneComment)
Could anyone give me a hand ?
Basically, I think you misunderstood context.params and query string.
I assume that you are using koa-router. With koa-router, a params object is added to the koa context, and it provides access to named route parameters. For example, if you declare your route with a named parameter id, you can access it via params:
router.get('/delete/:id', (ctx, next) => {
console.log(ctx.params);
// => { id: '[the id here]' }
});
To get the query string pass through the HTTP body, you need to use ctx.request.query, which ctx.request is koa request object.
Another thing you should be aware with your code is essentially, a http delete request is not recommended to have a body, which mean you should not pass a params with it.
You can use ctx.query and then the name of the value you need.
For instance, for the given url:
https://hey.com?id=123
You can access the property id with ctx.query.id.
router.use("/api/test", async (ctx, next) => {
const id = ctx.query.id
ctx.body = {
id
}
});
per koa documentation ctx.request.query

Node Error: Route.get() requires callback functions but got a [object Undefined]

I have not found a question with a similar setup... how do I fix this?
I'm using node, express routing, request to call a token from an api, and async series to keep everything clean. I simplified the code by only showing one function in the async series.
routes.js
var express = require('express')
var router = express.Router()
var isAuthenticated = require("./passportAuth.js")
var tokens = require('./tokens')
module.exports = function() {
router.get('/allTokens', isAuthenticated, tokens())
return router
}
./tokens.js
var request = require("request")
var async = require('async')
module.exports = function(req, res, next) {
var allTokens = function(callback) {
request('url', function(err, res, body) {
if(err) return callback(err, null)
return callback(null, 'success')
})
}
var asyncFinally = function(err, results) {
if(err) return next(err)
res.send(results)
}
async.series([allTokens], asyncFinally)
}
Error message
Route.get() requires callback functions but got a [object Undefined]
The router is expecting a function value but you are passing in an invoked function tokens(). Try just tokens.
You are prematurely calling the tokens() function rather than just passing a reference to it. Change this:
router.get('/allTokens', isAuthenticated, tokens())
to this:
router.get('/allTokens', isAuthenticated, tokens)
Remember that any time you put () after a function name that means to call it now (immediately). Any time you just pass the function name by itself, that just passes a reference to the function that can be called later at the appropriate time (that's what you want here). This is a very common mistake.
Since calling tokens() returns undefined, that is what you end up passing to router.get() and thus why you get the specific error message you see.

Resources