You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					113 lines
				
				2.6 KiB
			
		
		
			
		
	
	
					113 lines
				
				2.6 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | var uuid = require('uuid/v4') | ||
|  | var CombinedStream = require('combined-stream') | ||
|  | var isstream = require('isstream') | ||
|  | var 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 | ||
|  |   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 |