Blame view

node_modules/request/lib/multipart.js 2.61 KB
f7563de62   Palak Handa   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  'use strict'
  
  var uuid = require('uuid')
    , CombinedStream = require('combined-stream')
    , isstream = require('isstream')
    , Buffer = require('safe-buffer').Buffer
  
  
  function Multipart (request) {
    this.request = request
    this.boundary = uuid()
    this.chunked = false
    this.body = null
  }
  
  Multipart.prototype.isChunked = function (options) {
    var self = this
      , chunked = false
      , 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
  ')
    }
  
    parts.forEach(function (part) {
      var preamble = '--' + self.boundary + '\r
  '
      Object.keys(part).forEach(function (key) {
        if (key === 'body') { return }
        preamble += key + ': ' + part[key] + '\r
  '
      })
      preamble += '\r
  '
      add(preamble)
      add(part.body)
      add('\r
  ')
    })
    add('--' + self.boundary + '--')
  
    if (self.request.postambleCRLF) {
      add('\r
  ')
    }
  
    return body
  }
  
  Multipart.prototype.onRequest = function (options) {
    var self = this
  
    var chunked = self.isChunked(options)
      , parts = options.data || options
  
    self.setHeaders(chunked)
    self.chunked = chunked
    self.body = self.build(parts, chunked)
  }
  
  exports.Multipart = Multipart