Home > Blockchain >  Custom Computed Etag for Express.js
Custom Computed Etag for Express.js

Time:05-23

I'm working on a simple local image server that provides images to a web application with some JSON. The web application has pagination that will do a get request "/images?page=X&limit&200" to an express.js server that returns the JSON files in a single array. I want to take advantage of the browser's internal caching such that if a user goes to a previous page the express.js returns an ETAG. I was wondering how this could be achieved with express.js? For this application, I really just want the computation of the ETAG to take in three parameters the page, the directory, and the limit (It doesn't need to consider the whole JSON body). Also this application is for local use only, so I want the server to do the heavy lifting since I figured it be faster than the browser. I did see https://www.npmjs.com/package/etag which seems promising, but I'm not sure how to use it with express.js

Here's a boilerplate of the express.js code I have below:

var express = require('express');
var app = express();
var fs = require('fs');

app.get('/', async (req, res) =>{
  
  let files = [];
  
  let directory = fs.readdirSync("mypath");
  
  let page = parseInt(req.query.page);
  let limit = parseInt(req.query.limit);
  
  for (let i = 0; i < limit;   i) {
    files.push(new Promise((resolve) => {
      fs.readFile(files[i   page * limit].name, (err, data) => {
        // format the data so easy to use for UI
        resolve(JSON.parse(data));
      });
    });
  }
  
  let results = await Promise.all(files);
  // compute an etag here and attach it the results. 
  res.send(results);
});

app.listen(3000);

CodePudding user response:

When your server sends an ETag to the client, it must also be prepared to check the ETag that the client sends back to the server in the If-None-Match header in a subsequent "conditional" request.

If it matches, the server shall respond with status 304; otherwise there is no benefit in using ETags.

var serverEtag = "<compute from page, directory and limit>";
var clientEtag = req.get("If-None-Match");
if (clientEtag === serverEtag) res.status(304).end();
else {
  // Your code from above
  res.set("ETag", serverEtag);
  res.send(results);
}

The computation of the serverEtag could be based on the time of the last modification in the directory, so that it changes whenever any of the images in that directory changes. Importantly, this could be done without carrying out the fs.readFile statements from your code.

  • Related