ExpressJs execute a callback after sending a response for every route - javascript

The scenario is to save the data in cache. We have numerous express routes written with complicated logic.
I have to find a way to save the response data in cache. I cannot go to each and every route and check whether this needs to be saved and save the data before sending the response. (If no other go, then this may be the way)
I have tried the following approaches.
https://nodejs.org/api/http.html#http_event_close_1 - using 'close' or 'finish', which fires after sending the response would do the trick. But there is no way I could get the response data in these events.
Also my node version is v0.10.31
Thought of using app.all('*', callback), but i am not sure how to catch the response data for cacheing.
Finally i thought of adding a second callback for routing, app.VERB(path, [callback...], callback), but upon returning the response in first callback, second callback is never called.
Hoping there is a solution for this, and I am stuck in this for more than a week.
The reason why adding logic into each and every routes is a tedious job is that, I need to add a configuration entry specifying which route needs to be cached with an expiry time.
Response needs to be cached in redis server. A cache key will be generated based on the route data and query strings. All those complete user specific information will be saved in a key.
So when the user hits the same route the key will be generated to check if it already exists using app.use and the data will be served without precedding to the successive middlewares.

Define a callback middleware as,
var storeResponseMiddleware = function(req, res, next) {
console.log("storing data in redis....")
..........more stuff
}
Add it to expressJs app as,
app.use(logicRoute)
app.use(storeResponseMiddleware)
Now, for all the responses storeResponseMiddleware will be called. you must call next() inside the route handlers.

Related

How to log userId in a server that handles concurrent requests?

I have an express server, and it handles all kind of functionalities that I want to log. I dont want to log only incoming requests, I want to log for example how much time it took for a certain function that handles data to execute. I also have a client that passes username as a header to each request in the server, and I want the username to be a part of every log. I can't store the username in a class or a global variable, as it won't be correct when multiple requests from different users are made. My logger is a class that you can simply call in order to log, for example: logger.log("blah", payload)
I don't want to pass the userId to every function where I want to log, what can I do?
Things I thought to do:
pass userId to every function, though I don't want to do it
Maybe somehow make the req known to the logger? But I don't know how to do it correctly

Why is express matching two routes?

I have an express API with a bunch of routes.
routes.get('/', perms('read', 'document'), r(CRUD.getAll))
routes.get('/search', perms('read', 'document'), r(CRUD.search))
routes.get('/:id', perms('read', 'document'), r(CRUD.getById))
I made sure to have /search above /:id, however, when a new request comes in to /search, I see both endpoints getting a hit (I added a console.log inside of each function).
I tried flipping the two and in that case, only /:id gets a hit.
Any idea of why this may be happening?
Think about Express routing as an array of handlers (middlewares), that have a matching rule (url). When a request comes in, the router starts checking each item in the array from the beginning. If it matches the rule, then the handler is run (some don't have conditions, so they just run on each request :)). The request chain does not end when a single url is matched! You can execute multiple handlers on the same request (and that's exactly how middlewares work).
Therefore, it really depends on what happens inside your handler. You can tell it to continue with the next item in the list, and if there's a match - the next handler will be executed (like /search and /:id, which will be search again).
Make sure you end your response. Beware if you call next and with what parameters. Post some samples of the handlers in order to debug it more :)

What is the middleware and app.use in expess?

Just want to say at the beginning. I'm really sorry if you will consider this as a duplicate but I'd like to ask you what is the middleware. I know stackoverflow has some similar questions but I'd be glad if you could answer this one. Also what is the .use ? Where do we use it? Thank you very much!
Middleware is a term that refers to request handlers that "pre-process" an incoming request. A given middleware will typically run on lots of incoming requests. Usually, it doesn't send the final response, it just does some setup or pre-processing on the request and then passes the request on to its eventual handler. There are thousands on things that people find to do with middleware.
The general idea is that it's easier to put middleware in one place and configure it to apply to lots of requests rather than have to add it to every single request handler that its supposed to apply to.
I'll offer a few examples:
Check to see if the requester is authenticated/loggedin on the site. If not, then redirect to the login page. If so, then pass the request through to the actual page request handler.
Log usage or performance statistics.
Pre-parse query parameters so they're already parsed for the request handler
Pre-parse post bodies so they're already parsed for the request handler
Preset desired cross origin headers for the response
Hopefully, you can see the general idea that middleware is often used as pre-setup work that can be done in one place rather than having to be added to every single request handler.
Keep in mind that middleware can be configured to determine which incoming requests it gets run for. It can be only for a single URL (not typical), a whole group of URLs such as everything start with a particular path, or all URLs on the entire site.

How do i search in node.js?

I'm using mongoosastic and it's working fine but the problem that I'm facing is that, how do I take the object from .post method and pass it to .get method?
For example:
router.post('/search', function(req, res, next) {
Product.search({ something: 'Something'}, function(err, result) {
if (err) return next(err);
res.redirect('/search') // <--- How do i pass the result object?
});
});
router.get('/search', function(req, res, next) {
res.render('search');
});
I tried another approached where I use req.flash, but I don't really like that approach.
How did you guys solve this problem? it's a really basic search, where user search then it will redirect that user to another page where it either will show the found result or not found.
You don't need to redirect the user to another route with GET to send the response.
You can serve the request in .post and it is perfectly acceptable.
POST and GET are two forms of HTTP Request. No matter what type of request comes to a web server, the response could be anything. It could be a redirect, or an actual web-page, or other types of things such as errors.
I don't think you need this, but just to be complete, for search pages it could be a different scenario. GET requests could be bookmarked in the browser, because all it takes to re-render the page is the URL. But POST requests could not be, because it needs post parameters as well which is in the request's body. If you want to let the users bookmark the page with the result or have a permanent link to the same page with the result, you could serve the request in GET requests (as well). Adding an extra parameter like ?q=search-term to the URL for example ...
This is a sort of sending parameters via GET request. A /search route will also catch a /search?q=search-term URL. You can have access to that using req.query.q and its value would be "search-term" (look at this question for more info). So you can either modify your form to send a GET request instead of POST (<form action="get">...) or you can redirect the user back to the search page using GET and pass the parameter along the URL. And finally serve all the search result in a GET request.
But again, this is more advanced stuff, for what you need to do, generally, it is all good to serve a request whether it is POST or GET or anything else.

(Node.js) How to get URL of a binary file stored in server?

I am developing a service using node.js, which returns a url to a file stored in my service's database. In my program, I save the file to, for example, "./aFolder/filename.jpg". I'm going to use DigitalOcean.
My questions are:
1. What is the form of such a url?
2. How can I get that url in my code using node.js?
Thank you in advance.
The URL will be whatever you want to make it since you'll presumably be the one writing the code to handle incoming requests.
Something like http://uri/download/aFolder/filename.jpg seems like a reasonable choice, but you'd need to write your app to accept those paths.
You may want to look into Express where you can add route handlers via app.route() such that anything to /download gets processed by a particular callback that facilitates the mapping of the URL onto your filesystem and will likely be sending the correct file over using res.download()
A basic skeleton might be:
app.route('/download:path')
.all(function(req, res, next) {
res.download(req.params.path)
})

Categories

Resources