Dynamic routing in Node.js - javascript

I want to create dynamic stubs as webservices. My idea is to load at every request a definition file and return data for corresponding URL.
The definition file could look like this:
/api/users {users:["john", "jack", "jake"]}
/api/users/1 {user:"john"}
/api/some-data/1 {data:"some data"}
In an application I created on behalf of a tutorial I find:
router.post('/some-irl', function (req, res) {
//some code
return {some JSON}
});
But this definition looks static to me, which should be there before I start Node.js Is it possible to define /some-irl at the time then request occures?
EDIT
Actually, I was intending to do somehting like this: https://github.com/typicode/json-server but it is already there!

You can attach a use middleware, which can check the path and decide whether to handle it or pass it on:
router.use(function(req, res, next) {
// req.path
// decide what to do
// respond or next()
});

you can define variables in the routes, use : before the variable name to define it, and then you'll get the value in req.params:
route.get('/api/users/:user/', function (req, res) {
var username = req.params.user;
});

Related

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 to create a global function which will access DB in express.js

I use express.js, mongodb, ejs. In the navbar, there's an email icon and will display the count of new emails.
<%=newEmailCount%>
Then I need to add this newEmailCount to every route.
Emails.count({userId: userId, new: true})
my question is in express.js, how can I add a global function that can be executed by every route?
If you want to get the count for every GET requests then you can use following approach
router.get('*', function(req, res, next) {
res.locals.newEmailCount = Emails.count({userId: userId, new: true})
next();
})
You need to make sure this is always executed by placing it above all the other routes.
You can then pass res.locals.newEmailCount to your render function which renders HTML file for matched route.
This will work also for application instance level routes handling if that's what you're using.

Mongoose pass req object to middleware

I am writing a middleware for mongoose that gets executed for every find object using pre query hook.
postSchema.pre('query', function(query, next) {
// I want to access the req.user object here
query.populate('Category');
next();
});
I want to access req.user object inside the pre for every request made to the api server. How can i pass the object to the middleware?
Is it even possible?
https://github.com/Automattic/mongoose/issues/1931
I found the above but it doesnt talk about passing req object.
====================
Edit after some confusion about the question.
What i am trying to accomplish is to get the req.user role and the model name pass it to another function to get the query condition for find. So depending on the user role and the type of model accessed the query condition will change.
Wrap the middleware in another middleware that has access to req.
Something like, assuming express
router.verb('/some-route', function (req, res, next) {
postSchema.pre('query', function(query, next) {
console.log(req);
query.populate('Category');
next();
});
});
Edit
- Attach this only to the route that you want the prehook for.
Disclaimer - Not tested.
I know i'm joining this party late but you can use a service to pass the data you want between the request object and the mongoose prehook method. In your service create private variables that hold the data that you want to pass. Set those variables in your custom middleware and call the service get method to get the values in the mongoose prehook method.
Use
query.op to get the type of query
query.options to get other options like {runValidators: true}
query._condition to get the conditions of the query
query._update to get the incoming body
query._fields to get the selected fields,
You can also log the query to the terminal to see various options
Yes, it is possible.
restify.serve(router, model, {
preCreate: function (req, res, next) {
req.body.createdBy = req.user._id
next()
}
})
Follow this doc

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