Express callback needs more parameters than (req, res) - javascript

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.

Related

Custom middleware for express routes

I actually implemented a custom middleware in an expressJs application. I aim for modifying the request object before sending it back. It works and the result is exactly what i was expecting, but i am not sure if this is the correct way to do so. I am kind of afraid, that manipulating the reqeust object is not the correct way to do this.
Here is the code:
expressApp.get('/apps/:id', isAuthenticated, appLinks(dbController), async (req, res) => {
res.send(req.__appLink)
})
app-links.ts:
export const appLinks: MiddlewareWrapper = (dbController: DatabaseHandler) => async (req: Request, res: Response, next: NextFunction) => {
dbResult = modifyMyDatabaseResult(await dbController.getApps());
req.__appLink = dbResult
next()
}
As you can see, in my route i send req.__appLink which was set inside the middleware. It this the correct way to do such things?
This is good! Nothing is wrong with modifying the req object.
Yes this is fine. But for better presentation you can save the result of req._appLink in a variable and pass it to res object.

Modify response body before res.send() executes in ExpressJS

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()
});
});

ExpressJS + JWT. What's the proper way to get auth data?

Let's jump to an example. I'll skip some parts like imports, exports.
I have a controller called controllers/book.js with one route:
router.get('/my-books', function(req, res) {
if(Auth.authenticated(req,res)) {
Book.getMyBooks(function(rows) {
response.operationSucceed(req, res, rows);
});
}
});
Then, in a model called models/book.js I have that function:
function getMyBooks(successCallback) {
db.query('SELECT * FROM book b WHERE b.id_user=?', [Auth.getLoggedUID()], function(rows) {
successCallback(rows);
});
}
My question is about Auth.getLoggedUID function.
Assuming that I have a JWT authentication and assuming that I have an UID in payload (is that even acceptable?), what's the best option to retrieve it? Is there any, EXCEPT passing the req every time to every function where I need auth data?
I may have a function execution inside a function, do I need to pass the req through both of them to get the user ID? Like this?:
function getBooks(req) {
getMyBooks(req);
getCriminalBooks(req);
getEvenOtherBooksByAuthor(req, authorId);
}
Honestly I wouldn't like that.
Maybe my whole concept is wrong and I should be doing things differently?
Can someone point me the right direction in scenarios like this?
You can pass UID in header and retrieve it inside your controller as:
var uid =req.header('UID');
Then pass this UID where ever you want there is no need to carryforward whole req object everywhere.
You can use a middleware function. Let's say that every request that hits your endpoints, will have a token which you should check and possibly decode it. After that, you can set the decoded content to the req object. So something like this:
app.use(function(req, res, next) {
// get the token from the request headers most likely.
// verify and decode the token
// set the decoded content to the request
var payload = ..
req.payload = payload;
});
After this you can access the payload in every single endpoint you have. So for example in some controller you can do:
app.get('/hey', function(req, res) {
var payload = req.payload;
});

How are these three JavaScript function arguments use?

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

Easy way to handle post data in meteor.js?

I need to handle some POST data in my meteor.js app, is there an easy way to do this?
Very basic, if it was a PHP app I would just want the $_POST variable.
Meteor router
https://github.com/tmeasday/meteor-router#server-side-routing
Meteor.Router.add('/items/:id', 'POST', function(id) {
// update Item Function
return [200, 'ok'];
});
If you are simply looking to intercept the GET and POST data, then send Meteor on it's merry way, you could do something like this on the server.
if (Meteor.isServer) {
var connect = Npm.require('connect');
var app = __meteor_bootstrap__.app;
var post, get;
app
// parse the POST data
.use(connect.bodyParser())
// parse the GET data
.use(connect.query())
// intercept data and send continue
.use(function(req, res, next) {
post = req.body;
get = req.query;
return next();
});
Meteor.startup(function() {
// do something with post and get variables
});
}
EDIT 11/01/13
I ended up creating a smart package for this (for myself). There is no documentation but you are welcome to use it. https://github.com/johnnyfreeman/request-data
To retrieve the foo request variable:
RequestData.get('foo') // --> 'bar'
RequestData.post('foo') // --> 'bar'
Both methods will throw a Meteor.Error if the key isn't found so make sure you use wrap with a try/catch if the variable is optional.
You can use Meteor's Iron Router, docs here, since Router (as mentioned above) is outdated and might be no longer functional.
Router.route('/items/:id', {where: 'server'})
.get(function () {
this.response.end('get request\n');
})
.post(function () {
this.response.end('post request\n');
});
I'm using this package to serialize body data: simple:json-routes. Here is the link.
And this code snippet to access it:
WebApp.connectHandlers.use('/api/request', (req, res, next) => {
console.log(req.body);
});

Categories

Resources