HTTP ETag Generator
The `etag` package is a minimalist, RFC 7232-compliant utility for generating HTTP ETags in Node.js applications. It currently maintains a stable version 1.8.1 and has a low release cadence, reflecting its maturity and focused scope. The library supports generating strong ETags for strings and `Buffer`s, and weak ETags by default for `fs.Stats` objects, with an option to override this behavior. Key differentiators include its strict adherence to the HTTP ETag specification, performance optimization for various entity sizes, and a history of robust integration within the `jshttp` ecosystem, often used by popular HTTP frameworks like Express. It prioritizes correctness and efficiency in ETag calculation, having evolved through several hashing algorithm updates to improve security and performance.
Common errors
-
TypeError: entity must be a string, Buffer or fs.Stats
cause The `etag` function was called with an unsupported data type for the `entity` argument (e.g., `null`, `undefined`, a number, or a complex object that isn't `fs.Stats`).fixEnsure the first argument passed to `etag()` is a `string`, a `Buffer` instance, or an `fs.Stats` object (or a compatible mock object mimicking properties like `mtime`, `size`, `ino`). -
ETags generated are inconsistent between different deployments or environments.
cause This issue typically arises when different versions of the `etag` package are used across environments. Past updates to `etag` have changed the underlying hashing algorithms (e.g., from MD5 to SHA1) or ETag generation logic, leading to different output for the same input.fixTo guarantee consistent ETag generation, ensure that the `etag` package version is locked and identical across all deployment environments. Use package manager commands like `npm ci` or `yarn install --frozen-lockfile` to enforce exact dependency versions.
Warnings
- breaking In `v1.8.0`, the underlying hashing algorithm for ETag generation was changed from MD5 to SHA1. This means ETags generated by `v1.8.0` and later will differ from those generated by prior versions for the same entity, potentially invalidating existing client caches.
- breaking Version `v1.7.0` introduced significant changes to ETag generation logic. This included always incorporating entity length, generating non-Stats ETags using only MD5 (CRC32 removed), and removing base64 padding. These changes result in different ETag values compared to `v1.6.0` and earlier.
- gotcha By default, `etag` generates strong ETags for strings and `Buffer`s, but a weak ETag for `fs.Stats` objects. If you require a strong ETag for `fs.Stats` or a weak ETag for strings/buffers, you must explicitly set the `options.weak` flag.
Install
-
npm install etag -
yarn add etag -
pnpm add etag
Imports
- etag
import { etag } from 'etag';import etag from 'etag';
- etag (CommonJS)
import etag from 'etag';
const etag = require('etag');
Quickstart
import etag from 'etag';
// Scenario 1: Generating a strong ETag for a string entity
const stringBody = '<h1>Hello World!</h1>';
const strongStringEtag = etag(stringBody);
console.log(`Strong ETag for string: ${strongStringEtag}`);
// Scenario 2: Generating a weak ETag for a string entity
const weakStringEtag = etag(stringBody, { weak: true });
console.log(`Weak ETag for string: ${weakStringEtag}`);
// Scenario 3: Generating a strong ETag for a Buffer entity
const bufferBody = Buffer.from('<p>This is a buffered response.</p>');
const strongBufferEtag = etag(bufferBody);
console.log(`Strong ETag for buffer: ${strongBufferEtag}`);
// Scenario 4: Generating a weak ETag for a Buffer entity
const weakBufferEtag = etag(bufferBody, { weak: true });
console.log(`Weak ETag for buffer: ${weakBufferEtag}`);
// Scenario 5: How it's typically used in an HTTP response (conceptual)
// (Imagine `res` is an HTTP response object in a web framework)
// const res = {
// setHeader: (name, value) => console.log(`Setting Header: ${name}: ${value}`)
// };
// const responseBody = 'Some dynamic content';
// res.setHeader('ETag', etag(responseBody));
// console.log("Header set for responseBody.");