diff --git a/.gitignore b/.gitignore index e019dac..8598150 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ test/config.json # ignore built releases *.tgz +node_modules diff --git a/lib/panda/api_authentication.js b/lib/panda/api_authentication.js index 01d411f..01c273c 100644 --- a/lib/panda/api_authentication.js +++ b/lib/panda/api_authentication.js @@ -5,11 +5,10 @@ function canonicalString(params){ var index2 = []; Object.keys(params).forEach(function(key) { - index.push(key); + if (key !== 'file') + index.push(key); }); - delete index['file']; - index.sort(); index.forEach(function(key) { @@ -42,4 +41,4 @@ function hashToQuery(params){ module.exports = { generateSignature: generateSignature, hashToQuery: hashToQuery -}; \ No newline at end of file +}; diff --git a/lib/panda/panda.js b/lib/panda/panda.js index 81cef05..39304ea 100644 --- a/lib/panda/panda.js +++ b/lib/panda/panda.js @@ -4,6 +4,10 @@ var auth = require('./api_authentication'); var sys = require('sys'); var http = require('http'); var https = require('https'); +var fs = require('fs'); +var FormData = require('form-data'); + +var form = new FormData(); function merge(dest, src) { for (var k in src) { @@ -101,6 +105,38 @@ merge(Panda.prototype, { }, makeRequest: function (options,cb) { + // File upload + if (form._streams.length > 0) { + options['protocol'] = options.port === 80 ? 'http:' : 'https:'; // it's necessary for form-data + + form.submit(options, function(err, res) { + if (err) + throw err; + res.setEncoding('utf8'); + var body = ''; + res.addListener("data", function (data) { + body += data; + }); + res.addListener('end', function (chunk) { + if(cb) { + if (body) { + cb(JSON.parse(body)); + } else { + cb({error: 'requestError', message: 'Empty response body'}); + } + } + }); + res.addListener('error', function(err) { + if (cb) { + cb({error: 'requestError', message: err.message}); + } + }); + }); + + return; + } + + // Everything else var request = this.httpClient().request(options, function(res) { res.setEncoding('utf8'); var body = ''; @@ -110,7 +146,7 @@ merge(Panda.prototype, { res.addListener('end', function (chunk) { if(cb) { if (body) { - cb(JSON.parse(body)) + cb(JSON.parse(body)); } else { cb({error: 'requestError', message: 'Empty response body'}); } @@ -122,21 +158,38 @@ merge(Panda.prototype, { } }); }); - request.end(); + + request.end(); }, queryOptions: function(verb, uri, params) { - var query = auth.hashToQuery(this.signedParams(verb, uri, params)); var request_uri = '/v2' + uri; + var path = ''; + var headers = {}; + var signedParams = this.signedParams(verb, uri, params); + + if (verb === 'POST' && params['file'] !== undefined) { // File upload + var paramsKeys = Object.keys(signedParams); + + paramsKeys.forEach(function (key) { + form.append(key, signedParams[key]); + }); + form.append('file', fs.createReadStream(signedParams['file'])); + + path = request_uri; + } + else { + var query = auth.hashToQuery(signedParams); + path = request_uri + '?' + query; + headers['Content-Length'] = 0; + } return { host: this.apiHost, port: this.apiPort, - path: request_uri + '?' + query, + path: path, method: verb, - headers: { - 'Content-Length': 0 - } + headers: headers }; }, diff --git a/package.json b/package.json index 8896a6d..a205733 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,19 @@ "lib": "./lib/panda" }, "main": "./lib/panda/index", - "dependencies": {}, + "dependencies": { + "form-data": "^0.1.4" + }, "devDependencies": { - "gently": ">= 0.9.0", - "jasmine-node": ">= 1.0.10" + "gently": ">= 0.9.0", + "jasmine-node": ">= 1.0.10" }, "engines": { "node": "*" }, - "licenses" : [ { "type" : "MIT" } ] + "licenses": [ + { + "type": "MIT" + } + ] }