I've looked up JavaScript functions and arguments but couldn't find anything to help me understand a function like the one below. You can reference the original tutorial.
createPuppy has three arguments: req, res and next.
function createPuppy(req, res, next) {
req.body.age = parseInt(req.body.age);
db.none('insert into pups(name, breed, age, sex)' +
'values(${name}, ${breed}, ${age}, ${sex})',
req.body)
.then(function () {
res.status(200)
.json({
status: 'success',
message: 'Inserted one puppy'
});
})
.catch(function (err) {
return next(err);
});
}
That function is being called by a router:
var express = require('express');
var router = express.Router();
var db = require('../queries');
router.get('/api/puppies', db.getAllPuppies);
router.get('/api/puppies/:id', db.getSinglePuppy);
router.post('/api/puppies', db.createPuppy);
router.put('/api/puppies/:id', db.updatePuppy);
router.delete('/api/puppies/:id', db.removePuppy);
module.exports = router;
When db.createPuppy is called, there wasn't any arguments passed.
How do those three arguments fit into this function?
Update: I'm new to Node, JavaScript, pg-promise and express. So it was a bit overwhelming to narrow down where to dig. I came here to get leads on where to narrow my focus in. Thank you!
I believe that (req, res, next) are default arguments in Express.
When you write router.post('/api/puppies', db.createPuppy);, the function createPuppy is not actually called yet. This just establishes what function to call when that method/endpoint is hit.
Express takes care of calling the function and passing in the required arguments to it when you hit the /api/puppies endpoint with a POST.
Hope that helps!
You will be sending that data through a POST request to that endpoint. You can then access the data you pass in through the req.body variable.
You will also need the bodyParser middleware to access the request body. More on that here.. http://expressjs.com/en/api.html#req.body
Related
In application which I currently develop, it's using Express. In my case I want to get response before it's been sent and modify it (for purpose of JWT). In this application, there is a dozen of endpoints and I don't want to create my own function like sendAndSign() and replace res.send() everywhere in code. I heard there is option to override/modify logic of res.send(...) method.
I found something like this example of modifying, but in my case this doesn't work. Is there any other option (maybe using some plugin) to manage this action?
You can intercept response body in Express by temporary override res.send:
function convertData(originalData) {
// ...
// return something new
}
function responseInterceptor(req, res, next) {
var originalSend = res.send;
res.send = function(){
arguments[0] = convertData(arguments[0]);
originalSend.apply(res, arguments);
};
next();
}
app.use(responseInterceptor);
I tested in Node.js v10.15.3 and it works well.
I have created an NPM package called experss-response-hooks that provides response hooks.
You can register a hook in a middleware before all your other routes, that will enable you to change the response body when send() will be called.
For example:
const responseHooks = require('express-response-hooks');
// response hooks initialization
app.use(responseHooks());
// register a middleware that modifies the response body before being sent to the client
app.use(function (req, res, next) {
// hook on "send()" function
res.hooks.on('send', (args) => {
args[0] = 'new-body'; // args[0] is the body passed to send()
});
});
In my code I have code written like this
router.post('/', publicShare, function(req, res, next) {
I check in documents but not found why second param publicShare is here?
publicShare is looks like
var publicShare = function(req, res, next) {
if (condition1) {
if (condition2) {
res.status(400).send({success:false});
} else {
next();
}
} else {
if (condition3) {
res.status(401).send({success:false});
} else
next();
}
};
Please help me to understand.
You can check route handlers which accepts array of callbacks which just behaves like a middleware. Example from the docs:
app.get('/example/d', [cb0, cb1], function (req, res, next) {
So, in your case publicShare can be array of callbacks or just a callback which signature is just a callback accepting req, res, and next as parameter. So, you can also use like:
app.get('/', function(req, res, next){}, function(req, res, next){}, ...
And for easier, you would use an array of callbacks:
app.get('/',[cb1, cb2, cb3])
Where cb1, cb2, and cb3 are the callbacks with request, response and next parameters. It allows you to run one by one. cb1 -> do log 1, then cb2 -> do log 2, cb3 -> do log 3 and so on.
I would simplify this with an example:
You would request for water.
1) cb1: Purchase a jar of water.
2) cb2: Add few water drops in the bucket or jar.
3) cb3: Boil it.
Then, it's your turn. Drink!
publicShare method in your route is a express middleware function .According to the docs
Middleware functions are functions that have access to the request
object (req), the response object (res), and the next middleware
function in the application’s request-response cycle
A middleware checks for certain condition or criteria to be applied on your request and response object ,if the criteria fulfills then the next operation is done ,which is either
1-End the request response cycle
2-Call the next middleware function in the stack.
You can refer the docs for more information -https://expressjs.com/en/guide/using-middleware.html
According to the documentation, you can add multiple middleware functions separated by commas. The 'publicShare' variable must be a middleware function.
For an express app I'm working on, my callbacks can only have (req, res, next, err) passed into them.
This is what I had that worked.
function listEvents(auth, req, res, email, authURL = ""){
...
var calendar = google.calendar('v3');
calendar.events.list({
auth: auth, ... });
}
But my function definition must look like this:
function listEvents(req, res){...}
I can retrieve email and authURL from within the API call, but I don't know how to pass in auth which is created in the method of which listEvents is a callback. I am trying something like this:
oauth2Client.credentials = acctoken;
var output = {
auth: oauth2Client,
data: callback(req, res)
};
res.send(output);
But I need to get the oauth2Client into the callback itself. This would just let you send both in the response to the chain of callbacks.
I would appreciate any help. Thank you so much.
oauth2Client.credentials = acctoken;
var output = {
auth: oauth2Client,
data: callback(req, res)
};
res.send(output);
With reference to the above code block you are assigning auth as oauth2Client.
You can append oauth2Client in your req object and use it in your callback function.
So I've talked to multiple people and apparently my issue is that I was not thinking of the request object properly. As the above answer states, one can append fields to the body of the request. I have only ever prepared requests in postman up until this point - so this is very useful for me to know. This is almost exactly what I was looking for; I needed a way to give information to a callback without passing it in as a parameter.
I'm a little bit newbie with Nodejs. I'm working in a Nodejs - express solution (as webservice of an angularjs web). I want to send and e-mail when MSSSQL database query gives back some information. This is working well for me. The problem is this function should be call in the app.js (when the nodejs server starts), because the function don't should respond to any frontend/web call.
The function:
exports.sendMailBuy = function(req, res) {
//do stuff
}
The app.js
var silkcartCtrl = require('./controllers/silkcart.controller');
I need to connect with the database, so I've tried to call the funciont in the same function db connection (I'm using Tedious):
dbsqlservertoken.connect().then(function(err, req, res) {
console.log('Connection pool open for sql server');
silkcartCtrl.sendMailBuy(req, res);
}).catch(function(err) {
console.error('Error creating connection pool', err);
});
With this call I reach the function in the controller, but the req and res vars are empty, so the connection could not be done.
Any help will be appreciate.
Thanks in advance.
The .then() method is used when a Promise is returned. I'm not familiar with the libraries you're using, but your code indicates that connect() returns a Promise.
See Promises for more information.
In particular, the function passed to .then() takes a single argument which is the result resolved by the Promise. In your code, err is being assigned the result while req and res are undefined because the function only receives one argument.
req, res are not returned from connect callback function they are only acccessed using api requests e.g. app.post('/any route' , function(req, res))
You can use node_mailer module if you need req object to send email because with node_mailer you can send email without req object
I'm trying to learn Express session and authentication handling.
For example:
app.post('/login', authCredentials, function(req, res) {
console.log("second")
});
function authCredentials(req, res, next) {
//this happens first
console.log(req.body) // => { username: etc, password: etc }
next();
}
My question is just how much should my authCredentials function do?
For example if the credentials are correct, I can do something like
res.redirect('/index'). Once I do that, however, what purpose does the second function have?
Other questions:
How would I handle invalid credentials?
If I make authCredentials just return true or false depending on the credentials, doesn't that break the middleware flow because it would never invoke next()?
Is it possible to access anything in authCredentials in the anonymous callback after it? Basically in the function(req, res) { }?
The answer depends on your authentication strategy i.e. are you using session identifiers, access tokens, etc.
In either case I suggest that you break out the credential exchange (aka login) from the authentication.
function usernamePasswordExchange(req,res,next){
var username = req.body.username;
var password = req.body.password;
callToAuthService(username,password,function(err,user){
if(err){
next(err); // bad password, user doesn’t exist, etc
}else{
/*
this part depends on your application. do you use
sessions or access tokens? you need to send the user
something that they can use for authentication on
subsequent requests
*/
res.end(/* send something */);
}
});
}
function authenticate(req,res,next){
/*
read the cookie, access token, etc.
verify that it is legit and then find
the user that it’s associated with
*/
validateRequestAndGetUser(req,function(err,user){
if(err){
next(err); // session expired, tampered, revoked
}else{
req.user = user;
next();
}
});
}
app.post('/login',usernamePasswordExchange);
app.get('/protected-resource',authenticate,function(req,res,next){
/*
If we are here we know the user is authenticated and we
can know who the user is by referencing req.user
*/
});
Disclaimer: I work at Stormpath and we spend a lot of time writing
authentication code :) I just wrote our newest library, stormpath-sdk-express,
which has a concrete implementation of my suggestions
You want to add your authCredentials middleware to every end point that needs authentication. app.post('/login') usually does not need any as you want to access this end point to actually get credentials in the first place.
When credentials are correct/valid you simply invoke next() and the workflow will jump to the next middleware or the actual end point. If there was an error, invoke next() with an error object like next(new Error('could not authenticate'); for instance. Add an error route to your general routing and the error will be handled there:
app.use(function(err, req, res, next) {
res.render('error', err);
});
Should be answered by now.
A middleware does not return a value. It either calls next() or ends the process differently by calling res.send().
There are different approaches to pass variables from one middleware to another. The most common is probably to attach the desired value to the req parameter.
authenticate is an asychronous function in the following example:
function authCredentials(req, res, next) {
authenticate(req.body, function(err, user) {
if (err) {
return next(err);
}
req.user = user;
next();
});
}