superagent
Version:
elegant & feature rich browser / node HTTP with a fluent API
157 lines (132 loc) • 3.02 kB
JavaScript
/*!
* superagent - Part
* Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var utils = require('./utils')
, Stream = require('stream').Stream
, mime = require('mime')
, path = require('path')
, basename = path.basename;
/**
* Expose `Part`.
*/
module.exports = Part;
/**
* Initialize a new `Part` for the given `req`.
*
* @param {Request} req
* @api public
*/
function Part(req) {
this.req = req;
this.header = {};
this.headerSent = false;
this.request = req.request();
this.writable = true;
if (!req._boundary) this.assignBoundary();
}
/**
* Inherit from `Stream.prototype`.
*/
Part.prototype.__proto__ = Stream.prototype;
/**
* Assign the initial request-level boundary.
*
* @api private
*/
Part.prototype.assignBoundary = function(){
var boundary = utils.uid(32);
this.req.set('Content-Type', 'multipart/form-data; boundary=' + boundary);
this.req._boundary = boundary;
};
/**
* Set header `field` to `val`.
*
* @param {String} field
* @param {String} val
* @return {Part} for chaining
* @api public
*/
Part.prototype.set = function(field, val){
if (!this._boundary) {
// TODO: formidable bug
if (!this.request._hasFirstBoundary) {
this.request.write('--' + this.req._boundary + '\r\n');
this.request._hasFirstBoundary = true;
} else {
this.request.write('\r\n--' + this.req._boundary + '\r\n');
}
this._boundary = true;
}
this.request.write(field + ': ' + val + '\r\n');
return this;
};
/**
* Set _Content-Type_ response header passed through `mime.lookup()`.
*
* Examples:
*
* res.type('html');
* res.type('.html');
*
* @param {String} type
* @return {Part}
* @api public
*/
Part.prototype.type = function(type){
return this.set('Content-Type', mime.lookup(type));
};
/**
* Set _Content-Disposition_ header field to _form-data_
* and set the _name_ param to the given string.
*
* @param {String} name
* @return {Part}
* @api public
*/
Part.prototype.name = function(name){
this.set('Content-Disposition', 'form-data; name="' + name + '"');
return this;
};
/**
* Set _Content-Disposition_ header field to _attachment_ with `filename`
* and field `name`.
*
* @param {String} name
* @param {String} filename
* @return {Part}
* @api public
*/
Part.prototype.attachment = function(name, filename){
this.type(filename);
this.set('Content-Disposition', 'attachment; name="' + name + '"; filename="' + basename(filename) + '"');
return this;
};
/**
* Write `data` with `encoding`.
*
* @param {Buffer|String} data
* @param {String} encoding
* @return {Boolean}
* @api public
*/
Part.prototype.write = function(data, encoding){
if (!this._headerCRLF) {
this.request.write('\r\n');
this._headerCRLF = true;
}
return this.request.write(data, encoding);
};
/**
* End the part.
*
* @api public
*/
Part.prototype.end = function(){
this.emit('end');
this.complete = true;
};