Caseless object manipulation for HTTP headers with case-insensitive access while preserving original casing
npx @tessl/cli install tessl/npm-caseless@0.12.0Caseless provides an object wrapper for case-insensitive property access while preserving the original casing of keys. It's specifically designed for working with HTTP headers where case sensitivity can cause issues but the original casing needs to be maintained for compatibility.
npm install caselessCommonJS (primary pattern):
const caseless = require('caseless');const caseless = require('caseless');
// Create a caseless wrapper for an object
const headers = {};
const c = caseless(headers);
// Set headers with case preservation
c.set('Content-Type', 'application/json');
c.set('User-Agent', 'MyApp/1.0');
// Get values case-insensitively
console.log(c.get('content-type')); // 'application/json'
console.log(c.get('USER-AGENT')); // 'MyApp/1.0'
// Check for existence with original casing returned
console.log(c.has('content-type')); // 'Content-Type'
// Original object maintains the first casing used
console.log(headers); // { 'Content-Type': 'application/json', 'User-Agent': 'MyApp/1.0' }Creates a new caseless wrapper around an object.
/**
* Creates a caseless wrapper for an object
* @param {Object} [dict] - Optional initial object to wrap
* @returns {Caseless} Caseless instance
*/
function caseless(dict)Sets a property with case-insensitive behavior and optional value concatenation.
/**
* Sets a property value with caseless semantics
* @param {string|Object} name - Property name or object of key-value pairs
* @param {string} [value] - Property value (when name is string)
* @param {boolean} [clobber=true] - Whether to overwrite existing values
* @returns {string|false} Original casing of existing key if found, false if not found
*/
set(name, value, clobber)Usage Examples:
const headers = {};
const c = caseless(headers);
// Basic setting
c.set('Content-Type', 'application/json');
// Case-insensitive overwrite (default behavior)
c.set('content-type', 'text/html');
console.log(headers); // { 'Content-Type': 'text/html' }
// Append values with clobber=false
c.set('Accept', 'text/html');
c.set('accept', 'application/json', false);
console.log(c.get('Accept')); // 'text/html,application/json'
// Set multiple properties at once
c.set({
'User-Agent': 'MyApp/1.0',
'Authorization': 'Bearer token123'
});Retrieves a property value using case-insensitive lookup.
/**
* Gets a property value using case-insensitive lookup
* @param {string} name - Property name (case-insensitive)
* @returns {string|undefined} Property value or undefined if not found
*/
get(name)Checks if a property exists and returns the original casing.
/**
* Checks if property exists and returns original casing
* @param {string} name - Property name (case-insensitive)
* @returns {string|false} Original casing of key if found, false otherwise
*/
has(name)Usage Example:
c.set('Content-Length', '1024');
console.log(c.has('content-length')); // 'Content-Length'
console.log(c.has('nonexistent')); // falseChanges the casing of an existing property key.
/**
* Swaps the casing of an existing property key
* @param {string} name - New casing for the property key
* @throws {Error} If no matching property is found
*/
swap(name)Usage Example:
c.set('content-type', 'application/json');
c.swap('Content-Type');
console.log(c.has('content-type')); // 'Content-Type'Deletes a property using case-insensitive lookup.
/**
* Deletes a property using case-insensitive lookup
* @param {string} name - Property name (case-insensitive)
* @returns {boolean} Result of delete operation
*/
del(name)Access the underlying dictionary object directly.
/**
* Direct access to the internal dictionary object
* @type {Object} The underlying object storing key-value pairs
*/
caselessInstance.dictUsage Example:
const headers = {};
const c = caseless(headers);
c.set('Content-Type', 'application/json');
// Direct access to internal dictionary
console.log(c.dict); // { 'Content-Type': 'application/json' }
// Both references point to the same object
console.log(c.dict === headers); // trueIntegrates caseless functionality with Node.js HTTP response objects.
/**
* Integrates caseless functionality with Node.js HTTP response objects
* @param {Object} resp - HTTP response object to modify
* @param {Object} [headers] - Optional initial headers object
* @returns {Caseless} The caseless instance created
*/
caseless.httpify(resp, headers)Usage Example:
const http = require('http');
const caseless = require('caseless');
const server = http.createServer((req, res) => {
// Enhance response object with caseless header methods
const c = caseless.httpify(res, {
'Content-Type': 'application/json',
'Server': 'MyServer/1.0'
});
// Use enhanced methods
res.setHeader('Cache-Control', 'no-cache');
console.log(res.hasHeader('cache-control')); // 'Cache-Control'
console.log(res.getHeader('content-type')); // 'application/json'
res.end(JSON.stringify({ message: 'Hello' }));
});The httpify method adds the following methods to the response object:
resp.setHeader(key, value, clobber) - Case-insensitive header setting (ignores calls with undefined value)resp.hasHeader(key) - Case-insensitive header existence checkresp.getHeader(key) - Case-insensitive header retrievalresp.removeHeader(key) - Case-insensitive header removalresp.headers - Reference to the internal headers objectswap() method throws an Error with message "There is no header than matches "[name]"" if no matching property is foundfalse or undefined for missing keys rather than throwingclobber=false