Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fast-azure-storage

Package Overview
Dependencies
Maintainers
10
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fast-azure-storage - npm Package Compare versions

Comparing version 0.3.7 to 1.0.0

lib/authorization.js

1

lib/index.js

@@ -26,3 +26,4 @@ 'use strict';

lazyExportModule('Queue', './queue');
lazyExportModule('Blob', './blob');
lazyExportModule('Table', './table');
lazyExportModule('Agent', './agent');

202

lib/queue.js

@@ -13,2 +13,3 @@ 'use strict';

var xml = require('./xml-parser');
var auth = require('./authorization');

@@ -34,12 +35,2 @@ /*

/*
* List of x-ms-* headers supported in lexicographical order, used for
* construction of the canonicalized headers.
*/
var X_MS_HEADERS_SUPPORTED = [
'x-ms-client-request-id',
'x-ms-date',
'x-ms-version'
].sort();
/*
* List of query-string parameter supported in lexicographical order, used for

@@ -62,170 +53,2 @@ * construction of the canonicalized resource.

/*
* Authorize the request with shared key
* Intended to define `Queue.prototype.authorize`.
*/
var authorizeWithSharedKey = function (method, path, query, headers) {
// Find account id
var accountId = this.options.accountId;
// Build string to sign
var stringToSign = (
method + '\n' +
(headers['content-encoding'] || '') + '\n' +
(headers['content-language'] || '') + '\n' +
(headers['content-length'] || '') + '\n' +
(headers['content-md5'] || '') + '\n' +
(headers['content-type'] || '') + '\n' +
'\n' + // we always include x-ms-date, so we never specify date header
(headers['if-modified-since'] || '') + '\n' +
(headers['if-match'] || '') + '\n' +
(headers['if-none-match'] || '') + '\n' +
(headers['if-unmodified-since'] || '') + '\n' +
(headers['range'] || '')
);
// Check if we have meta-data header fields, if we don't we can use a
// presorted list of headers which doesn't involve any allocations.
// Otherwise, we callback to building a list of 'x-ms-' prefixed headers and
// sorting it.
var hasMetadata = false;
for (var field in headers) {
hasMetadata = hasMetadata || /^x-ms-meta/.test(field);
}
var fields;
if (hasMetadata) {
// Construct fields as a sorted list of 'x-ms-' prefixed headers
fields = [];
for (var field in headers) {
if (/^x-ms-/.test(field)) {
fields.push(field);
}
}
fields.sort();
} else {
// Fields used in most API methods presorted in lexicographical order.
fields = X_MS_HEADERS_SUPPORTED;
}
// Add lines for canonicalized headers using presorted list of fields
var N = fields.length;
for(var i = 0; i < N; i++) {
var field = fields[i];
var value = headers[field];
if (value) {
stringToSign += '\n' + field + ':' + value;
}
}
// Added lines from canonicalized resource and query-string parameters
// supported by this library in lexicographical order as presorted in
// QUERY_PARAMS_SUPPORTED
stringToSign += '\n/' + accountId + path;
var M = QUERY_PARAMS_SUPPORTED.length;
for(var j = 0; j < M; j++) {
var param = QUERY_PARAMS_SUPPORTED[j];
var value = query[param];
if (value) {
stringToSign += '\n' + param + ':' + value;
}
}
// Compute signature
var signature = crypto
.createHmac('sha256', this._accessKey)
.update(stringToSign)
.digest('base64');
// Set authorization header
headers.authorization = 'SharedKey ' + accountId + ':' + signature;
// Encode query string
var qs = querystring.stringify(query);
// Construct request options
return Promise.resolve({
host: this.hostname,
method: method,
path: (qs.length > 0 ? path + '?' + qs : path),
headers: headers,
agent: this.options.agent,
});
}
/*
* Authorize the request with a shared-access-signature that is refreshed with
* the a function given as `options.sas`.
* Intended to define `Queue.prototype.authorize`.
*/
function authorizeWithRefreshSAS(method, path, query, headers) {
var self = this;
// Check if we should refresh SAS
if (Date.now() > this._nextSASRefresh && this._nextSASRefresh !== 0) {
debug("Refreshing shared-access-signature");
// Avoid refreshing more than once
this._nextSASRefresh = 0;
// Refresh SAS
this._sas = Promise.resolve(this.options.sas());
// Update _nextSASRefresh when the SAS has been refreshed
this._sas.then(function(sas) {
sas = querystring.parse(sas);
// Find next sas refresh time
self._nextSASRefresh = (
new Date(sas.se).getTime() - self.options.minSASAuthExpiry
);
debug("Refreshed shared-access-signature, will refresh in %s ms",
self._nextSASRefresh);
// Throw an error if the signature expiration comes too soon
if (Date.now() > self._nextSASRefresh) {
throw new Error("Refreshed SAS, but got a Shared-Access-Signature " +
"that expires less than options.minSASAuthExpiry " +
"from now, signature expiry: " + sas.se);
}
}).catch(function(err) {
// If we have an error freshing SAS that's bad and we'll emit it; for most
// apps it's probably best to ignore this error and just crash.
self.emit('error', err);
});
}
// Construct request options, whenever the `_sas` promise is resolved.
return this._sas.then(function(sas) {
// Serialize query-string
var qs = querystring.stringify(query);
if (qs.length > 0) {
qs += '&';
}
qs += sas
return {
host: self.hostname,
method: method,
path: path + '?' + qs,
headers: headers,
agent: self.options.agent,
};
});
}
/*
* Authorize the request with a shared-access-signature that is given with
* `options.sas` as string.
* Intended to define `Queue.prototype.authorize`.
*/
function authorizeWithSAS(method, path, query, headers) {
// Serialize query-string
var qs = querystring.stringify(query);
if (qs.length > 0) {
qs += '&';
}
qs += this.options.sas;
// Construct request options
return Promise.resolve({
host: this.hostname,
method: method,
path: path + '?' + qs,
headers: headers,
agent: this.options.agent,
});
}
/**

@@ -330,3 +153,3 @@ * Queue client class for interacting with Azure Queue Storage.

// If set authorize to use shared key signatures
this.authorize = authorizeWithSharedKey;
this.authorize = auth.authorizeWithSharedKey.call(this, 'queue', QUERY_PARAMS_SUPPORTED);
// Decode accessKey

@@ -336,3 +159,3 @@ this._accessKey = new Buffer(this.options.accessKey, 'base64');

// Set authorize to use shared-access-signatures with refresh function
this.authorize = authorizeWithRefreshSAS;
this.authorize = auth.authorizeWithRefreshSAS;
// Set state with _nextSASRefresh = -1, we'll refresh on the first request

@@ -343,3 +166,3 @@ this._nextSASRefresh = -1;

// Set authorize to use shared-access-signature as hardcoded
this.authorize = authorizeWithSAS;
this.authorize = auth.authorizeWithSAS;
} else {

@@ -429,6 +252,3 @@ throw new Error("Either options.accessKey, options.sas as function or " +

// Compute signature
query.sig = crypto
.createHmac('sha256', this._accessKey)
.update(stringToSign)
.digest('base64');
query.sig = utils.hmacSha256(this._accessKey, stringToSign);;

@@ -505,3 +325,3 @@ // Return Shared-Access-Signature as query-string

// Parse error message
var data = xml.queueParseError(res);
var data = xml.parseError(res);

@@ -663,12 +483,6 @@ // Construct error object

}
// Extract meta-data
var metadata = {};
for(var field in res.headers) {
if (/x-ms-meta-/.test(field)) {
metadata[field.substr(10)] = res.headers[field];
}
}
return {
messageCount: parseInt(res.headers['x-ms-approximate-messages-count']),
metadata: metadata
metadata: utils.extractMetadataFromHeaders(res)
};

@@ -675,0 +489,0 @@ });

@@ -12,2 +12,3 @@ 'use strict';

var utils = require('./utils');
var auth = require('./authorization');

@@ -52,6 +53,3 @@ /* Transient error codes (we'll retry request when encountering these codes */

// Compute signature
var signature = crypto
.createHmac('sha256', this._accessKey)
.update(stringToSign)
.digest('base64');
var signature = utils.hmacSha256(this._accessKey, stringToSign);

@@ -74,82 +72,2 @@ // Set authorization header

/*
* Authorize the request with a shared-access-signature that is refreshed with
* the a function given as `options.sas`.
* Intended to define `Table.prototype.authorize`.
*/
function authorizeWithRefreshSAS(method, path, query, headers) {
var self = this;
// Check if we should refresh SAS
if (Date.now() > this._nextSASRefresh && this._nextSASRefresh !== 0) {
debug("Refreshing shared-access-signature");
// Avoid refreshing more than once
this._nextSASRefresh = 0;
// Refresh SAS
this._sas = Promise.resolve(this.options.sas());
// Update _nextSASRefresh when the SAS has been refreshed
this._sas.then(function(sas) {
sas = querystring.parse(sas);
// Find next sas refresh time
self._nextSASRefresh = (
new Date(sas.se).getTime() - self.options.minSASAuthExpiry
);
debug("Refreshed shared-access-signature, will refresh in %s ms",
self._nextSASRefresh);
// Throw an error if the signature expiration comes too soon
if (Date.now() > self._nextSASRefresh) {
throw new Error("Refreshed SAS, but got a Shared-Access-Signature " +
"that expires less than options.minSASAuthExpiry " +
"from now, signature expiry: " + sas.se);
}
}).catch(function(err) {
// If we have an error freshing SAS that's bad and we'll emit it; for most
// apps it's probably best to ignore this error and just crash.
self.emit('error', err);
});
}
// Construct request options, whenever the `_sas` promise is resolved.
return this._sas.then(function(sas) {
// Serialize query-string
var qs = querystring.stringify(query);
if (qs.length > 0) {
qs += '&';
}
qs += sas
return {
host: self.hostname,
method: method,
path: path + '?' + qs,
headers: headers,
agent: self.options.agent,
};
});
}
/*
* Authorize the request with a shared-access-signature that is given with
* `options.sas` as string.
* Intended to define `Table.prototype.authorize`.
*/
function authorizeWithSAS(method, path, query, headers) {
// Serialize query-string
var qs = querystring.stringify(query);
if (qs.length > 0) {
qs += '&';
}
qs += this.options.sas;
// Construct request options
return Promise.resolve({
host: this.hostname,
method: method,
path: path + '?' + qs,
headers: headers,
agent: this.options.agent,
});
}
/**

@@ -272,3 +190,3 @@ * Table client class for interacting with Azure Table Storage.

// If set authorize to use shared key signatures
this.authorize = authorizeWithSharedKey;
this.authorize = auth.authorizeWithSharedKey.call(this, 'table');
// Decode accessKey

@@ -278,3 +196,3 @@ this._accessKey = new Buffer(this.options.accessKey, 'base64');

// Set authorize to use shared-access-signatures with refresh function
this.authorize = authorizeWithRefreshSAS;
this.authorize = auth.authorizeWithRefreshSAS;
// Set state with _nextSASRefresh = -1, we'll refresh on the first request

@@ -285,3 +203,3 @@ this._nextSASRefresh = -1;

// Set authorize to use shared-access-signature as hardcoded
this.authorize = authorizeWithSAS;
this.authorize = auth.authorizeWithSAS;
} else {

@@ -394,6 +312,3 @@ throw new Error("Either options.accessKey, options.sas as function or " +

// Compute signature
query.sig = crypto
.createHmac('sha256', this._accessKey)
.update(stringToSign)
.digest('base64');
query.sig = utils.hmacSha256(this._accessKey, stringToSign);

@@ -400,0 +315,0 @@ // Return Shared-Access-Signature as query-string

@@ -5,2 +5,6 @@ 'use strict';

var https = require('https');
var crypto = require('crypto');
var querystring = require('querystring');
var debug = require('debug')('azure:utils');
var assert = require('assert');

@@ -11,3 +15,3 @@ /*

* @param {Number} delay - Number of ms to sleep.
* @returns {Promise} A romise that will be resolved after `delay` ms
* @returns {Promise} A promise that will be resolved after `delay` ms
*/

@@ -178,3 +182,3 @@ var sleep = function sleep(delay) {

var contentLength = res.headers['content-length'];
if (contentLength) {
if (contentLength && options.method !== 'HEAD') {
var length = Buffer.byteLength(res.payload, 'utf8');

@@ -232,1 +236,134 @@ if (length !== parseInt(contentLength)) {

exports.parseJSON = parseJSON;
/*
* Extracts the metadata from HTTP response header
*
* @param {object} response - HTTP response
* @returns {object} Mapping from meta-data keys to values
*/
var extractMetadataFromHeaders = function extractMetadataFromHeaders(response) {
var metadata = {};
/*
* Metadata names must be valid C# identifiers and are case-insensitive, but case preserving,
* meaning that you can set,for example, a metadata with the following form:
* {
* applicationName: 'fast-azure-blob-storage'
* }
* In order to return the original metadata name, the header names should be read from response.rawHeaders.
* That is because 'https' library returns the response headers with lowercase.
* The response.rawHeaders is a list that contains the raw header names and values. It is NOT a list of tuples.
* So, the even-numbered offsets are key values, and the odd-numbered offsets are the associated values.
*/
for(var i = 0; i < response.rawHeaders.length; i += 2) {
var key = response.rawHeaders[i];
if (/x-ms-meta-/.test(key)) {
metadata[key.substr(10)] = response.headers[key.toLowerCase()];
}
}
return metadata;
}
exports.extractMetadataFromHeaders = extractMetadataFromHeaders;
/*
* Checks if the given value is a valid GUID
*
* A string that contains a GUID in one of the following formats (`d` represents a hexadecimal digit whose case is ignored):
*
* - 32 contiguous digits: dddddddddddddddddddddddddddddddd
* - Groups of 8, 4, 4, 4, and 12 digits with hyphens between the groups
* dddddddd-dddd-dddd-dddd-dddddddddddd
* -or-
* {dddddddd-dddd-dddd-dddd-dddddddddddd}
* -or-
* (dddddddd-dddd-dddd-dddd-dddddddddddd)
* -Groups of 8, 4, and 4 digits, and a subset of eight groups of 2 digits, with each group prefixed by "0x" or "0X", and separated by commas.
* {0xdddddddd, 0xdddd, 0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}}
*
* @param {string} value - String value to be verified
* @returns {boolean} True if the value is a valid GUID
*/
var isValidGUID = function isValidGUID(value) {
// remove all embedded whitespaces
value = value.replace(/\s/g, '');
var patterns = [
/^[0-9a-fA-F]{1,32}$/i,
/^[0-9a-fA-F]{1,8}(-[0-9a-fA-F]{1,4}){3}-[0-9a-fA-F]{1,12}$/i,
/^\{[0-9a-fA-F]{1,8}(-[0-9a-fA-F]{1,4}){3}-[0-9a-fA-F]{1,12}\}$/i,
/^\([0-9a-fA-F]{1,8}(-[0-9a-fA-F]{1,4}){3}-[0-9a-fA-F]{1,12}\)$/i,
/^\{0x[0-9a-fA-F]{1,8}(,0x[0-9a-fA-F]{1,4}){2},\{0x[0-9a-fA-F]{1,2}(,0x[0-9a-fA-F]{1,2}){7}\}\}$/i
];
for (var x = 0 ; x < patterns.length ; x++) {
if (patterns[x].test(value)) {
return true;
}
}
return false;
}
exports.isValidGUID = isValidGUID;
/*
* @param {object} headers - request headers
* @param {object} conditionalHeaders - Conditional headers on the following form
* ```js
* {
* ifModifiedSince: new Date(), // Specify this to perform the operation only if the resource has been modified since the specified time. (optional)
* ifUnmodifiedSince: new Date(), // Specify this to perform the operation only if the resource has not been modified since the specified date/time. (optional)
* ifMatch: '...', // ETag value. Specify this to perform the operation only if the resource's ETag matches the value specified. (optional)
* ifNoneMatch: '...' // ETag value. Specify this to perform the operation only if the resource's ETag does not match the value specified. (optional)
* }
*```
* @param {boolean} onlyDateSupport - true if the request supports only the if-modified-since and if-unmodified-since conditional headers
*/
var setConditionalHeaders = function setConditionalHeaders(headers, conditionalHeaders, onlyDateSupport) {
if (conditionalHeaders) {
if (conditionalHeaders.ifModifiedSince){
assert(conditionalHeaders.ifModifiedSince instanceof Date,
'If specified, the `options.ifModifiedSince` must be a Date');
headers['if-modified-since'] = conditionalHeaders.ifModifiedSince.toUTCString();
}
if (conditionalHeaders.ifUnmodifiedSince) {
assert(conditionalHeaders.ifUnmodifiedSince instanceof Date,
'If specified, the `options.ifUnmodifiedSince` must be a Date');
headers['if-unmodified-since'] = conditionalHeaders.ifUnmodifiedSince.toUTCString();
}
if (!onlyDateSupport) {
if (conditionalHeaders.ifMatch) headers['if-match'] = conditionalHeaders.ifMatch;
if (conditionalHeaders.ifNoneMatch) headers['if-none-match'] = conditionalHeaders.ifNoneMatch;
}
}
}
exports.setConditionalHeaders = setConditionalHeaders;
/*
* Computes a signature for the specified string using the HMAC-SHA256 algorithm.
*
* @param {string} accessKey - The access key
* @param {string} stringToSign - The UTF-8-encoded string to sign.
* @return A String that contains the HMAC-SHA256-encoded signature.
*/
var hmacSha256 = function hmacSha256(accessKey, stringToSign) {
return crypto
.createHmac('sha256', accessKey)
.update(stringToSign)
.digest('base64');
}
exports.hmacSha256 = hmacSha256;
/*
* Calculate MD5sum for the content
*/
var md5 = function md5(content) {
return crypto
.createHash('md5')
.update(content, 'utf8')
.digest('base64');
}
exports.md5 = md5;
var libxml = require('libxmljs');
/* Parse queue error, return: {message, code, detail} */
exports.queueParseError = function queueParseError(res) {
exports.parseError = function parseError(res) {
// Parse payload for error message and code

@@ -28,3 +28,4 @@ var result = {

if (detail) {
result.detail = detail.text();
// pixl-xml parser strips whitespaces from beginning and end of a node value
result.detail = detail.text().trim();
}

@@ -128,2 +129,334 @@ } catch (e) {

});
};
};
/* Parse list of containers and return object for listContainers */
exports.blobParseListContainers = function blobParseListContainers(res) {
// Get results
var xml = libxml.parseXml(res.payload);
var containers = xml.get('/EnumerationResults/Containers').childNodes();
// Construct results
var result = {
containers: containers.map(function(container) {
var metadata = undefined;
var metaNode = container.get('Metadata');
if (metaNode) {
metadata = {};
metaNode.childNodes().forEach(function(node) {
metadata[node.name()] = node.text();
});
}
var properties = undefined;
var propsNode = container.get('Properties');
if (propsNode) {
properties = {};
properties.eTag = propsNode.get('Etag').text();
properties.lastModified = propsNode.get('Last-Modified').text();
properties.leaseStatus = propsNode.get('LeaseStatus').text();
properties.leaseState = propsNode.get('LeaseState').text();
if (propsNode.get('LeaseDuration')) {
properties.leaseDuration = propsNode.get('LeaseDuration').text();
}
if (propsNode.get('PublicAccess')) {
properties.publicAccessLevel = propsNode.get('PublicAccess').text();
}
}
return {
name: container.get('Name').text(),
properties: properties,
metadata: metadata
};
})
};
// Get Marker, Prefix, MaxResults and NextMarker, if present
var marker = xml.get('/EnumerationResults/Marker');
if (marker) {
result.marker = marker.text();
}
var prefix = xml.get('/EnumerationResults/Prefix');
if (prefix) {
result.prefix = prefix.text();
}
var maxResults = xml.get('/EnumerationResults/MaxResults');
if (maxResults) {
result.maxResults = parseInt(maxResults.text());
}
var nextMarker = xml.get('/EnumerationResults/NextMarker');
if (nextMarker ) {
result.nextMarker = nextMarker.text();
}
// Return result
return result;
};
/* Parse container ACL and return object to getContainerACL */
exports.blobParseContainerACL = function blobParseContainerACL(response) {
var xml = libxml.parseXml(response.payload);
var signedIdentifiers = xml.get('/SignedIdentifiers').childNodes();
// Construct results
var result = [];
result = signedIdentifiers.map(function(signedIdentifier) {
var policy = {};
var id = signedIdentifier.get('Id');
if (id) {
policy.id = id.text();
}
var accessPolicy = signedIdentifier.get('AccessPolicy');
if (accessPolicy) {
var start = accessPolicy.get('Start');
if (start) {
policy.start = start.text();
}
var expiry = accessPolicy.get('Expiry');
if (expiry) {
policy.expiry = expiry.text();
}
// Default values for permission
policy.permission = {
read: false,
add: false,
create: false,
write: false,
delete: false,
list: false
}
var permission = accessPolicy.get('Permission');
if (permission) {
permission = permission.text();
policy.permission.read = permission.indexOf('r') !== -1;
policy.permission.add = permission.indexOf('a') !== -1;
policy.permission.create = permission.indexOf('c') !== -1;
policy.permission.write = permission.indexOf('w') !== -1;
policy.permission.delete = permission.indexOf('d') !== -1;
policy.permission.list = permission.indexOf('l') !== -1;
}
}
return policy;
});
// return the result
return result;
};
/* Parse list of blobs and return object for listBlobs */
exports.blobParseListBlobs = function blobParseListBlobs(response) {
var xml = libxml.parseXml(response.payload);
var result = {
blobs: []
};
if (xml.get('Blobs')){
var blobs = xml.get('Blobs').childNodes();
result.blobs = blobs.map(function(blob){
var theBlob = {};
theBlob.name = blob.get('Name').text();
var snapshot = blob.get('Snapshot');
if (snapshot){
theBlob.snapshot = snapshot.text();
}
var properties = blob.get('Properties');
var lastModified = properties.get('Last-Modified');
if (lastModified){
theBlob.lastModified = lastModified.text();
}
var eTag = properties.get('Etag');
if (eTag){
theBlob.eTag = eTag.text();
}
var contentLength = properties.get('Content-Length');
if (contentLength) {
theBlob.contentLength = contentLength.text();
}
var contentType = properties.get('Content-Type');
if (contentType) {
theBlob.contentType = contentType.text();
}
var contentEncoding = properties.get('Content-Encoding');
if (contentEncoding) {
theBlob.contentEncoding = contentEncoding.text();
}
var contentLanguage = properties.get('Content-Language');
if (contentLanguage) {
theBlob.contentLanguage = contentLanguage.text();
}
var contentMD5 = properties.get('Content-MD5');
if (contentMD5) {
theBlob.contentMD5 = contentMD5.text();
}
var cacheControl = properties.get('Cache-Control');
if (cacheControl) {
theBlob.cacheControl = cacheControl.text();
}
var xmsBlobSequenceNumber = properties.get('x-ms-blob-sequence-number');
if (xmsBlobSequenceNumber) {
theBlob.xmsBlobSequenceNumber = xmsBlobSequenceNumber.text();
}
theBlob.type = properties.get('BlobType').text();
var leaseStatus = properties.get('LeaseStatus');
if (leaseStatus) {
theBlob.leaseStatus = leaseStatus.text();
}
var leaseState = properties.get('LeaseState');
if (leaseState) {
theBlob.leaseState = leaseState.text();
}
var leaseDuration = properties.get('LeaseDuration');
if (leaseDuration) {
theBlob.leaseDuration = leaseDuration.text();
}
var copyId = properties.get('CopyId');
if(copyId) {
theBlob.copyId = copyId.text();
}
var copyStatus = properties.get('CopyStatus');
if(copyStatus) {
theBlob.copyStatus = copyStatus.text();
}
var copySource = properties.get('CopySource');
if(copySource) {
theBlob.copySource = copySource.text();
}
var copyProgress = properties.get('CopyProgress');
if(copyProgress) {
theBlob.copyProgress = copyProgress.text();
}
var copyCompletionTime = properties.get('CopyCompletionTime');
if(copyCompletionTime) {
theBlob.copyCompletionTime = copyCompletionTime.text();
}
var copyStatusDescription = properties.get('CopyStatusDescription');
if(copyStatusDescription) {
theBlob.copyStatusDescription = copyStatusDescription.text();
}
theBlob.serverEncrypted = properties.get('ServerEncrypted').text();
var metadata = undefined;
var metaNode = blob.get('Metadata');
if (metaNode) {
metadata = {};
metaNode.childNodes().forEach(function(node) {
metadata[node.name()] = node.text();
});
}
if (metadata) {
theBlob.metadata = metadata;
}
return theBlob;
});
}
// Get Marker, Prefix, MaxResults and NextMarker, if present
var marker = xml.get('/EnumerationResults/Marker');
if (marker) {
result.marker = marker.text();
}
var prefix = xml.get('/EnumerationResults/Prefix');
if (prefix) {
result.prefix = prefix.text();
}
var maxResults = xml.get('/EnumerationResults/MaxResults');
if (maxResults) {
result.maxResults = parseInt(maxResults.text());
}
var nextMarker = xml.get('/EnumerationResults/NextMarker');
if (nextMarker) {
result.nextMarker = nextMarker.text();
}
var delimiter = xml.get('/EnumerationResults/Delimiter');
if (delimiter) {
result.nextMarker = delimiter.text();
}
return result;
}
/* Parse list of blocks and return object for getBlockList */
exports.blobParseListBlock = function blobParseListBlock(response) {
var xml = libxml.parseXml(response.payload);
var result = {};
var blockList = xml.get('/BlockList');
var getBlockInfo = function(block) {
return {
blockId: block.get('Name').text(),
size: block.get('Size').text()
}
};
if (blockList.get('CommittedBlocks')) {
var committedBlocksNodes = blockList.get('CommittedBlocks').childNodes();
result.committedBlocks = committedBlocksNodes.map(getBlockInfo);
}
if (blockList.get('UncommittedBlocks')) {
var uncommittedBlocks = blockList.get('UncommittedBlocks').childNodes();
result.uncommittedBlocks = uncommittedBlocks.map(getBlockInfo);
}
return result;
}
exports.blobParseServiceProperties = function blobParseServiceProperties(response) {
var xml = libxml.parseXml(response.payload);
var result = {};
var properties = xml.get('/StorageServiceProperties');
if (properties.get('Logging')){
var logging = properties.get('Logging');
result.logging = {};
result.logging.version = logging.get('Version').text();
result.logging.delete = logging.get('Delete').text();
result.logging.read = logging.get('Read').text();
result.logging.write = logging.get('Write').text();
result.logging.retentionPolicy = {};
result.logging.retentionPolicy.enabled = logging.get('RetentionPolicy/Enabled').text();
if(logging.get('RetentionPolicy/Days')) result.logging.retentionPolicy.days = logging.get('RetentionPolicy/Days').text();
}
if (properties.get('HourMetrics')){
var hourMetrics = properties.get('HourMetrics');
result.hourMetrics = {};
result.hourMetrics.version = hourMetrics.get('Version').text();
result.hourMetrics.enabled = hourMetrics.get('Enabled').text();
if (hourMetrics.get('IncludeAPIs')) result.hourMetrics.includeAPIs = hourMetrics.get('IncludeAPIs').text();
result.hourMetrics.retentionPolicy = {};
result.hourMetrics.retentionPolicy.enabled = hourMetrics.get('RetentionPolicy/Enabled').text();
if(hourMetrics.get('RetentionPolicy/Days')) result.hourMetrics.retentionPolicy.days = hourMetrics.get('RetentionPolicy/Days').text();
}
if (properties.get('MinuteMetrics')){
var minuteMetrics = properties.get('MinuteMetrics');
result.minuteMetrics = {};
result.minuteMetrics.version = minuteMetrics.get('Version').text();
result.minuteMetrics.enabled = minuteMetrics.get('Enabled').text();
if (minuteMetrics.get('IncludeAPIs')) result.minuteMetrics.includeAPIs = minuteMetrics.get('IncludeAPIs').text();
result.minuteMetrics.retentionPolicy = {};
result.minuteMetrics.retentionPolicy.enabled = minuteMetrics.get('RetentionPolicy/Enabled').text();
if(minuteMetrics.get('RetentionPolicy/Days')) result.minuteMetrics.retentionPolicy.days = minuteMetrics.get('RetentionPolicy/Days').text();
}
if (properties.get('Cors')){
result.corsRules = [];
var rules = properties.get('Cors').childNodes();
result.corsRules = rules.map(function(rule) {
return {
allowedOrigins: rule.get('AllowedOrigins').text(),
allowedMethods: rule.get('AllowedMethods').text(),
maxAgeInSeconds: rule.get('MaxAgeInSeconds').text(),
exposedHeaders: rule.get('ExposedHeaders').text(),
allowedHeaders: rule.get('AllowedHeaders').text()
};
});
}
return result;
}
var XML = require('pixl-xml');
/* Parse queue error, return: {message, code, detail} */
exports.queueParseError = function queueParseError(res) {
exports.parseError = function parseError(res) {
// Parse payload for error message and code

@@ -13,2 +13,3 @@ var result = {

var xml = XML.parse(res.payload);
result.message = xml.Message;

@@ -116,1 +117,326 @@ result.code = xml.Code;

};
/* Parse list of containers and return object for listContainers */
exports.blobParseListContainers = function blobParseListContainers(res) {
// Get results
var xml = XML.parse(res.payload);
var containers = (xml.Containers || {}).Container || [];
if(!(containers instanceof Array)) {
containers = [containers];
}
// Construct results
var result = {
containers: containers.map(function(container) {
var metadata = undefined;
if (container.hasOwnProperty('Metadata')) {
metadata = container.Metadata || {};
}
var properties = undefined;
if (container.hasOwnProperty('Properties')) {
properties = {};
properties.eTag = container.Properties.Etag;
properties.lastModified = container.Properties['Last-Modified'];
properties.leaseStatus = container.Properties.LeaseStatus;
properties.leaseState = container.Properties.LeaseState;
if (container.Properties.hasOwnProperty('LeaseDuration')) {
properties.leaseDuration = container.Properties.LeaseDuration;
}
if (container.Properties.hasOwnProperty('PublicAccess')) {
properties.publicAccessLevel = container.Properties.PublicAccess;
}
}
return {
name: container.Name,
properties: properties,
metadata: metadata
};
})
};
// Get Marker, Prefix, MaxResults and NextMarker, if present
if (xml.hasOwnProperty('Marker')) {
result.marker = xml.Marker;
}
if (xml.hasOwnProperty('Prefix')) {
result.prefix = xml.Prefix;
}
if (xml.hasOwnProperty('MaxResults')) {
result.maxResults = parseInt(xml.MaxResults);
}
if (xml.hasOwnProperty('NextMarker')) {
result.nextMarker = xml.NextMarker;
}
// Return result
return result;
};
/* Parse container ACL and return object to getContainerACL */
exports.blobParseContainerACL = function blobParseContainerACL(response) {
var xml = XML.parse(response.payload);
var signedIdentifiers = xml.SignedIdentifier || [];
if(!(signedIdentifiers instanceof Array)) {
signedIdentifiers = [signedIdentifiers];
}
var result = [];
// Construct results
result = signedIdentifiers.map(function(signedIdentifier) {
var policy = {};
policy.id = signedIdentifier.Id;
if (signedIdentifier.hasOwnProperty('AccessPolicy')){
var accessPolicy = signedIdentifier.AccessPolicy;
if (accessPolicy.hasOwnProperty('Start')) {
policy.start = accessPolicy.Start;
}
if (accessPolicy.hasOwnProperty('Expiry')) {
policy.expiry = accessPolicy.Expiry;
}
// Default values for permission
policy.permission = {
read: false,
add: false,
create: false,
write: false,
delete: false,
list: false
}
if (accessPolicy.hasOwnProperty('Permission')) {
var permission = accessPolicy.Permission;
policy.permission.read = permission.indexOf('r') !== -1;
policy.permission.add = permission.indexOf('a') !== -1;
policy.permission.create = permission.indexOf('c') !== -1;
policy.permission.write = permission.indexOf('w') !== -1;
policy.permission.delete = permission.indexOf('d') !== -1;
policy.permission.list = permission.indexOf('l') !== -1;
}
}
return policy;
});
return result;
};
/* Parse list of blobs and return object for listBlobs */
exports.blobParseListBlobs = function blobParseListBlobs(response) {
var xml = XML.parse(response.payload);
var blobs = (xml.Blobs || {}).Blob || [];
if(!(blobs instanceof Array)) {
blobs = [blobs];
}
var result = {};
result.blobs = blobs.map(function(blob) {
var theBlob = {};
theBlob.name = blob.Name;
if (blob.hasOwnProperty('Snapshot')) {
theBlob.snapshot = blob.Snapshot;
}
var properties = blob.Properties;
if (properties.hasOwnProperty('Last-Modified')){
theBlob.lastModified = properties['Last-Modified'];
}
if (properties.hasOwnProperty('Etag')){
theBlob.eTag = properties.Etag;
}
if (properties.hasOwnProperty('Content-Length')){
theBlob.contentLength = properties['Content-Length'];
}
if (properties.hasOwnProperty('Content-Type')){
theBlob.contentType = properties['Content-Type'];
}
if (properties.hasOwnProperty('Content-Encoding')){
theBlob.contentEncoding = properties['Content-Encoding'];
}
if (properties.hasOwnProperty('Content-Language')){
theBlob.contentLanguage = properties['Content-Language'];
}
if (properties.hasOwnProperty('Content-MD5')){
theBlob.contentMD5 = properties['Content-MD5'];
}
if (properties.hasOwnProperty('Cache-Control')){
theBlob.cacheControl = properties['Cache-Control'];
}
if (properties.hasOwnProperty('x-ms-blob-sequence-number')){
theBlob.xmsBlobSequenceNumber = properties['x-ms-blob-sequence-number'];
}
theBlob.type = properties.BlobType;
if (properties.hasOwnProperty('LeaseStatus')){
theBlob.leaseStatus = properties.LeaseStatus;
}
if (properties.hasOwnProperty('LeaseState')){
theBlob.leaseState = properties.LeaseState;
}
if (properties.hasOwnProperty('LeaseDuration')){
theBlob.leaseDuration = properties.LeaseDuration;
}
if (properties.hasOwnProperty('CopyId')){
theBlob.copyId = properties.CopyId;
}
if (properties.hasOwnProperty('CopyStatus')){
theBlob.copyStatus = properties.CopyStatus;
}
if (properties.hasOwnProperty('CopySource')){
theBlob.copySource = properties.CopySource;
}
if (properties.hasOwnProperty('CopyProgress')){
theBlob.copyProgress = properties.CopyProgress;
}
if (properties.hasOwnProperty('CopyCompletionTime')){
theBlob.copyCompletionTime = properties.CopyCompletionTime;
}
if (properties.hasOwnProperty('CopyStatusDescription')){
theBlob.copyStatusDescription = properties.CopyStatusDescription;
}
theBlob.serverEncrypted = properties.ServerEncrypted;
var metadata = undefined;
if (blob.hasOwnProperty('Metadata')) {
metadata = blob.Metadata || {};
}
if (metadata) {
theBlob.metadata = metadata;
}
return theBlob;
});
// Get Marker, Prefix, MaxResults and NextMarker, if present
if (xml.hasOwnProperty('Marker')) {
result.marker = xml.Marker;
}
if (xml.hasOwnProperty('Prefix')) {
result.prefix = xml.Prefix;
}
if (xml.hasOwnProperty('MaxResults')) {
result.maxResults = parseInt(xml.MaxResults);
}
if (xml.hasOwnProperty('NextMarker')) {
result.nextMarker = xml.NextMarker;
}
if (xml.hasOwnProperty('Delimiter')) {
result.delimiter = xml.Delimiter;
}
// Return result
return result;
};
/* Parse list of blocks and return object for getBlockList */
exports.blobParseListBlock = function blobParseListBlock(response) {
var xml = XML.parse(response.payload);
var result = {};
var getBlockInfo = function(block){
return {
blockId: block.Name,
size: block.Size
}
};
if (xml.hasOwnProperty('CommittedBlocks')) {
var blocks = (xml.CommittedBlocks || {}).Block || [];
if(!(blocks instanceof Array)) {
blocks = [blocks];
}
result.committedBlocks = blocks.map(getBlockInfo);
}
if (xml.hasOwnProperty('UncommittedBlocks')) {
var blocks = (xml.UncommittedBlocks || {}).Block || [];
if(!(blocks instanceof Array)) {
blocks = [blocks];
}
result.uncommittedBlocks = blocks.map(getBlockInfo);
}
return result;
};
/* Parse the blob service properties and return object for getServiceProperties */
exports.blobParseServiceProperties = function blobParseServiceProperties(response) {
var xml = XML.parse(response.payload);
var result = {};
if (xml.hasOwnProperty('Logging')) {
result.logging = {
version: xml.Logging.Version,
delete: xml.Logging.Delete,
read: xml.Logging.Read,
write: xml.Logging.Write,
retentionPolicy: {
enabled: xml.Logging.RetentionPolicy.Enabled
}
};
if (xml.Logging.RetentionPolicy.hasOwnProperty('Days')){
result.logging.retentionPolicy.days = xml.Logging.RetentionPolicy.Days;
}
}
if (xml.hasOwnProperty('HourMetrics')) {
result.hourMetrics = {
version: xml.HourMetrics.Version,
enabled: xml.HourMetrics.Enabled
};
if (xml.HourMetrics.hasOwnProperty('IncludeAPIs')) {
result.hourMetrics.includeAPIs = xml.HourMetrics.IncludeAPIs;
}
result.hourMetrics.retentionPolicy = {
enabled: xml.HourMetrics.RetentionPolicy.Enabled
};
if (xml.HourMetrics.RetentionPolicy.hasOwnProperty('Days')){
result.hourMetrics.retentionPolicy.days = xml.HourMetrics.RetentionPolicy.Days;
}
}
if (xml.hasOwnProperty('MinuteMetrics')) {
result.minuteMetrics = {
version: xml.MinuteMetrics.Version,
enabled: xml.MinuteMetrics.Enabled
};
if (xml.MinuteMetrics.hasOwnProperty('IncludeAPIs')) {
result.minuteMetrics.includeAPIs = xml.MinuteMetrics.IncludeAPIs;
}
result.minuteMetrics.retentionPolicy = {
enabled: xml.MinuteMetrics.RetentionPolicy.Enabled
};
if (xml.MinuteMetrics.RetentionPolicy.hasOwnProperty('Days')){
result.minuteMetrics.retentionPolicy.days = xml.MinuteMetrics.RetentionPolicy.Days;
}
}
if (xml.hasOwnProperty('Cors')) {
var rules = (xml.Cors || {}).CorsRule || [];
if(!(rules instanceof Array)) {
rules = [rules];
}
result.corsRules = rules.map(function(rule) {
return {
allowedOrigins: rule.AllowedOrigins,
allowedMethods: rule.AllowedMethods,
maxAgeInSeconds: rule.MaxAgeInSeconds,
exposedHeaders: rule.ExposedHeaders,
allowedHeaders: rule.AllowedHeaders
};
});
}
return result;
};
{
"name": "fast-azure-storage",
"version": "0.3.7",
"author": "Jonas Finnemann Jensen <jopsen@gmail.com>",
"version": "1.0.0",
"author": "Jonas Finnemann Jensen <jopsen@gmail.com>, Elena Solomon <elenasolomon28@gmail.com>",
"description": "Fast client library for azure storage services",

@@ -17,2 +17,5 @@ "license": "MPL-2.0",

},
"engines": {
"node": ">=4"
},
"dependencies": {

@@ -19,0 +22,0 @@ "debug": "^2.2.0",

@@ -10,3 +10,3 @@ Fast Azure Storage Client for Node.js

At this point this library implement most of the APIs for queue and table
At this point this library implement most of the APIs for queue, table and blob
storage. Pull request with additional feature additions will generally be

@@ -22,3 +22,3 @@ accepted, as long as patches don't compromise efficiency.

---------------------
Both `Queue` and `Table` takes a range of common configuration options.
All three clients, `Queue`, `Table` and `Blob`, take a range of common configuration options.

@@ -38,5 +38,6 @@ ### Authentication Options

// Create queue and table clients
// Create queue, table and blob clients
var queue = new azure.Queue(options);
var table = new azure.Table(options);
var blob = new azure.Blob(options);
```

@@ -71,3 +72,3 @@

optimized for Azure Storage service to reduce latency and avoid errors.
By default both `Table` and `Queue` clients will use a global instance of this
By default,`Blob`,`Table` and `Queue` clients will use a global instance of this
custom agent configured to allow 100 connections per host.

@@ -182,1 +183,59 @@

Azure Blob Storage Client
--------------------------
The Azure Blob Storage client aims at interfacing Azure Blob Storage.
Using this client, text and binary data can be stored in one of the following types
of blob:
* Block blobs, which are optimized for upload large blobs
* Append blobs, which are optimized for append operations, making it ideal for
eg. logging, auditing
Simple example of a container and blob creation.
```js
// Load fast-azure-storage client
var azure = require('fast-azure-storage');
var blob = new azure.Blob({
accountId: '...',
accessKey: '...'
});
var blobContent = 'Sample content'; // The content can be a string or a Buffer
// Create container and upload a blob
blob.createContainer('mycontainer').then(function() {
return blob.putBlob('mycontainer', 'myblob', {
type: 'BlockBlob', // Type of the blob
}, blobContent);
});
```
### Blob API Reference
See also [reference documentation](https://taskcluster.github.io/fast-azure-storage/).
* `Blob(options)`
* `Blob#setServiceProperties(options)`
* `Blob#getServiceProperties()`
* `Blob#createContainer(name, options)`
* `Blob#setContainerMetadata(name, metadata, options)`
* `Blob#getContainerMetadata(name, options)`
* `Blob#deleteContainer(name, options)`
* `Blob#listContainers(options)`
* `Blob#getContainerProperties(name, options)`
* `Blob#getContainerACL(name, options)`
* `Blob#setContainerACL(name, options)`
* `Blob#listBlobs(container, options)`
* `Blob#leaseContainer(name, options)`
* `Blob#putBlob(container, blob, options, content)`
* `Blob#getBlob(container, blob, options)`
* `Blob#getBlobProperties(container, blob, options)`
* `Blob#setBlobProperties(container, blob, options)`
* `Blob#getBlobMetadata(container, blob, options)`
* `Blob#setBlobMetadata(container, blob, metadata, options)`
* `Blob#deleteBlob(container, blob, options)`
* `Blob#putBlock(container, blob, options, content)`
* `Blob#putBlockList(container, blob, options)`
* `Blob#getBlockList(container, blob, options)`
* `Blob#getBlockId(prefix, blockNumber, length)`
* `Blob#appendBlock(container, blob, options, content)`
* `Blob#sas(container, blob, options)`

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc