HTTP content negotiation library for Node.js applications that selects the best response format based on client Accept headers
npx @tessl/cli install tessl/npm-negotiator@1.0.0Negotiator is an HTTP content negotiation library for Node.js applications that automatically selects the most appropriate response format based on client preferences expressed in HTTP Accept headers. It supports negotiation for media types, languages, character sets, and encodings, parsing quality values and priority rankings to determine optimal matches from available options.
npm install negotiatorconst Negotiator = require('negotiator');const Negotiator = require('negotiator');
// Create negotiator from request object
const negotiator = new Negotiator(request);
// Negotiate media types
const availableTypes = ['text/html', 'application/json', 'text/plain'];
const preferredType = negotiator.mediaType(availableTypes);
// Returns: 'text/html' (if client prefers HTML)
// Negotiate languages
const availableLanguages = ['en', 'es', 'fr'];
const preferredLanguage = negotiator.language(availableLanguages);
// Returns: 'en' (if client prefers English)
// Negotiate encodings
const availableEncodings = ['gzip', 'identity'];
const preferredEncoding = negotiator.encoding(availableEncodings);
// Returns: 'gzip' (if client accepts gzip)Negotiator is built around a single constructor class that provides:
Negotiates the best media type from the Accept header based on client preferences and available options.
/**
* Create a Negotiator instance from a request object
* @param {Object} request - HTTP request object with headers property
*/
function Negotiator(request);
/**
* Returns the most preferred media type from client
* @param {string[]} [available] - Array of available media types
* @returns {string|undefined} Most preferred media type, '*/*' if no Accept header, or undefined if none match
*/
Negotiator.prototype.mediaType(available);
/**
* Returns array of preferred media types ordered by client preference
* @param {string[]} [available] - Array of available media types
* @returns {string[]} Array of media types in preference order
*/
Negotiator.prototype.mediaTypes(available);Usage Examples:
const negotiator = new Negotiator(request);
// Get all client preferences in order
const allTypes = negotiator.mediaTypes();
// Returns: ['text/html', 'application/json', 'text/plain']
// Get best match from available types
const available = ['application/json', 'text/plain'];
const best = negotiator.mediaType(available);
// Returns: 'application/json' (if client prefers JSON over plain text)Negotiates the best language from the Accept-Language header based on client preferences and available options.
/**
* Returns the most preferred language from client
* @param {string[]} [available] - Array of available languages
* @returns {string|undefined} Most preferred language, '*' if no Accept-Language header, or undefined if none match
*/
Negotiator.prototype.language(available);
/**
* Returns array of preferred languages ordered by client preference
* @param {string[]} [available] - Array of available languages
* @returns {string[]} Array of languages in preference order
*/
Negotiator.prototype.languages(available);Usage Examples:
const negotiator = new Negotiator(request);
// Get client language preferences
const languages = negotiator.languages();
// Returns: ['en-US', 'en', 'es'] (based on Accept-Language header)
// Find best match from available languages
const available = ['en', 'fr', 'de'];
const bestLanguage = negotiator.language(available);
// Returns: 'en' (if client prefers English)Negotiates the best character set from the Accept-Charset header based on client preferences and available options.
/**
* Returns the most preferred charset from client
* @param {string[]} [available] - Array of available charsets
* @returns {string|undefined} Most preferred charset, '*' if no Accept-Charset header, or undefined if none match
*/
Negotiator.prototype.charset(available);
/**
* Returns array of preferred charsets ordered by client preference
* @param {string[]} [available] - Array of available charsets
* @returns {string[]} Array of charsets in preference order
*/
Negotiator.prototype.charsets(available);Usage Examples:
const negotiator = new Negotiator(request);
// Get charset preferences
const charsets = negotiator.charsets();
// Returns: ['utf-8', 'iso-8859-1'] (if no Accept-Charset, defaults to '*')
// Find best charset match
const available = ['utf-8', 'iso-8859-1', 'ascii'];
const bestCharset = negotiator.charset(available);
// Returns: 'utf-8' (if client prefers UTF-8)Negotiates the best encoding from the Accept-Encoding header based on client preferences and available options. Supports preferred encoding arrays for tie-breaking.
/**
* Returns the most preferred encoding from client
* @param {string[]} [available] - Array of available encodings
* @param {Object} [options] - Options object
* @param {string[]} [options.preferred] - Preferred encodings for tie-breaking
* @returns {string|undefined} Most preferred encoding, 'identity' if no Accept-Encoding header, or undefined if none match
*/
Negotiator.prototype.encoding(available, options);
/**
* Returns array of preferred encodings ordered by client preference
* @param {string[]} [available] - Array of available encodings
* @param {Object} [options] - Options object
* @param {string[]} [options.preferred] - Preferred encodings for tie-breaking
* @returns {string[]} Array of encodings in preference order
*/
Negotiator.prototype.encodings(available, options);Usage Examples:
const negotiator = new Negotiator(request);
// Get encoding preferences
const encodings = negotiator.encodings();
// Returns: ['gzip', 'deflate', 'identity'] (based on Accept-Encoding)
// Find best encoding with server preferences
const available = ['gzip', 'deflate', 'identity'];
const options = { preferred: ['gzip', 'deflate'] };
const bestEncoding = negotiator.encoding(available, options);
// Returns: 'gzip' (if client accepts and server prefers gzip)
// Identity encoding is automatically added with lowest quality if not specified
const identityIncluded = negotiator.encodings(['gzip']);
// Returns: ['gzip', 'identity'] (identity added automatically)Legacy method names are supported for backward compatibility:
// These are aliases to the main methods
Negotiator.prototype.preferredCharset = Negotiator.prototype.charset;
Negotiator.prototype.preferredCharsets = Negotiator.prototype.charsets;
Negotiator.prototype.preferredEncoding = Negotiator.prototype.encoding;
Negotiator.prototype.preferredEncodings = Negotiator.prototype.encodings;
Negotiator.prototype.preferredLanguage = Negotiator.prototype.language;
Negotiator.prototype.preferredLanguages = Negotiator.prototype.languages;
Negotiator.prototype.preferredMediaType = Negotiator.prototype.mediaType;
Negotiator.prototype.preferredMediaTypes = Negotiator.prototype.mediaTypes;Single methods (.mediaType(), .language(), .charset(), .encoding()):
*/*, *, *, identity respectively)undefined when no acceptable match is found from available optionsArray methods (.mediaTypes(), .languages(), .charsets(), .encodings()):
const negotiator = new Negotiator(request);
// No matching media type from available options
const result = negotiator.mediaType(['application/xml']);
// Returns: undefined (if client doesn't accept XML)
// No Accept header present - returns default
const defaultType = negotiator.mediaType();
// Returns: '*/*' (RFC 2616 default)
// Array method with no header - returns default array
const allTypes = negotiator.mediaTypes();
// Returns: ['*/*'] (default array when no Accept header)Negotiator follows RFC 2616 specifications for HTTP content negotiation:
text/html;q=0.8)* for charset, */* for media types)*/*, text/*, *)/**
* HTTP request object expected by Negotiator constructor
*/
interface Request {
headers: {
accept?: string;
'accept-language'?: string;
'accept-charset'?: string;
'accept-encoding'?: string;
};
}
/**
* Options object for encoding negotiation
*/
interface EncodingOptions {
preferred?: string[];
}