How does Express.js handle Cache-Control automatically? - node.js

I was going to use a 'cache buster' to add a hash to the end of static js and css files during grunt build. I don't know too much about cache control. Without doing anything Express.js was sending a 304 status code. If I modified the file then Express.js would send the new file. It seems like I don't need to do anything and it works as expected.
Do I need to implement Cache-Control? Is it already handled auto magically?

Yes, express handles cache-control automatically. It's default value is set to true. And you can just handle it by increasing/decreasing it's maxAge property value. (in milliseconds). Or you can turn this option on or off by setting cacheControl to true or false .
For more Reference you can refer : Express Documentation

Related

What does this immutable property in options object of express.static used for?

I am a newbie to Node and Express, trying to explore things. I was going through the Express' documentation at this link: https://expressjs.com/en/4x/api.html#express.static
Here, The description of the immutable property passed in options says:
Enable or disable the immutable directive in the Cache-Control response header. If enabled, the maxAge option should also be specified to enable caching. The immutable directive will prevent supported clients from making conditional requests during the life of the maxAge option to check if the file has changed.
I am unable to understand this. I've understood how maxAge is used but not able to get this immutable.
When and How is this property used?
Thanks in advance for any help you are able to provide
It's used for caching resources. Immutable here implies that it won't change(mutate). If you're delivering static assets through your express routes, the browser can use it's cache instead of verifying the asset's validity when the page refreshes. The maxAge directive here sets the duration for which the asset is immutable.
This simply means less server requests when you navigate or refresh pages.
You can use it in your routes by setting the response header before sending the response or you could create a middleware to plug-in between your routes.
router.get('/assets/*', function (req, res, next) {
res.setHeader('Cache-Control', 'max-age=36000,immutable');
res.send({});
}

How can update static files in node js app?

I have nodejs app using express module, i had been changes some images inside public folder but when i checked from users side still on the old images and when clear browser cache i get on new images , is there a command to make this automatically.
Have a look at Etag. If the content of the resource is not changed the server will not send it again. When it is, as in your case it will.
Looking at the express docs I see etag is an boolean option of the middleware function static.
express.static({etag: true})
Some background information about tags.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag

Express.js trying to set express.static with variables

I have template settings that vary depending on the subdomain I’m using. Therefore I’m trying to find a way to set the express.static dynamically based on the subdomain name I’m using.
When app.use runs, template is undefined. If I run app.use inside app.get it is out of scope. And if I try to run app.use from a function it is also out of scope.
"template" is a variable that I get in app.get it is my subdomain and http request
app.use('/subdomain/:domain/bower',express.static(path.join(__dirname, '/public/' + **template** + '/bower')));
app.get('/subdomain/:domain',function(req,res,next) {
get('/stores/template/' + req.params.domain)
.then(function(body){
console.log("template: " + body.toString());
template = body;
res.render('store',{store:req.params.domain});
});
});
I’m pretty sure it has to do with scopes, but so far I haven’t been able to solve it. Any help would be appreciated
Your first app.use() and the express.static() call in it runs when your sever is first starting up. At that point, the template variable does not yet have a value. You can't really do things the way you're trying to do it.
app.get() runs immediately also, but its callback is not called until sometime in the future when an http request matching that route actually arrives. By then, when the template variable gets assigned, it's way too late for it to be useful in your prior app.use() statement.
This would be much easier if your server could just know which sub-domain it was serving when it was originally set up from a configuration file or something like that. If you intend for the same server to serve many sub-domains at once and you want it to serve different files based on the subdomain, then you will have to code completely differently because you can't just use plain route matching like express.static() does since what you really want is sub-domain + route matching which isn't a built-in feature that I'm aware of.
I think if I was trying to solve this, I'd have my first middleware examine the sub-domain of the request and insert it into the front of the URL making a unique pseudo-URL for each sub-domain. Then, you could do normal routing on that pseudo-URL which is what the rest of the middleware and routes will see as the request URL.

Does express.static() cache files in the memory?

In ExpressJS for NodeJS, we can do the following:
app.use(express.static(__dirname + '/public'));
to serve all the static CSS, JS, and image files. My questions are these:
1) When we do that, does Express automatically cache the files in the server's memory or does it read from the hard disk every time one of the resources is served?
2) When we do that, does Express, using ETag by default, save the resources on the client's hard disk, or on the client's memory only?
The static middleware does no server-side caching. It lets you do two methods of client-side caching: ETag and Max-Age:
If the browser sees the ETag with the page, it will cache it. The next time the browser loads the page it checks for the ETag number changes. If the file is exactly the same, and so is its ETag - the server responds with an HTTP 304("not modified") status code instead of sending all the bytes again and saves a bunch of bandwidth.
Etag is turned-on by default but you can turn it off like this:
app.use(express.static(myStaticPath, {
etag: false
}))
Max-age is will set the max-age to some amount of time so the browser will only request that resource after one day has passed.
app.use(express.static(myStaticPath, {
maxAge: '5000' // uses milliseconds per docs
}))
For more details you can read this article
By default it's on the hard-drive, but someone can use something like this

node.js body on http request object vs body on express request object

I'm trying to build an http module that suppose to work with an express server.
while reading the http module api, I see that it doesn't save the body inside the request object.
So my questions are:
If I want to build an express server which works with the official http module, how should I get the body?
I consider to implement the http module in the following way: listening to the socket, and if I get content-length header, listetning to the rest of the socket stream till I get all the body, save it as a memeber of the http request, and only then send the request object to the express server handler.
What are the pros and cons of my suggestion above vs letting the express server to "listen" to the body of the request via request.on('data',callback(data))
I mean , why shouldn't I keep the body inside the 'request' object the same way I keep the headers?
It's hard to answer your question without knowing exactly what you want to do. But I can give you some detail about how the request body is handled by Node/Express, and hopefully you can take things from there.
When handling a request (either directly via Node's request handler, or through Express's request handlers), the body of the request won't automatically be received: you have to open an HTTP stream to receive it.
The type of the body content should be determined by the Content-Type request header. The two most common body types are application/x-www-form-urlencoded and multipart/form-data. It's possible, however, to use any content type you want, which is usually more common for APIs (for example, using application/json is becoming more common for REST APIs).
application/x-www-form-urlencoded is pretty straightforward; name=value pairs are URL encoded (using JavaScript's built-in encodeURIComponent, for example), then combined with an ampersand (&). They're usually UTF-8 encoded, but that can also be specified in Content-Type.
multipart/form-data is more complicated, and can also typically be quite large, as vkurchatkin's answer points out (meaning you may not want to bring it into memory).
Express makes available some middleware to automatically handle the various types of body parsing. Usually, people simply use bodyParser, though you have to be careful with that middleware. It's really just a convenience middleware that combines json, urlencoded, and multipart. However, multipart has been deprecated. Express is still bundling Connect 2.12, which still includes multipart. When Express updates its dependency, though, the situation will change.
As I write this, bodyParser, json, urlencoded, and multipart have all been removed from Connect. Everything but multipart has been moved into the module body-parser (https://github.com/expressjs/body-parser). If you need multipart support, I recommend Busboy (https://npmjs.org/package/busboy), which is very robust. At some point, Express will update it's dependency on Connect, and will most likely add a dependency to body-parser since it has been removed from Connect.
So, since bodyParser bundles deprecated code (multipart), I recommend explicitly linking in only json and urlencoded (and you could even omit json if you're not accepting any JSON-encoded bodies):
app.use(express.json());
app.use(express.urlencoded());
If you're writing middleware, you probably don't want to automatically link in json and urlencoded (much less Busboy); that would break the modular nature of Express. However, you should specify in your documentation that your middleware requires the req.body object to be available (and fail gracefully if it isn't): you can go on to say that json, urlencoded, and Busboy all provide the req.body object, depending on what kind of content types you need to accept.
If you dig into the source code for urlencoded or json, you will find that they rely on another Node module, raw-body, which simply opens the request stream and retrieves the body content. If you really need to know the details of retrieving the body from a request, you will find everything you need in the source code for that module (https://github.com/stream-utils/raw-body/blob/master/index.js).
I know that's a lot of detail, but they're important details!
You can do that, it fairly simple. bodyParser middleware does that, for example (https://github.com/expressjs/body-parser/blob/master/index.js#L27). The thing is, request body can be really large (file upload, for example), so you generally don't want to put that in memory. Rather you can stream it to disk or s3 or whatnot.

Resources