diff --git a/.gitignore b/.gitignore index ba2a97b57..98f9955c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules coverage +.idea diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a0a2cc25..e163ee24f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## Change Log +### v2.49.0 (2014/11/28) +- [#1295](https://github.com/request/request/pull/1295) fix(proxy): no-proxy false positive (@oliamb) +- [#1292](https://github.com/request/request/pull/1292) Upgrade `caseless` to 0.8.1 (@mmalecki) +- [#1276](https://github.com/request/request/pull/1276) Set transfer encoding for multipart/related to chunked by default (@simov) +- [#1275](https://github.com/request/request/pull/1275) Fix multipart content-type headers detection (@simov) +- [#1269](https://github.com/request/request/pull/1269) adds streams example for review (@tbuchok) +- [#1238](https://github.com/request/request/pull/1238) Add examples README.md (@simov) + ### v2.48.0 (2014/11/12) - [#1263](https://github.com/request/request/pull/1263) Fixed a syntax error / typo in README.md (@xna2) - [#1253](https://github.com/request/request/pull/1253) Add multipart chunked flag (@simov, @nylen) diff --git a/README.md b/README.md index c2c1c860e..1a5481ac5 100644 --- a/README.md +++ b/README.md @@ -256,10 +256,11 @@ var formData = { my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), // Pass multiple values /w an Array attachments: [ - fs.createReadStream(__dirname + '/attacment1.jpg'), + fs.createReadStream(__dirname + '/attachment1.jpg'), fs.createReadStream(__dirname + '/attachment2.jpg') ], // Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS} + // Use case: for some types of streams, you'll need to provide "file"-related information manually. // See the `form-data` README for more information about options: https://github.com/felixge/node-form-data custom_file: { value: fs.createReadStream('/dev/urandom'), @@ -277,7 +278,7 @@ request.post({url:'http://service.com/upload', formData: formData}, function opt }); ``` -For advanced cases, you can the form-data object itself via `r.form()`. This can be modified until the request is fired on the next cycle of the event-loop. (Note that this calling `form()` will clear the currently set form data for that request.) +For advanced cases, you can access the form-data object itself via `r.form()`. This can be modified until the request is fired on the next cycle of the event-loop. (Note that this calling `form()` will clear the currently set form data for that request.) ```javascript // NOTE: Advanced use-case, for normal use see 'formData' usage above @@ -313,7 +314,7 @@ Some variations in different HTTP implementations require a newline/CRLF before, chunked: false, data: [ { - 'content-type': 'application/json', + 'content-type': 'application/json', body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) }, { body: 'I am an attachment' } diff --git a/package.json b/package.json index c85d3ac6c..3517704de 100755 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "util", "utility" ], - "version": "2.48.1", + "version": "2.49.1", "author": "Mikeal Rogers ", "repository": { "type": "git", @@ -23,9 +23,9 @@ "main": "index.js", "dependencies": { "bl": "~0.9.0", - "caseless": "~0.7.0", + "caseless": "~0.8.0", "forever-agent": "~0.5.0", - "form-data": "~0.1.0", + "form-data": "~0.2.0", "json-stringify-safe": "~5.0.0", "mime-types": "~1.0.1", "node-uuid": "~1.4.0", diff --git a/request.js b/request.js index 826ed7f1b..93239feb7 100644 --- a/request.js +++ b/request.js @@ -199,7 +199,8 @@ function getProxyFromURI(uri) { } } else { noProxyItem = noProxyItem.replace(/^\.*/, '.') - if (hostname.indexOf(noProxyItem) === hostname.length - noProxyItem.length) { + var isMatchedAt = hostname.indexOf(noProxyItem) + if (isMatchedAt > -1 && isMatchedAt === hostname.length - noProxyItem.length) { return null } } @@ -1429,6 +1430,10 @@ Request.prototype.multipart = function (multipart) { return chunked ? items.append(part) : items.push(new Buffer(part)) } + if (chunked) { + self.setHeader('transfer-encoding', 'chunked') + } + var headerName = self.hasHeader('content-type') if (!headerName || self.headers[headerName].indexOf('multipart') === -1) { self.setHeader('content-type', 'multipart/related; boundary=' + self.boundary) @@ -1477,7 +1482,7 @@ Request.prototype.json = function (val) { self._json = true if (typeof val === 'boolean') { - if (typeof self.body === 'object') { + if (self.body !== undefined) { self.body = safeStringify(self.body) if (!self.hasHeader('content-type')) { self.setHeader('content-type', 'application/json') diff --git a/tests/server.js b/tests/server.js index f18c01d1e..7e64a165a 100644 --- a/tests/server.js +++ b/tests/server.js @@ -77,6 +77,24 @@ exports.createPostValidator = function (text, reqContentType) { } return l } +exports.createPostJSONValidator = function (value, reqContentType) { + var l = function (req, resp) { + var r = '' + req.on('data', function (chunk) {r += chunk}) + req.on('end', function () { + var parsedValue = JSON.parse(r) + assert.deepEqual(parsedValue, value) + if (reqContentType) { + assert.ok(req.headers['content-type']) + assert.ok(~req.headers['content-type'].indexOf(reqContentType)) + } + resp.writeHead(200, {'content-type':'application/json'}) + resp.write(r) + resp.end() + }) + } + return l +} exports.createGetResponse = function (text, contentType) { var l = function (req, resp) { contentType = contentType || 'text/plain' diff --git a/tests/test-json-request.js b/tests/test-json-request.js new file mode 100644 index 000000000..af41964bd --- /dev/null +++ b/tests/test-json-request.js @@ -0,0 +1,54 @@ +'use strict' + +var server = require('./server') + , stream = require('stream') + , request = require('../index') + , tape = require('tape') + +var s = server.createServer() + +tape('setup', function(t) { + s.listen(s.port, function() { + t.end() + }) +}) + +function testJSONValue(testId, value) { + tape('test ' + testId, function(t) { + var testUrl = '/' + testId + s.on(testUrl, server.createPostJSONValidator(value, 'application/json')) + var opts = { + method: 'PUT', + uri: s.url + testUrl, + json: true, + body: value + } + request(opts, function (err, resp, body) { + t.equal(err, null) + t.equal(resp.statusCode, 200) + t.deepEqual(body, value) + t.end() + }) + }) +} + +testJSONValue('jsonNull', null) +testJSONValue('jsonTrue', true) +testJSONValue('jsonFalse', false) +testJSONValue('jsonNumber', -289365.2938) +testJSONValue('jsonString', 'some string') +testJSONValue('jsonArray', ['value1', 2, null, 8925.53289, true, false, ['array'], { object: 'property' }]) +testJSONValue('jsonObject', { + trueProperty: true, + falseProperty: false, + numberProperty: -98346.34698, + stringProperty: 'string', + nullProperty: null, + arrayProperty: ['array'], + objectProperty: { object: 'property' } +}) + +tape('cleanup', function(t) { + s.close() + t.end() +}) diff --git a/tests/test-multipart.js b/tests/test-multipart.js index bc1ab1438..ec18ef8ea 100644 --- a/tests/test-multipart.js +++ b/tests/test-multipart.js @@ -94,7 +94,7 @@ function runTest(t, a) { if (a.json) { reqOptions.json = true } - request.post(reqOptions, function (err, res, body) { + request[a.method](reqOptions, function (err, res, body) { t.equal(err, null) t.equal(res.statusCode, 200) t.deepEqual(body, a.json ? {status: 'done'} : 'done') @@ -105,6 +105,7 @@ function runTest(t, a) { }) } +var methods = ['post', 'get'] var cases = [ {name: '-json +array', args: {json: false, array: true}}, {name: '-json -array', args: {json: false, array: false}}, @@ -127,8 +128,11 @@ var cases = [ {name: '+json +headers -chunked', args: {json: true, headers: true, array: false, chunked: false}} ] -cases.forEach(function (test) { - tape('multipart related ' + test.name, function(t) { - runTest(t, test.args) +methods.forEach(function(method) { + cases.forEach(function (test) { + tape('multipart related ' + method + ' ' + test.name, function(t) { + test.args.method = method + runTest(t, test.args) + }) }) }) diff --git a/tests/test-proxy.js b/tests/test-proxy.js index fd329fbfc..12c5f9666 100644 --- a/tests/test-proxy.js +++ b/tests/test-proxy.js @@ -131,6 +131,13 @@ if (process.env.TEST_PROXY_HARNESS) { env : { http_proxy : s.url } }, true) + runTest('http_proxy with length of one more than the URL', { + env: { + HTTP_PROXY : s.url, + NO_PROXY: 'elgoog1.com' // one more char than google.com + } + }, true) + runTest('NO_PROXY hostnames are case insensitive', { env : { HTTP_PROXY : s.url,