CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
index.js337 linesDownload Raw Back to raw-body
1/*!2 * raw-body3 * Copyright(c) 2013-2014 Jonathan Ong4 * Copyright(c) 2014-2022 Douglas Christopher Wilson5 * MIT Licensed6 */7 8'use strict'9 10/**11 * Module dependencies.12 * @private13 */14 15var asyncHooks = tryRequireAsyncHooks()16var bytes = require('bytes')17var createError = require('http-errors')18var iconv = require('iconv-lite')19var unpipe = require('unpipe')20 21/**22 * Module exports.23 * @public24 */25 26module.exports = getRawBody27 28/**29 * Module variables.30 * @private31 */32 33var ICONV_ENCODING_MESSAGE_REGEXP = /^Encoding not recognized: /34 35/**36 * Get the decoder for a given encoding.37 *38 * @param {string} encoding39 * @private40 */41 42function getDecoder (encoding) {43  if (!encoding) return null44 45  try {46    return iconv.getDecoder(encoding)47  } catch (e) {48    // error getting decoder49    if (!ICONV_ENCODING_MESSAGE_REGEXP.test(e.message)) throw e50 51    // the encoding was not found52    throw createError(415, 'specified encoding unsupported', {53      encoding: encoding,54      type: 'encoding.unsupported'55    })56  }57}58 59/**60 * Get the raw body of a stream (typically HTTP).61 *62 * @param {object} stream63 * @param {object|string|function} [options]64 * @param {function} [callback]65 * @public66 */67 68function getRawBody (stream, options, callback) {69  var done = callback70  var opts = options || {}71 72  // light validation73  if (stream === undefined) {74    throw new TypeError('argument stream is required')75  } else if (typeof stream !== 'object' || stream === null || typeof stream.on !== 'function') {76    throw new TypeError('argument stream must be a stream')77  }78 79  if (options === true || typeof options === 'string') {80    // short cut for encoding81    opts = {82      encoding: options83    }84  }85 86  if (typeof options === 'function') {87    done = options88    opts = {}89  }90 91  // validate callback is a function, if provided92  if (done !== undefined && typeof done !== 'function') {93    throw new TypeError('argument callback must be a function')94  }95 96  // require the callback without promises97  if (!done && !global.Promise) {98    throw new TypeError('argument callback is required')99  }100 101  // get encoding102  var encoding = opts.encoding !== true103    ? opts.encoding104    : 'utf-8'105 106  // convert the limit to an integer107  var limit = bytes.parse(opts.limit)108 109  // convert the expected length to an integer110  var length = opts.length != null && !isNaN(opts.length)111    ? parseInt(opts.length, 10)112    : null113 114  if (done) {115    // classic callback style116    return readStream(stream, encoding, length, limit, wrap(done))117  }118 119  return new Promise(function executor (resolve, reject) {120    readStream(stream, encoding, length, limit, function onRead (err, buf) {121      if (err) return reject(err)122      resolve(buf)123    })124  })125}126 127/**128 * Halt a stream.129 *130 * @param {Object} stream131 * @private132 */133 134function halt (stream) {135  // unpipe everything from the stream136  unpipe(stream)137 138  // pause stream139  if (typeof stream.pause === 'function') {140    stream.pause()141  }142}143 144/**145 * Read the data from the stream.146 *147 * @param {object} stream148 * @param {string} encoding149 * @param {number} length150 * @param {number} limit151 * @param {function} callback152 * @public153 */154 155function readStream (stream, encoding, length, limit, callback) {156  var complete = false157  var sync = true158 159  // check the length and limit options.160  // note: we intentionally leave the stream paused,161  // so users should handle the stream themselves.162  if (limit !== null && length !== null && length > limit) {163    return done(createError(413, 'request entity too large', {164      expected: length,165      length: length,166      limit: limit,167      type: 'entity.too.large'168    }))169  }170 171  // streams1: assert request encoding is buffer.172  // streams2+: assert the stream encoding is buffer.173  //   stream._decoder: streams1174  //   state.encoding: streams2175  //   state.decoder: streams2, specifically < 0.10.6176  var state = stream._readableState177  if (stream._decoder || (state && (state.encoding || state.decoder))) {178    // developer error179    return done(createError(500, 'stream encoding should not be set', {180      type: 'stream.encoding.set'181    }))182  }183 184  if (typeof stream.readable !== 'undefined' && !stream.readable) {185    return done(createError(500, 'stream is not readable', {186      type: 'stream.not.readable'187    }))188  }189 190  var received = 0191  var decoder192 193  try {194    decoder = getDecoder(encoding)195  } catch (err) {196    return done(err)197  }198 199  var buffer = decoder200    ? ''201    : []202 203  // attach listeners204  stream.on('aborted', onAborted)205  stream.on('close', cleanup)206  stream.on('data', onData)207  stream.on('end', onEnd)208  stream.on('error', onEnd)209 210  // mark sync section complete211  sync = false212 213  function done () {214    var args = new Array(arguments.length)215 216    // copy arguments217    for (var i = 0; i < args.length; i++) {218      args[i] = arguments[i]219    }220 221    // mark complete222    complete = true223 224    if (sync) {225      process.nextTick(invokeCallback)226    } else {227      invokeCallback()228    }229 230    function invokeCallback () {231      cleanup()232 233      if (args[0]) {234        // halt the stream on error235        halt(stream)236      }237 238      callback.apply(null, args)239    }240  }241 242  function onAborted () {243    if (complete) return244 245    done(createError(400, 'request aborted', {246      code: 'ECONNABORTED',247      expected: length,248      length: length,249      received: received,250      type: 'request.aborted'251    }))252  }253 254  function onData (chunk) {255    if (complete) return256 257    received += chunk.length258 259    if (limit !== null && received > limit) {260      done(createError(413, 'request entity too large', {261        limit: limit,262        received: received,263        type: 'entity.too.large'264      }))265    } else if (decoder) {266      buffer += decoder.write(chunk)267    } else {268      buffer.push(chunk)269    }270  }271 272  function onEnd (err) {273    if (complete) return274    if (err) return done(err)275 276    if (length !== null && received !== length) {277      done(createError(400, 'request size did not match content length', {278        expected: length,279        length: length,280        received: received,281        type: 'request.size.invalid'282      }))283    } else {284      var string = decoder285        ? buffer + (decoder.end() || '')286        : Buffer.concat(buffer)287      done(null, string)288    }289  }290 291  function cleanup () {292    buffer = null293 294    stream.removeListener('aborted', onAborted)295    stream.removeListener('data', onData)296    stream.removeListener('end', onEnd)297    stream.removeListener('error', onEnd)298    stream.removeListener('close', cleanup)299  }300}301 302/**303 * Try to require async_hooks304 * @private305 */306 307function tryRequireAsyncHooks () {308  try {309    return require('async_hooks')310  } catch (e) {311    return {}312  }313}314 315/**316 * Wrap function with async resource, if possible.317 * AsyncResource.bind static method backported.318 * @private319 */320 321function wrap (fn) {322  var res323 324  // create anonymous resource325  if (asyncHooks.AsyncResource) {326    res = new asyncHooks.AsyncResource(fn.name || 'bound-anonymous-fn')327  }328 329  // incompatible node.js330  if (!res || !res.runInAsyncScope) {331    return fn332  }333 334  // return bound function335  return res.runInAsyncScope.bind(res, fn, null)336}337