expressjs / express

Fast, unopinionated, minimalist web framework for node.
https://expressjs.com
MIT License
65.62k stars 16.21k forks source link

custom ETag function isn't working for SendFile #4750

Open kokushkin opened 2 years ago

kokushkin commented 2 years ago

I set the custom function according to the http://expressjs.com/en/api.html#etag.options.table

app.set('etag', function (body, encoding) {
  return generateHash(body, encoding) // consider the function is defined
})

Despite on that it's not working and the best way I could influence etag value is to call sendFile with etag : true or false but this just turns on and off the standard etag (also not documented) , not the custom one.

https://github.com/expressjs/express/issues/2294 https://github.com/expressjs/express/issues/2129

My use case is that I want to track responses of specific files. So I wanted to make a "strong hash" that I can be 100% sure would unambiguously represent the file.

dougwilson commented 2 years ago

Hi @kokushkin thank you for bringing this up. Yes, the current etag setting does not affect files, as calculating an etag for a file is noy always trivial. For example, a file can be multiple gigabytes in size and it is not practical to hold the entire contents of a file in memory in order to invoke the etag setting.

You can currently calcualte your etag and set the etag header using res.header and it will not be replaced by the framework.

We can determine what kind of API would be needed otherwise in order to assist in calculating the etag for a file. What do yoi currently do to calculate the etag of these files, may I ask?

kokushkin commented 2 years ago

Well, I've solved my problem by just calculated it's sha256 digest using "crypto" and writing the result into the log. But initially I tried to use "morgan" together with the standard ETag functionality of "express". I think I even tried to make it explicitly with res.header and it didn't work out (morgan was enable to access etag for some reason) but I'm not sure, I might try it again and give you feedback). So, the initial thought was to hook into the process and say I wanna get absolutely unique digest for some types of files, let's say *.jpg files no matter where they are in the routes and I couldn't do it so I have to explore the routes.

juanarbol commented 2 weeks ago

This could be solved w/ something like:

res.sendfile(yourPath, { headers: { etag: 'your-etag' } })

Not sure how would you calculate etags in a file stream, what could the "chunk" arg be if not "data" from the filestream.