express-negotiator
raw JSON → 1.1.0 verified Sat Apr 25 auth: no javascript
An Express/Connect middleware for content negotiation of static files, inspired by Apache mod_negotiation. Version 1.1.0 has no recent updates. It rewrites req.url based on exact matches, locale GET parameter, cookie, and Accept-Language/Accept headers, in priority order. Differentiates from other negotiation libraries by integrating directly with express.static and handling ETags for conditional requests. Requires cookieParser when using cookie-based locale.
Common errors
error Error: Most middleware (like cookieParser) is no longer bundled with Express and must be installed separately. ↓
cause Express 4+ removed bundled middleware; cookieParser is now in the cookie-parser package.
fix
Run 'npm install cookie-parser' and use 'import cookieParser from 'cookie-parser'' instead of 'express.cookieParser()'.
error TypeError: negotiator is not a function ↓
cause Named import instead of default import in ESM.
fix
Use 'import negotiator from 'express-negotiator'' instead of 'import { negotiator } from 'express-negotiator''.
error Cannot find module 'express-negotiator' ↓
cause Package not installed.
fix
Run 'npm install express-negotiator' in your project directory.
Warnings
gotcha Negotiator rewrites req.url to a negotiated filename, which may affect downstream middleware that inspects req.url. ↓
fix Run negotiator right before express.static and after any middleware that depends on the original url.
deprecated The package uses express.cookieParser() which is deprecated in Express 4+; use cookie-parser middleware instead. ↓
fix Install and use cookie-parser as a separate middleware.
gotcha When no acceptable file is found, req.url is left untouched, which may cause the static middleware to serve a non-negotiated file or 404. ↓
fix Ensure that your static root contains all negotiated variants or handle the case when no match is found.
gotcha The ETag format includes Content-Type and locale, but if you use a CDN or proxy that calculates its own ETag, conditional requests may not work as expected. ↓
fix Disable custom ETag generation in the CDN/proxy or ensure it passes the ETag from the origin.
gotcha If the request URL already exactly matches a file, negotiator does not rewrite, ignoring the negotiation parameters. ↓
fix Design your URL scheme to avoid exact matches when negotiation is desired, e.g., use a path without extension.
Install
npm install express-negotiator yarn add express-negotiator pnpm add express-negotiator Imports
- default wrong
const negotiator = require('express-negotiator')correctimport negotiator from 'express-negotiator' - negotiator wrong
import { negotiator } from 'express-negotiator'correctimport negotiator from 'express-negotiator' - negotiator wrong
const { negotiator } = require('express-negotiator')correctconst negotiator = require('express-negotiator')
Quickstart
import express from 'express';
import negotiator from 'express-negotiator';
import cookieParser from 'cookie-parser';
const root = '/path/to/static/files';
const app = express();
app.use(cookieParser());
app.use(negotiator({ root: root, cookieName: 'locale' }));
app.use(express.static(root));
app.listen(1337, () => {
console.log('Server listening on port 1337');
});