Comparing version 0.2.7 to 0.2.8
176
index.js
@@ -14,3 +14,4 @@ /** | ||
var StringDecoder = require('string_decoder').StringDecoder; | ||
var querystring = require('querystring'); | ||
var QueryString = require('querystring'); | ||
var FormData = require('form-data'); | ||
var Stream = require('stream'); | ||
@@ -20,2 +21,3 @@ var mime = require('mime'); | ||
var path = require('path'); | ||
var URL = require('url'); | ||
var fs = require('fs'); | ||
@@ -40,8 +42,7 @@ | ||
/** | ||
* Container to hold headers with lowercased field-names. | ||
* Stream Multipart form-data request | ||
* | ||
* @type {Object} | ||
* @private | ||
* @type {Boolean} | ||
*/ | ||
_headers: {}, | ||
_stream: false, | ||
@@ -92,3 +93,29 @@ /** | ||
hasHeader: function (name) { | ||
var headers; | ||
var lowercaseHeaders; | ||
name = name.toLowerCase(); | ||
headers = Object.keys($this.options.headers); | ||
lowercaseHeaders = headers.map(function (header) { return header.toLowerCase(); }); | ||
for (var i = 0; i < lowercaseHeaders.length; i++) | ||
if (lowercaseHeaders[i] === name) | ||
return headers[i]; | ||
return false; | ||
}, | ||
/** | ||
* Turn on multipart-form streaming | ||
* | ||
* @return {Object} | ||
*/ | ||
stream: function () { | ||
$this._stream = true; | ||
return this; | ||
}, | ||
/** | ||
* Attaches a field to the multipart-form request. | ||
@@ -102,3 +129,3 @@ * | ||
*/ | ||
field: function (name, value) { | ||
field: function (name, value, options) { | ||
if (is(name).a(Object)) { | ||
@@ -111,3 +138,4 @@ for (var key in name) | ||
value: value, | ||
attachment: false | ||
options: options, | ||
attachment: false, | ||
}); | ||
@@ -126,3 +154,3 @@ } | ||
*/ | ||
attach: function (name, path) { | ||
attach: function (name, path, options) { | ||
if (is(name).a(Object)) { | ||
@@ -135,2 +163,3 @@ for (var key in name) | ||
value: path, | ||
options: options, | ||
attachment: true | ||
@@ -179,4 +208,5 @@ }); | ||
$this.options.headers[field] = value; | ||
$this._headers[field.toLowerCase()] = value; | ||
var existingHeaderName = $this.hasHeader(field); | ||
$this.options.headers[existingHeaderName || field] = value; | ||
return $this; | ||
@@ -192,5 +222,4 @@ }, | ||
query: function (value) { | ||
if (is(value).a(Object)) value = querystring.stringify(value); | ||
if (is(value).a(Object)) value = Unirest.serializers.form(value); | ||
if (!value.length) return $this; | ||
$this.options.url += (does($this.options.url).contain('?') ? '&' : '?') + value; | ||
@@ -226,10 +255,8 @@ return $this; | ||
send: function (data) { | ||
var type = $this._headers['content-type']; | ||
var type = $this.options.headers[$this.hasHeader('content-type')]; | ||
if (is(data).a(Object)) { | ||
if (is(data).a(Object) && !Buffer.isBuffer(data)) { | ||
if (!type || type != 'application/json') { | ||
$this.type('form'); | ||
type = $this._headers['content-type']; | ||
type = $this.options.headers[$this.hasHeader('content-type')]; | ||
$this.options.body = Unirest.serializers.form(data); | ||
@@ -248,4 +275,3 @@ } else if (type == 'application/json') { | ||
$this.type('form'); | ||
type = $this._headers['content-type']; | ||
type = $this.options.headers[$this.hasHeader('content-type')]; | ||
} | ||
@@ -290,3 +316,3 @@ | ||
part: function (options) { | ||
if (!$this.options.multipart) | ||
if (!$this._multipart) | ||
$this.options.multipart = []; | ||
@@ -321,5 +347,12 @@ | ||
end: function (callback) { | ||
var Request = Unirest.request($this.options, function (error, response, body) { | ||
var data, type, result = {}; | ||
var Request; | ||
var header; | ||
var parts; | ||
var form; | ||
function handleRequestResponse (error, response, body) { | ||
var result = {}; | ||
var data; | ||
var type; | ||
// Handle pure error | ||
@@ -421,2 +454,4 @@ if (error && !response) { | ||
body = body || response.body; | ||
result.raw_body = body; | ||
@@ -436,23 +471,5 @@ result.headers = response.headers; | ||
(callback) && callback(result); | ||
}); | ||
if ($this._multipart.length) { | ||
var form = Request.form(); | ||
for (var i = 0; i < $this._multipart.length; i++) { | ||
var item = $this._multipart[i]; | ||
if (item.attachment && is(item.value).a(String)) { | ||
if (does(item.value).contain('http://') || does(item.value).contain('https://')) { | ||
item.value = Unirest.request(item.value); | ||
} else { | ||
item.value = fs.createReadStream(path.resolve(item.value)); | ||
} | ||
} | ||
form.append(item.name, item.value); | ||
} | ||
} | ||
Request.on('response', function (response) { | ||
function handleGZIPResponse (response) { | ||
if (/^(deflate|gzip)$/.test(response.headers['content-encoding'])) { | ||
@@ -501,4 +518,74 @@ var unzip = zlib.createUnzip(); | ||
} | ||
}); | ||
} | ||
function handleFormData (form) { | ||
for (var i = 0; i < $this._multipart.length; i++) { | ||
var item = $this._multipart[i]; | ||
if (item.attachment && is(item.value).a(String)) { | ||
if (does(item.value).contain('http://') || does(item.value).contain('https://')) { | ||
item.value = Unirest.request(item.value); | ||
} else { | ||
item.value = fs.createReadStream(path.resolve(item.value)); | ||
} | ||
} | ||
form.append(item.name, item.value, item.options); | ||
} | ||
return form; | ||
} | ||
if ($this._multipart.length && !$this._stream) { | ||
parts = URL.parse($this.options.url); | ||
form = new FormData(); | ||
if (header = $this.options.headers[$this.hasHeader('content-type')]) { | ||
$this.options.headers['content-type'] = header.split(';')[0] + '; boundary=' + form.getBoundary(); | ||
} else { | ||
$this.options.headers['content-type'] = 'multipart/mixed; boundary=' + form.getBoundary(); | ||
} | ||
return handleFormData(form).submit({ | ||
host: parts.host, | ||
path: parts.path, | ||
method: $this.options.method, | ||
headers: $this.options.headers, | ||
auth: $this.options.auth | ||
}, function (error, response) { | ||
var decoder = new StringDecoder('utf8'); | ||
if (error) { | ||
return handleRequestResponse(error, response); | ||
} | ||
if (!response.body) { | ||
response.body = ""; | ||
} | ||
// Node 10+ | ||
response.resume(); | ||
// GZIP, Feel me? | ||
handleGZIPResponse(response); | ||
// Fallback | ||
response.on('data', function (chunk) { | ||
if (typeof chunk === 'string') response.body += chunk; | ||
else response.body += decoder.write(chunk); | ||
}); | ||
// After all, we end up here | ||
response.on('end', function () { | ||
return handleRequestResponse(error, response); | ||
}); | ||
}); | ||
} | ||
Request = Unirest.request($this.options, handleRequestResponse); | ||
Request.on('response', handleGZIPResponse); | ||
if ($this._multipart.length && $this._stream) | ||
handleFormData(Request.form()); | ||
return Request; | ||
@@ -528,3 +615,2 @@ } | ||
/** | ||
@@ -651,3 +737,3 @@ * Aliases for _.end_ | ||
form: function (obj) { | ||
return querystring.stringify(obj); | ||
return QueryString.stringify(obj); | ||
}, | ||
@@ -668,3 +754,3 @@ | ||
var serializer = Unirest.enum.serialize[type]; | ||
return seralizer ? serializer(string) : string; | ||
return serializer ? serializer(string) : string; | ||
}, | ||
@@ -671,0 +757,0 @@ |
{ | ||
"name": "unirest", | ||
"version": "0.2.7", | ||
"version": "0.2.8", | ||
"description": "Lightweight HTTP Request library.", | ||
@@ -10,4 +10,5 @@ "main": "index.js", | ||
"dependencies": { | ||
"form-data": "^0.1.2", | ||
"mime": "~1.2.11", | ||
"request": "~2.34.0", | ||
"request": "~2.40.0", | ||
"should": "~2.0.1" | ||
@@ -14,0 +15,0 @@ }, |
@@ -66,3 +66,3 @@ # Unirest for Node.js [![Build Status](https://travis-ci.org/Mashape/unirest-nodejs.png?branch=master)](https://travis-ci.org/Mashape/unirest-nodejs) | ||
- `method` - Request type (GET, PUT, POST, etc...) | ||
- `uri` - _Optional_; When declared the method will return a [Request](#request) object. | ||
- `uri` - _Optional_; When declared the method will return a [Request](#request) object. | ||
Otherwise it will return the method below with `method` set to the method given. | ||
@@ -77,3 +77,3 @@ - `headers` (`Object`) - _Optional_; Will be aliased to unirest\[method] `headers` argument when `uri` is present. | ||
- `url` - Request location. | ||
- `headers` (`Object` | `Function`) - _Optional_; When `Object` headers are passed along to the `Request.set()` method, | ||
- `headers` (`Object` | `Function`) - _Optional_; When `Object` headers are passed along to the `Request.set()` method, | ||
when `Function` this argument is used as the `callback`. | ||
@@ -84,3 +84,3 @@ - `body` (`Mixed` | `Function`) - _Optional_; When `body` is not a `Function` it will be passed along to `Request.send()` method, | ||
All arguments above, with the exclusion of `url`, will accept a `Function` as the `callback`. | ||
All arguments above, with the exclusion of `url`, will accept a `Function` as the `callback`. | ||
When no `callback` is present, the [Request](#request) object will be returned. | ||
@@ -145,4 +145,4 @@ | ||
Provides simple and easy to use methods for manipulating the request prior to being sent. This object is created when a | ||
Unirest Method is invoked. This object contains methods that are chainable like other libraries such as jQuery and popular | ||
Provides simple and easy to use methods for manipulating the request prior to being sent. This object is created when a | ||
Unirest Method is invoked. This object contains methods that are chainable like other libraries such as jQuery and popular | ||
request module Superagent (which this library is modeled after slightly). | ||
@@ -198,3 +198,3 @@ | ||
- `field` (`String`) - Header name, such as `Accepts` | ||
- `value` (`String`) - Header value, such as `application/json` | ||
- `value` (`String`) - Header value, such as `application/json` | ||
@@ -295,3 +295,3 @@ **Object** | ||
Sets the header `Content-Type` through either lookup for extensions (`xml`, `png`, `json`, etc...) using `mime` or using the full value such as `application/json`. | ||
Sets the header `Content-Type` through either lookup for extensions (`xml`, `png`, `json`, etc...) using `mime` or using the full value such as `application/json`. | ||
@@ -356,5 +356,11 @@ Uses `Request.header()` to set header value. | ||
#### Request.stream() | ||
Sets `_stream` flag to use `request` streaming instead of direct `form-data` usage. | ||
This seemingly appears to only work for node servers, use streaming only if you are a hundred percent sure it will work. | ||
Tread carefully. | ||
## Request.options | ||
The _options_ `object` is where almost all of the request settings live. Each option method sugars to a field on this object to allow for chaining and ease of use. If | ||
The _options_ `object` is where almost all of the request settings live. Each option method sugars to a field on this object to allow for chaining and ease of use. If | ||
you have trouble with an option method and wish to directly access the _options_ object | ||
@@ -477,7 +483,7 @@ you are free to do so. | ||
Request.strictSSL(true); | ||
``` | ||
``` | ||
#### Request.httpSignature(Object) | ||
Sets `httpSignature` | ||
Sets `httpSignature` | ||
@@ -498,3 +504,3 @@ #### Request.proxy(String) | ||
Request.secureProtocol('SSLv2_method'); | ||
// or | ||
// or | ||
Request.secureProtocol('SSLv3_client_method'); | ||
@@ -510,3 +516,3 @@ ``` | ||
```js | ||
Request.aws({ | ||
Request.aws({ | ||
key: 'AWS_S3_KEY', | ||
@@ -531,3 +537,3 @@ secret: 'AWS_S3_SECRET', | ||
var access_token = response.body; | ||
Request = unirest.post('https://api.twitter.com/oauth/access_token'); | ||
@@ -541,3 +547,3 @@ Request.oauth({ | ||
var token = response.body; | ||
Request = unirest.get('https://api.twitter.com/1/users/show.json'); | ||
@@ -544,0 +550,0 @@ Request.oauth({ |
@@ -72,2 +72,22 @@ var should = require("should"); | ||
it('should correctly post MULTIFORM data.', function (done) { | ||
var request = unirest.post('http://httpbin.org/post'); | ||
var file = __dirname + '/../README.md'; | ||
var data = { | ||
a: 'foo', | ||
b: 'bar' | ||
}; | ||
request.attach('u', file); | ||
for (var key in data) { | ||
request.field(key, data[key]); | ||
} | ||
request.end(function (response) { | ||
should(response.status).equal(200); | ||
done(); | ||
}); | ||
}); | ||
it('should correctly post JSON data.', function (done) { | ||
@@ -97,3 +117,13 @@ var data = { | ||
}); | ||
it('should correctly post a buffer with mime-type', function (done) { | ||
unirest.post('http://httpbin.org/post') | ||
.headers({ 'Content-Type': 'img/svg+xml' }) | ||
.send(new Buffer("<svg></svg>")) | ||
.end(function (response) { | ||
should(response.body.headers['Content-Type']).equal('img/svg+xml'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50809
889
686
4
+ Addedform-data@^0.1.2
+ Addedhawk@1.1.1(transitive)
+ Addedmime-types@1.0.2(transitive)
+ Addedqs@1.0.2(transitive)
+ Addedrequest@2.40.0(transitive)
+ Addedstringstream@0.0.6(transitive)
+ Addedtunnel-agent@0.4.3(transitive)
- Removedhawk@1.0.0(transitive)
- Removedqs@0.6.6(transitive)
- Removedrequest@2.34.0(transitive)
- Removedtunnel-agent@0.3.0(transitive)
Updatedrequest@~2.40.0