lib/utils.js JAVASCRIPT 272 lines View on github.com → Search inside
1/*!2 * express3 * Copyright(c) 2009-2013 TJ Holowaychuk4 * Copyright(c) 2014-2015 Douglas Christopher Wilson5 * MIT Licensed6 */78'use strict';910/**11 * Module dependencies.12 * @api private13 */1415var { METHODS } = require('node:http');16var contentType = require('content-type');17var etag = require('etag');18var mime = require('mime-types')19var proxyaddr = require('proxy-addr');20var qs = require('qs');21var querystring = require('node:querystring');22const { Buffer } = require('node:buffer');232425/**26 * A list of lowercased HTTP methods that are supported by Node.js.27 * @api private28 */29exports.methods = METHODS.map((method) => method.toLowerCase());3031/**32 * Return strong ETag for `body`.33 *34 * @param {String|Buffer} body35 * @param {String} [encoding]36 * @return {String}37 * @api private38 */3940exports.etag = createETagGenerator({ weak: false })4142/**43 * Return weak ETag for `body`.44 *45 * @param {String|Buffer} body46 * @param {String} [encoding]47 * @return {String}48 * @api private49 */5051exports.wetag = createETagGenerator({ weak: true })5253/**54 * Normalize the given `type`, for example "html" becomes "text/html".55 *56 * @param {String} type57 * @return {Object}58 * @api private59 */6061exports.normalizeType = function(type){62  return ~type.indexOf('/')63    ? acceptParams(type)64    : { value: (mime.lookup(type) || 'application/octet-stream'), params: {} }65};6667/**68 * Normalize `types`, for example "html" becomes "text/html".69 *70 * @param {Array} types71 * @return {Array}72 * @api private73 */7475exports.normalizeTypes = function(types) {76  return types.map(exports.normalizeType);77};787980/**81 * Parse accept params `str` returning an82 * object with `.value`, `.quality` and `.params`.83 *84 * @param {String} str85 * @return {Object}86 * @api private87 */8889function acceptParams (str) {90  var length = str.length;91  var colonIndex = str.indexOf(';');92  var index = colonIndex === -1 ? length : colonIndex;93  var ret = { value: str.slice(0, index).trim(), quality: 1, params: {} };9495  while (index < length) {96    var splitIndex = str.indexOf('=', index);97    if (splitIndex === -1) break;9899    var colonIndex = str.indexOf(';', index);100    var endIndex = colonIndex === -1 ? length : colonIndex;101102    if (splitIndex > endIndex) {103      index = str.lastIndexOf(';', splitIndex - 1) + 1;104      continue;105    }106107    var key = str.slice(index, splitIndex).trim();108    var value = str.slice(splitIndex + 1, endIndex).trim();109110    if (key === 'q') {111      ret.quality = parseFloat(value);112    } else {113      ret.params[key] = value;114    }115116    index = endIndex + 1;117  }118119  return ret;120}121122/**123 * Compile "etag" value to function.124 *125 * @param  {Boolean|String|Function} val126 * @return {Function}127 * @api private128 */129130exports.compileETag = function(val) {131  var fn;132133  if (typeof val === 'function') {134    return val;135  }136137  switch (val) {138    case true:139    case 'weak':140      fn = exports.wetag;141      break;142    case false:143      break;144    case 'strong':145      fn = exports.etag;146      break;147    default:148      throw new TypeError('unknown value for etag function: ' + val);149  }150151  return fn;152}153154/**155 * Compile "query parser" value to function.156 *157 * @param  {String|Function} val158 * @return {Function}159 * @api private160 */161162exports.compileQueryParser = function compileQueryParser(val) {163  var fn;164165  if (typeof val === 'function') {166    return val;167  }168169  switch (val) {170    case true:171    case 'simple':172      fn = querystring.parse;173      break;174    case false:175      break;176    case 'extended':177      fn = parseExtendedQueryString;178      break;179    default:180      throw new TypeError('unknown value for query parser function: ' + val);181  }182183  return fn;184}185186/**187 * Compile "proxy trust" value to function.188 *189 * @param  {Boolean|String|Number|Array|Function} val190 * @return {Function}191 * @api private192 */193194exports.compileTrust = function(val) {195  if (typeof val === 'function') return val;196197  if (val === true) {198    // Support plain true/false199    return function(){ return true };200  }201202  if (typeof val === 'number') {203    // Support trusting hop count204    return function(a, i){ return i < val };205  }206207  if (typeof val === 'string') {208    // Support comma-separated values209    val = val.split(',')210      .map(function (v) { return v.trim() })211  }212213  return proxyaddr.compile(val || []);214}215216/**217 * Set the charset in a given Content-Type string.218 *219 * @param {String} type220 * @param {String} charset221 * @return {String}222 * @api private223 */224225exports.setCharset = function setCharset(type, charset) {226  if (!type || !charset) {227    return type;228  }229230  // parse type231  var parsed = contentType.parse(type);232233  // set charset234  parsed.parameters.charset = charset;235236  // format type237  return contentType.format(parsed);238};239240/**241 * Create an ETag generator function, generating ETags with242 * the given options.243 *244 * @param {object} options245 * @return {function}246 * @private247 */248249function createETagGenerator (options) {250  return function generateETag (body, encoding) {251    var buf = !Buffer.isBuffer(body)252      ? Buffer.from(body, encoding)253      : body254255    return etag(buf, options)256  }257}258259/**260 * Parse an extended query string with qs.261 *262 * @param {String} str263 * @return {Object}264 * @private265 */266267function parseExtendedQueryString(str) {268  return qs.parse(str, {269    allowPrototypes: true270  });271}

Code quality findings 35

Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var { METHODS } = require('node:http');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var contentType = require('content-type');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var etag = require('etag');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var mime = require('mime-types')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var proxyaddr = require('proxy-addr');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var qs = require('qs');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var querystring = require('node:querystring');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var length = str.length;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var colonIndex = str.indexOf(';');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var index = colonIndex === -1 ? length : colonIndex;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
var index = colonIndex === -1 ? length : colonIndex;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var ret = { value: str.slice(0, index).trim(), quality: 1, params: {} };
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var splitIndex = str.indexOf('=', index);
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (splitIndex === -1) break;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var colonIndex = str.indexOf(';', index);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var endIndex = colonIndex === -1 ? length : colonIndex;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
var endIndex = colonIndex === -1 ? length : colonIndex;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var key = str.slice(index, splitIndex).trim();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var value = str.slice(splitIndex + 1, endIndex).trim();
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (key === 'q') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var fn;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof val === 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof val === 'function') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var fn;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof val === 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof val === 'function') {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof val === 'function') return val;
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof val === 'function') return val;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (val === true) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof val === 'number') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof val === 'number') {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof val === 'string') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof val === 'string') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var parsed = contentType.parse(type);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = !Buffer.isBuffer(body)

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.