Efficient way to use api request header in controller, models in Node Express Js - node.js

I am pretty much new to Node JS. We do have a requirement to use the request header from router to model class.
Let us assume an simple router
router.ts
router.delete(
'/sample/:id',
validateRequest(),
async function (req: Request, res: Response, next: NextFunction) {
try {
const solution: string = req.header('Some Header Value') || '';
await Controller.someMethods(req.params.id, solution);
return res.json(new HttpResponse('SUCCESS', {}, {}));
} catch (err) {
return next(err);
}
},
);
This is our router, Here we should be able to read "solution" in controller, service, and model classes. Right now we have passed this as an argument to different components. Is there any better approach to read the header value which is in the current request scope?
Similarly using components in spring framework, or sesison management or any other better approach other than passing the header value as an argument at each component level.
regards
Eresh

TL; DR; There is no other way than just mapping it manually.
Express is quite minimalistic so we don't such abstractions as Spring, the truth is that Node.js is different from Java. In Java we spawn a thread per request, so every request has a single thread. Whereas Node.js is async and single-threaded, so multiple requests share the same thread so you need to pass the values down your calls because there is no out-of-the-box solution on storing global values for a request.
If you want to have an access to the headers somewhere inside an application you could build a system that does so. The first step is to add the middleware that stores the headers in service with a unique ID associated with it and somehow passes this ID down the road. Then whenever you know the ID you could call the service to get the data for you, though you still will need to pass the ID down the road. I think you should not care about that, and that is okay. I would refactor your code in a way that a Controller methods access req and res then all the logic of working with these objects will be incapsulated here, whereas the service layer will expect raw data that know nothing about the transport layer that controllers operate with. Thus you can call services from another service, because they know nothing about the request and response.
FWIW, if you need a better framework use Nest.js, it is great and advanced, also it uses decorators (in a way similar to annotations in Spring). For instance you could just inject the header value as a call argument for your method in the following way #Header("some-header") solution: string
Best regards.

Related

Express + Typescript. Call controller from another controller

So I have a controller which I want to call from another controller. As you can see I trying to pass parameter {params: {task_id: String(task_id), result}}, but typescript complains that res doesn't have all attributes. How can I make it?
I suggest that you encapsulate the common logic in another function (which's not a controller but a service) and use it in both getCommentById and getCommentsSocketListener.
Every controller needs a response and request object and there's no good way of skipping it.

Change server option in middleware

In Fastify I can specify instance options while creating it, e.g.
const fastify = require('fastify')({logger:true, disableRequestLogging: false});
Is it possible to do this in a middleware registered with the instance?
e.g. if I do something like
fastify.register(myPlugin);
and instance of fastify is passed to myPlugin - can I, for example change its disableRequestLogging value while in the middleware?
The router is the what relies on disableRequestLogging to switch on/off logging for the request and the later response.
if (disableRequestLogging === false) {
childLogger.info({ req: request }, 'incoming request')
}
The router does provide a setup function that allows disableRequestLogging to be changed. You can see fastify.js uses router.setup() late in initialisation here to apply some new values.
The problem is fastify doesn't provide access to router as part of it's public API. Only functions like fastify.get/.post/.route etc which allow access to specific components of the router.
Short of modifying the source, I can't see a way. Not even something dodgey like onkeypatching a function in due to the way fastify variables are scoped. Even if you could do that, it would be delving into undefined/untested behaviours.

At what point are request and response objects populated in express app

I’m always coding backend api’s and I don’t really get how express does its bidding with my code. I know what the request and response objects offer, I just don’t understand how they come to be.
This simplified code for instance:
exports.getBlurts = function() {
return function(req, res) {
// build query…
qry.exec(function(err, results) {
res.json(results);
}
});
}
}
Then I’d call in one of my routes:
app.get('/getblurts/, middleware.requireUser, routes.api.blurtapi.getBlurts());
I get that the function is called upon the route request. It’s very abstract to me though and I don’t understand the when, where, or how as it pertains to the req\res params being injected.
For instance. I use a CMS that modifies the request object by adding a user property, which is then available globally on all requests made whether ajax or otherwise, making it easy at all times to determine if a user is logged in.
Are the req and res objects just pre-cooked by express but allow freedom for them to be modified to your needs? When are they actually 'built'
At its heart express is actually using node's default http-module and passing the express-application as a callback to the http.createServer-function. The request and response objects are populated at that point, i.e. from node itself for every incoming connection. See the nodeJS documentation for more details regarding node's http-module and what req/res are.
You might want to check out express' source code which shows how the express application is passed as a callback to http.createServer.
https://github.com/expressjs/express/blob/master/lib/request.js and https://github.com/expressjs/express/blob/master/lib/response.js show how node's request/response are extended by express specific functions.

API mocking in Mithril for front-end development, like jquery-mockjax

I am using mithril in an IoT framework. I am trying to isolate the front-end development from backend API implementation tasks. In jQuery, I have used jQuery-mockjax and a similar mechanism in Angular. What I understand is that those libraries intercept ajax function call an appropriately respond with data that are setup using $.mockjax (or similar functions)
The mechanism recommended here https://groups.google.com/forum/#!topic/mithriljs/FzpCPMfauf0, does not give the flexibility to implement this. There is no easy way to use mock for a selected few APIs.
After looking through the code, I realized is, to implement this, I need to get access to the ‘ajax’ function (or just the XHR processing section), so that it can be overridden using my own implementation that can mock selected APIs. The problem is that ajax is a local function in the library. If it is exposed as m.ajax, my library can override it and get the functionality I need.
My question is, is there a better way to achieve the same? If you have done similar things please share.
My code structure will be something like this:
// in mithril-mockjax.js, implements mockjax function
m.mockjax = function (options) { … }
// in app-api-mocks.js
m.mockjax({
method: GET,
url: /sessions/123,
response: { …}
});
m.mockjax({
method: POST,
url: /sessions,
data: {},
response: { … }
});
The above two files are inserted in the page when I am in the development mode. The rest of the code remains the same.
You can do this by either mocking m.request by monkey-patching it or you add a layer of abstraction between m.request and your code that you are then able to mock away.

How to avoid fat models in a node.js + mongoose app?

The app is using express 3. Here is a barebones example of a route that fetches data from the database:
var Post = mongoose.model('Post')
app.get('post/:id/loompas', function(req, res) {
Post.getLoompas(function(err, data){
res.render('x', data)
})
})
Where Posts.getSomeData is defined as instance methods in /models/post.js, and sometimes accesses external APIs:
PostSchema.method('getLoompas', function(callback){
var post = this
API.get('y', function(x){
this.save(x)
callback(x)
})
})
This is starting to smell, and doesn't look like it belongs along the Schema definition. The collection of methods could grow quite large.
What design patterns are recommended to separate these concerns and avoid extremely fat models? A service layer for external API calls? Any interesting solutions out there?
This does indeed smell a little bit.
I would use the approach of considering your web app merely as a view of your application.
The best way to ensure this is to never use your mongoose models from your webapp. You could have your webapp living in a process and your model specific logic in another process. The job of that second process would be to take care of your business logic and persistence layer (mongoDB), making it the M in MVC.
Accessing external APIs would take place in that Model layer, we your can separate it from your persistence implementation.
There's a way of communicating between node processes that I like, it's dnode. Once set up, it looks like you are communicating with objects and callbacks within your own process. I would make the webapp and the business app communicating through this in order to get data. The webapp needn't manipulate the actual data and instead sends message to the Model layer (as described by the MVC pattern).
This ensures complete separation between controller/view (webapp) and model+persistence.
One side effect of this organization is that you can easily write other clients of your application, for example a CLI client or a RESTful API.
Are you trying to get id and somedata from url (post/:id/:somedata) ? to construct schema ?
Ideally one should use :
app.post('/reg', function(request, response){
console.log(request.body.name);
console.log(request.body.email);
...
}
which is when form is submitted on the 'reg' HTML form page, where you can set all the variables(name,email) in object. In app.post you can get the schema definition from the request itself without having to scan through the url to get variables.
If you still want to know how to get the variables from the url then do this in app.get:
vars=request.url.split('/');
//vars contains all the variables you have to use.
//use vars to create schema
After you get/create the schema directly pass it to the function / or iterate through the object elements calling that function.

Resources