Sharing objects across routes - node.js

Trying out Keen.io and wondering if it's possible to NOT have to call "configure" in each file that will make a call to the Keen API?
Their docs from here: https://github.com/keenlabs/KeenClient-node show how to configure an instance which I use in one of my routes but I have a number of routes and find that I have to keep configuring.
var Keen = require('keen.io');
// Configure instance. Only projectId and writeKey are required to send data.
var client = Keen.configure({
projectId: "<project_id>",
writeKey: "<write_key>",
readKey: "<read_key>",
masterKey: "<master_key>"
});
Is there a way to "configure" just once or have I got the wrong idea?

Check out this answer to another question on SO. It describes a method to use app.get() and app.set() to access dependencies across the application.
After you configure client, set it in the app:
app.set('keen', client);
Then later get it back out from within any route:
var client = app.get('keen');

I decided to configure the app inserver.js and then pass the client object to each route that requires it. This appears to work well and has tidied my code up considerably.

Related

fastify-swagger is not picking up my dynamic routes

I've been a fan of ExpressJs for a long time but in a Youtube video I stumble upon Fastify and wanted to give it a try
I'm struggling in making the fastify-swagger plugin work as I assume it should work - dynamic setup to pick up the schema from each route, but I'm certainly missing something 😔
here's my test repo that after running, none of my routes appear
my setup for the plugin is the default one
but all I see is
I've read in the read me that because of OpenAPI specs, some properties, like description are mandatory or will not pick up the route, but I've added in one route, and still does not pick up, I've also added tags wondering if that was also mandatory, but nothing...
does anyone know what am I missing? must be a simple thing, but got me puzzled this last few days 😔
I ran into the same issue and ended up solving it by following the first Usage example line-by-line: https://github.com/fastify/fastify-swagger#usage
const fastify = require('fastify')()
(async () => {
// set up swagger
await fastify.register(require('#fastify/swagger'), {
...swagger config
});
// define all your routes
// then call these
await fastify.ready()
fastify.swagger()
})();
Consider the order in which your plugins are loaded, the routes need to be registered before fastify swagger. If fastify swagger comes first, it doesn't detect any route.
I encountered this issue in my project. In my case, I solved it using fastify-plugin. Looking at the source code for fastify-swagger, it seems to rely on a hook listening for onRoute events to detect routes. I'm thinking maybe encapsulation can interfere with the plugin's ability to receive the events.

Register new route at runtime in NodeJs/ExpressJs

I want to extend this open topic: Add Routes at Runtime (ExpressJs) which sadly didn't help me enough.
I'm working on an application that allows the creation of different API's that runs on NodeJs. The UI looks like this:
As you can see, this piece of code contains two endpoints (GET, POST) and as soon as I press "Save", it creates a .js file located in a path where the Nodejs application is looking for its endpoints (e.g: myProject\dynamicRoutes\rule_test.js).
The problem that I have is that being that the Nodejs server is running while I'm developing the code, I'm not able to invoke these new endpoints unless I restart the server once again (and ExpressJs detects the file).
Is there a way to register new routes while the
NodeJs (ExpressJs) is running?
I tried to do the following things with no luck:
app.js
This works if the server is restarted. I tried to include this library (express-dynamic-router, but not working at runtime.)
//this is dynamic routing function
function handleDynamicRoutes(req,res,next) {
var path = req.path; //http://localhost:8080/api/rule_test
//LoadModules(path)
var controllerPath = path.replace("/api/", "./dynamicRoutes/");
var dynamicController = require(controllerPath);
dynamicRouter.index(dynamicController[req.method]).register(app);
dynamicController[req.method] = function(req, res) {
//invocation
}
next();
}
app.all('*', handleDynamicRoutes);
Finally, I readed this article (#NodeJS / #ExpressJS: Adding routes dynamically at runtime), but I couldn't figure out how this can help me.
I believe that this could be possible somehow, but I feel a bit lost. Anyone knows how can I achieve this? I'm getting a CANNOT GET error, after each file creation.
Disclaimer: please know that it is considered as bad design in terms of stability and security to allow the user or even administrator to inject executable code via web forms. Treat this thread as academic discussion and don't use this code in production!
Look at this simple example which adds new route in runtime:
app.get('/subpage', (req, res) => res.send('Hello subpage'))
So basically new route is being registered when app.get is called, no need to walk through routes directory.
All you need to do is simply load your newly created module and pass your app to module.exports function to register new routes. I guess this one-liner should work just fine (not tested):
require('path/to/new/module')(app)
Is req.params enough for you?
app.get('/basebath/:path, (req,res) => {
const content = require('content/' + req.params.path);
res.send(content);
});
So the user can enter whatever after /basepath, for example
http://www.mywebsite.com/basepath/bergur
The router would then try to get the file content/bergur.js
and send it's contents.

Access Previously-Defined Middleware

Is there a way to access or delete middleware in connect or express that you already defined on the same instance? I have noticed that under koa you can do this, but we are not going to use koa yet because it is so new, so I am trying to do the same thing in express. I also noticed that it is possible with connect, with somewhat more complicated output, but connect does not have all the features I want, even with middleware.
var express = require('express');
var connect = require('connect');
var koa = require('koa');
var server1 = express();
var server2 = connect();
var server3 = koa();
server1.use(function express(req, res, next) {
console.log('Hello from express!');
});
server2.use(function connect(req, res, next) {
console.log('Hello from connect!');
});
server3.use(function* koa(next) {
console.log('Hello from koa!');
});
console.log(server1.middleware);
// logs 'undefined'
console.log(server2.middleware);
// logs 'undefined'
console.log(server2.stack);
logs [ { route: '', handle: [Function: connect] } ]
console.log(server3.middleware);
// logs [ [Function: koa] ]
koa's docs say that it added some sugar to its middleware, but never explicitly mentions any sugar, and in particular does not mention this behavior.
So is this possible in express? If it is not possible with the vanilla version, how hard would it be to implement? I would like to avoid modifying the library itself. Also, what are the drawbacks for doing this, in any of the 3 libraries?
EDIT:
My use case is that I am essentially re-engineering gulp-webserver, with some improvements, as that plugin, and all others like it, are blacklisted. gulp is a task runner, that has the concept of "file objects", and it is possible to access their contents and path, so I basically want to serve each file statically when the user goes to a corresponding URL in the browser. The trouble is watching, as I need to ensure that the user gets the new file, and not the old version. If I just add an app.use each time, the server would see the file as it is originally, and never get to the middleware with the new version.
I don't want to restart the server every time a file changes, though I will if I can find no better way, so it seems I need to either modify the original middleware on the fly (not a good idea), delete it, or add it to the beginning instead of the end. Either way, I first need to know where it "lives".
You might be able to find what your looking for in server1._router.stack, but it's not clear what exactly you're trying to do (what do you mean "access"?).
In any case, it's not a good idea to do any of these, since that relies strictly on implementation, and not on specification / API. As a result any and all assumptions made regarding the inner implementation of a library is eventually bound to break. You will eventually have to either rewrite your code (and "reverse engineer" the library again to do so), or lock yourself to a specific library version which will result in stale code, with potential bugs and vulnerabilities and no new features / improvements.

Capture and log the api calls made to the server along with the passed data and the results

I have an api written in node.js that handles calls coming in from websites, desktop applications, iOS applications etc. There are probably 50+ endpoints and each end point can accept anywhere from 1 parameter to possibly 10-20 depending on what is intendeding to be accomplished. These can be GET/POST/PUT/DEL
I want to start load testing my API and simulating users activities.
What I am looking for is suggestions on how you can capture the API call and the parameters that were passed along with it in a logical way.
I use forever to run my app and everything is written to a log file so my initial reaction was to do something like add a piece of middleware to the express routes that would capture the endpoint as well as the req.params and req.body but then I need to put this middleware in all 50+ routes kind of tedious.
Anyone done something like this before and has a good idea on how to capture calls / data with those calls as well as possibly capturing what is returned from my API.
Perhaps some module?
I need to have this in a readable format to provide to other people so they can structure a fake set of calls... so raw log files aren't really helpful unless they are outputted.... "pretty".
Thanks!
You're on the right track – just add your logger middleware via app.use, which runs the middleware on every request (rather than adding it to each route).
In fact, the Express docs give an example of using logger middleware:
var express = require('express');
var app = express();
// simple logger
app.use(function(req, res, next){
console.log('%s %s', req.method, req.url);
next();
});
Connect (on which Express is built) provides logger middleware, so you can just do:
var logFile = fs.createWriteStream('./myLogFile.log', {flags: 'a'});
app.use(express.logger({stream: logFile}));

Node.js Express: require/use one app within another

I'm facing the following situation. In order to further modulize my software development, I've written a few standard modules stand alone. Think for instance of an login module based upon Express and Passport, allowing users to login with all kinds of social services. The module also contains UI for user management, login, registration, profile, etc.
Now, the thing I'm trying to do is to just drop the Auth app folder (containing the express app, all it's routes, views, models, settings and dependecies) into another Express app (for instance, a CMS) and then load it with something like require('./lib/auth/app.js'). I know this is possible, take a look at Kue.
How would I go about doing this? And how do I manage namespacing problems? I could of cours append /auth/ to each route, but I can imagine the settings (app.use()'s) and public folder would conflict with the 'parent' app.js' settings and public folder.
Thanks in advance,
Fabian
Think I found my answer. So, I found this question, and this one. Guess my terminology was off.
I solved my problem by doing a few things. First of all, I changed all routes and url's to be "namespaced" (not really, but this does the job). All routes now have /auth/ in front of them. I did the same to all links, so that's all working.
Next, I removed the server part from my app.js. So, in stead of doing:
require('http').createServer(app).listen(app.get('port'));
I just do:
module.exports = app;
And I add some custom methods to the app object:
app.isLoggedIn = auth.isLoggedIn;
app.notLoggedIn = auth.notLoggedIn;
Then, in my root app, I just do the following to load the auth app in. Routing, public files, and all other stuff happens magically. pretty cool.
var auth = require('./vendor/auth/app');
var app = express();
app.configure(function() {
app.use(auth); // use our auth app
// do a lot of root-app related stuff...
});
Things still to do:
My auth app uses some session stuff. According to the second link, if I understand correctly, the app.use(session...) stuff in my auth app gets overridden by app.use. Also, I want to define an EJS helper to generate my urls (something like site_url('/facebook/callback') which then points to /auth/facebook/callback). Finally, I need to include settings from my root app. I'm thinking of wrapping my entire app.js (in auth) in a function, to which I pass a config object. Like this:
module.exports = function(config) {
var app = express();
app.set('config', config);
// various app settings, routes, etc
// return app so it's available in my root.
return app;
}
I hope this helps, if you need a bit more information I'll see if I can post some code to a gist. just let me know!

Resources