| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 | 'use strict'var uuid = require('uuid/v4')var CombinedStream = require('combined-stream')var isstream = require('isstream')var Buffer = require('safe-buffer').Bufferfunction Multipart (request) {  this.request = request  this.boundary = uuid()  this.chunked = false  this.body = null}Multipart.prototype.isChunked = function (options) {  var self = this  var chunked = false  var parts = options.data || options  if (!parts.forEach) {    self.request.emit('error', new Error('Argument error, options.multipart.'))  }  if (options.chunked !== undefined) {    chunked = options.chunked  }  if (self.request.getHeader('transfer-encoding') === 'chunked') {    chunked = true  }  if (!chunked) {    parts.forEach(function (part) {      if (typeof part.body === 'undefined') {        self.request.emit('error', new Error('Body attribute missing in multipart.'))      }      if (isstream(part.body)) {        chunked = true      }    })  }  return chunked}Multipart.prototype.setHeaders = function (chunked) {  var self = this  if (chunked && !self.request.hasHeader('transfer-encoding')) {    self.request.setHeader('transfer-encoding', 'chunked')  }  var header = self.request.getHeader('content-type')  if (!header || header.indexOf('multipart') === -1) {    self.request.setHeader('content-type', 'multipart/related; boundary=' + self.boundary)  } else {    if (header.indexOf('boundary') !== -1) {      self.boundary = header.replace(/.*boundary=([^\s;]+).*/, '$1')    } else {      self.request.setHeader('content-type', header + '; boundary=' + self.boundary)    }  }}Multipart.prototype.build = function (parts, chunked) {  var self = this  var body = chunked ? new CombinedStream() : []  function add (part) {    if (typeof part === 'number') {      part = part.toString()    }    return chunked ? body.append(part) : body.push(Buffer.from(part))  }  if (self.request.preambleCRLF) {    add('\r\n')  }  parts.forEach(function (part) {    var preamble = '--' + self.boundary + '\r\n'    Object.keys(part).forEach(function (key) {      if (key === 'body') { return }      preamble += key + ': ' + part[key] + '\r\n'    })    preamble += '\r\n'    add(preamble)    add(part.body)    add('\r\n')  })  add('--' + self.boundary + '--')  if (self.request.postambleCRLF) {    add('\r\n')  }  return body}Multipart.prototype.onRequest = function (options) {  var self = this  var chunked = self.isChunked(options)  var parts = options.data || options  self.setHeaders(chunked)  self.chunked = chunked  self.body = self.build(parts, chunked)}exports.Multipart = Multipart
 |