planet-client
Advanced tools
Comparing version 1.2.0 to 2.0.0-beta.1
@@ -7,9 +7,3 @@ /** | ||
var http = require('http'); | ||
var https = require('https'); | ||
var path = require('path'); | ||
var url = require('url'); | ||
var bole = require('bole'); | ||
var assign = require('./util').assign; | ||
@@ -20,4 +14,2 @@ var util = require('./util'); | ||
var log = bole(path.basename(__filename, '.js')); | ||
var defaultHeaders = { | ||
@@ -27,9 +19,7 @@ 'accept': 'application/json' | ||
var boundary = generateBoundary(); | ||
/** | ||
* Generate request options provided a config object. | ||
* @param {Object} config A request config. | ||
* @return {Promise<IncomingMessage>} A promise that resolves to a successful | ||
* response. Any non 200 status will result in a rejection. | ||
* @return {Object} An object with method, headers, url, and withCredentials | ||
* properties. | ||
* @private | ||
@@ -67,8 +57,3 @@ */ | ||
headers['content-type'] = 'application/json'; | ||
headers['content-length'] = JSON.stringify(config.body).length; | ||
} | ||
if (config.file) { | ||
headers['content-type'] = 'multipart/form-data; boundary=' + boundary; | ||
headers['content-length'] = byteCount(toMultipartUpload(config.file)); | ||
} | ||
@@ -86,13 +71,7 @@ if (config.withCredentials !== false) { | ||
var options = { | ||
protocol: config.protocol, | ||
hostname: config.hostname, | ||
method: config.method || 'GET', | ||
path: config.path, | ||
headers: headers | ||
headers: headers, | ||
url: config.protocol + '//' + config.hostname + (config.port ? ':' + config.port : '') + config.path | ||
}; | ||
if (config.port) { | ||
options.port = config.port; | ||
} | ||
if ('withCredentials' in config) { | ||
@@ -134,3 +113,3 @@ options.withCredentials = config.withCredentials; | ||
* response stream. | ||
* @return {function(IncomingMessage)} A function that handles an http(s) | ||
* @return {function(XMLHttpRequest)} A function that handles an http(s) | ||
* incoming message. | ||
@@ -140,60 +119,44 @@ * @private | ||
function createResponseHandler(resolve, reject, info) { | ||
return function(response) { | ||
var status = response.statusCode; | ||
if (status === 302) { | ||
log.debug('Following redirect: ', response.headers.location); | ||
https.get(response.headers.location, | ||
createResponseHandler(resolve, reject, info)); | ||
return function(event) { | ||
var client = event.target; | ||
if (client.status === 302) { | ||
client = new XMLHttpRequest(); | ||
client.addEventListener('load', createResponseHandler(resolve, reject, info)); | ||
client.addEventListener('error', function(event) { | ||
reject(new errors.ClientError('Request failed')); | ||
}); | ||
client.open('GET', client.getResponseHeader('Location')); | ||
return; | ||
} | ||
if (info.stream) { | ||
var streamErr = errorCheck(response, null); | ||
if (streamErr) { | ||
reject(streamErr); | ||
} else { | ||
resolve({response: response, body: null}); | ||
} | ||
client.statusCode = client.status; // backwards compatibility with http response | ||
info.completed = true; | ||
if (info.aborted) { | ||
return; | ||
} | ||
var data = ''; | ||
response.on('data', function(chunk) { | ||
data += String(chunk); | ||
}); | ||
response.on('error', function(err) { | ||
if (!info.aborted) { | ||
reject(err); | ||
var body = null; | ||
var err = null; | ||
var data = client.responseText; | ||
if (data) { | ||
try { | ||
body = JSON.parse(data); | ||
} catch (parseErr) { | ||
err = new errors.UnexpectedResponse( | ||
'Trouble parsing response body as JSON: ' + data + '\n' + | ||
parseErr.stack + '\n', client, data); | ||
} | ||
}); | ||
} | ||
response.on('end', function() { | ||
info.completed = true; | ||
if (info.aborted) { | ||
return; | ||
} | ||
var body = null; | ||
var err = null; | ||
if (data) { | ||
try { | ||
body = JSON.parse(data); | ||
} catch (parseErr) { | ||
err = new errors.UnexpectedResponse( | ||
'Trouble parsing response body as JSON: ' + data + '\n' + | ||
parseErr.stack + '\n', response, data); | ||
} | ||
} | ||
err = errorCheck(client, body) || err; | ||
err = errorCheck(response, body) || err; | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve({ | ||
response: response, | ||
body: body | ||
}); | ||
} | ||
}); | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve({ | ||
response: client, | ||
body: body | ||
}); | ||
} | ||
}; | ||
@@ -230,34 +193,39 @@ } | ||
var protocol; | ||
if (options.protocol && options.protocol.indexOf('https') === 0) { | ||
protocol = https; | ||
} else { | ||
protocol = http; | ||
} | ||
log.debug('request options: %j', options); | ||
var info = { | ||
aborted: false, | ||
completed: false, | ||
stream: config.stream | ||
completed: false | ||
}; | ||
return new Promise(function(resolve, reject) { | ||
var client = new XMLHttpRequest(); | ||
var handler = createResponseHandler(resolve, reject, info); | ||
var client = protocol.request(options, handler); | ||
client.on('error', function(err) { | ||
reject(new errors.ClientError(err.message)); | ||
client.addEventListener('load', handler); | ||
client.addEventListener('error', function(event) { | ||
reject(new errors.ClientError('Request failed')); | ||
}); | ||
var body = null; | ||
if (config.body) { | ||
client.write(JSON.stringify(config.body)); | ||
body = JSON.stringify(config.body); | ||
} | ||
if (config.file) { | ||
client.write(toMultipartUpload(config.file)); | ||
client.open(options.method, options.url, true); | ||
for (var header in options.headers) { | ||
client.setRequestHeader(header, options.headers[header]); | ||
} | ||
client.end(); | ||
if ('withCredentials' in options) { | ||
client.withCredentials = options.withCredentials; | ||
} | ||
client.send(body); | ||
if (config.terminator) { | ||
config.terminator(function() { | ||
if (!info.aborted && !info.completed) { | ||
if (!info.completed && !info.aborted) { | ||
info.aborted = true; | ||
client.abort(); | ||
reject(new errors.AbortedRequest('Request aborted')); | ||
@@ -325,49 +293,2 @@ } | ||
/** | ||
* Converts a file object to a multipart payload. The file is assumed to have | ||
* textual content and to conform to the | ||
* [File](https://developer.mozilla.org/en-US/docs/Web/API/File) interface. | ||
* | ||
* Note: this isn't binary-safe. | ||
* | ||
* @param {File} file A File-like object conforming to the HTML File api. | ||
* @return {String} A multipart request body for a file upload. | ||
*/ | ||
function toMultipartUpload(file) { | ||
return [ | ||
'--' + boundary, | ||
'\r\n', | ||
'Content-Type: application/json; charset=utf-8', | ||
'\r\n', | ||
'Content-Disposition: form-data; name="file"; filename="' + file.name + '"', | ||
'\r\n\r\n', | ||
file.contents, | ||
'\r\n', | ||
'--' + boundary + '--' | ||
].join(''); | ||
} | ||
/** | ||
* Returns the length in bytes of a string. | ||
* @param {String} source A string whose length we wish to count. | ||
* @return {Number} The byte-length of a string | ||
*/ | ||
function byteCount(source) { | ||
return encodeURI(source).split(/%..|./).length - 1; | ||
} | ||
/** | ||
* Returns a boundary, generating a new one and memoizing it if necessary. | ||
* | ||
* @return {String} A 24 character hex string string to use as a multipart | ||
* boundary. | ||
*/ | ||
function generateBoundary() { | ||
var newBoundary = []; | ||
for (var i = 0; i < 24; i++) { | ||
newBoundary.push(Math.floor(Math.random() * 16).toString(16)); | ||
} | ||
return newBoundary.join(''); | ||
} | ||
exports.get = get; | ||
@@ -374,0 +295,0 @@ exports.post = post; |
{ | ||
"name": "planet-client", | ||
"version": "1.2.0", | ||
"version": "2.0.0-beta.1", | ||
"description": "A client for Planet's imagery API", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -17,2 +17,8 @@ ## planet-client | ||
It is also possible to load a standalone bundle of the library in a script tag. Without a module loader, this will create a global `planet` object: | ||
<script src="https://npmcdn.com/planet-client/dist/planet.js"></script> | ||
This will redirect to the most recent release. To avoid the redirect, you can include a specific version number (e.g. https://npmcdn.com/planet-client@1.2.0/dist/planet.js). | ||
The library requires a global [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) implementation. This comes with Node >= 0.12 and [modern browsers](http://caniuse.com/#search=promise). To use `planet-client` in an environment without `Promise`, you can [use a polyfill](https://www.google.com/search?q=promise+polyfill). | ||
@@ -19,0 +25,0 @@ |
Sorry, the diff of this file is too big to display
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
106
9
4
100464
1896
3