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

azurite

Package Overview
Dependencies
Maintainers
1
Versions
156
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

azurite - npm Package Compare versions

Comparing version 0.8.0 to 0.8.1

lib/utils.js

8

lib/api/GetBlob.js

@@ -20,3 +20,3 @@ 'use strict';

if (req.query.snapshot) {
blob.setSnapshotDate(req.query.params.snapshot);
blob.setSnapshotDate(req.query.snapshot);
}

@@ -34,5 +34,3 @@ storageManager.getBlob(containerName, blob)

// Fixme: Depending on whether the blob refers to a virtual directory or a snapshot the path differs.
// We need the same mechanism that we use for storage url (see env.storageUrl) for workspace directory.
const fullPath = path.join(env.localStoragePath, containerName, blobName);
const fullPath = env.diskStorageUri(containerName, blob);
const readStream = fs.createReadStream(fullPath, {

@@ -59,3 +57,3 @@ flags: 'r',

} else {
request(this._addRequestHeader(env.storageUrl(env.port, containerName, blob), range))
request(this._addRequestHeader(env.webStorageUri(env.port, containerName, blob), range))
.on('response', (staticResponse) => {

@@ -62,0 +60,0 @@ result.httpProps['Content-Length'] = staticResponse.headers['content-length'];

'use strict';
const storageManager = require('./../StorageManager'),
Blob = require('./../model/Blob'),
ResponseHeader = require('./../model/ResponseHeader');

@@ -11,3 +12,7 @@

process(req, res, containerName, blobName) {
storageManager.getBlobMetadata(containerName, blobName)
const blob = new Blob(blobName, req.headers);
if (req.query.snapshot) {
blob.setSnapshotDate(req.query.snapshot);
}
storageManager.getBlobMetadata(containerName, blob)
.then((result) => {

@@ -14,0 +19,0 @@ res.set(new ResponseHeader(result.httpProps, result.metaProps));

'use strict';
const storageManager = require('./../StorageManager'),
Blob = require('./../model/Blob'),
ResponseHeader = require('./../model/ResponseHeader');

@@ -11,3 +12,7 @@

process(req, res, containerName, blobName) {
storageManager.getBlobProperties(containerName, blobName)
const blob = new Blob(blobName, req.headers);
if (req.query.snapshot) {
blob.setSnapshotDate(req.query.snapshot);
}
storageManager.getBlobProperties(containerName, blob)
.then((result) => {

@@ -14,0 +19,0 @@ const optionalProps = {

@@ -18,3 +18,3 @@ 'use strict';

const model = this._createModel(result.pageRanges);
res.set(new ResponseHeader({ 'x-ms-blob-content-length': result.httpProps['Content-Length'] }));
res.set(new ResponseHeader({ 'x-ms-blob-content-length': result.size }));
res.status(200).send(model.toString());

@@ -21,0 +21,0 @@ })

@@ -21,3 +21,3 @@ 'use strict';

xmlDoc = xmlDoc.replace(/\>[\s]+\</g, '><');
res.set(new ResponseHeader({ 'Content-Type': 'application/xml', 'Content-Length': xmlDoc.length }));
res.set(new ResponseHeader({ 'Content-Type': 'application/xml' }));
res.status(200).send(xmlDoc);

@@ -24,0 +24,0 @@ })

@@ -18,3 +18,3 @@ 'use strict';

res.set(new ResponseHeader(response));
res.status(201).send('Created');
res.status(201).send();
})

@@ -21,0 +21,0 @@ .catch((e) => {

'use strict';
const path = require('path'),
const utils = require('./utils'),
path = require('path'),
BbPromise = require('bluebird'),

@@ -36,3 +37,13 @@ fs = BbPromise.promisifyAll(require("fs-extra"));

storageUrl(port, container, blob) {
/**
* Based on the container name and blob it creates the according URI that is served by Azurite's web interface.
*
* @param {number} port
* @param {string} containerName
* @param {model.Blob} blob
* @returns
*
* @memberof Environment
* */
webStorageUri(port, containerName, blob) {
return (blob.isVirtualDirectory() && !blob.isSnapshot())

@@ -42,6 +53,37 @@ ? `http://localhost:${port}/blobs/${this.virtualDirUri}/${container}/${blob.publicName()}`

? `http://localhost:${port}/blobs/${this.snapshotUri}/${container}/${blob.publicName()}`
: `http://localhost:${port}/blobs/${container}/${blob.name}`;
: `http://localhost:${port}/blobs/${containerName}/${blob.name}`;
}
/**
* Based on the blob name it creates the full path to the location on disk.
*
* Virtual directories are stored in a special folder that is not accessible through the Standard REST API.
* This is to make sure that not special characters or words need to be reserved in the regular blob workspace.
* Since virtual directories contain trailing slashes (which are invalid filename characters) we store the
* Base64 representation on disk.
*
* Snapshots are also stored in a special folder since we encode the snapshot date into the name as <blobname>-<snapshotId>.
*
* @param {string} containerName
* @param {model.Blob} blob
* @returns Full path on disk
*
* @memberof StorageManager
*/
diskStorageUri(containerName, blob) {
let containerPath;
if (blob.isVirtualDirectory()) {
containerPath = path.join(this.virtualDirPath, containerName);
} else if (blob.isSnapshot()) {
containerPath = path.join(this.snapshotPath, containerName);
} else {
containerPath = path.join(this.localStoragePath, containerName);
}
const blobPath = path.join(containerPath, blob.publicName());
return (blob.isVirtualDirectory())
? blobPath
: utils.escapeBlobDelimiter(blobPath);
}
}
module.exports = new Environment();

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

this.httpProps['Last-Modified'] = httpHeader['Last-Modified'] || new Date().toGMTString();
this.httpProps.ETag = httpHeader.ETag || 1;
this.httpProps.ETag = httpHeader.ETag || 0;
this.httpProps['Content-Length'] = httpHeader['Content-Length'] || httpHeader['content-length'];

@@ -29,0 +29,0 @@ // x-ms-* attributes have precedence over according HTTP-Headers

'use strict';
const env = require('./env'),
utils = require('./utils'),
path = require('path'),

@@ -144,2 +145,3 @@ BbPromise = require('bluebird'),

delete blob.httpProps['Content-Length'];
if (blobResult.length === 0) {

@@ -166,3 +168,3 @@ const newBlob = coll.insert({

}
return fs.outputFileAsync(this._getStoragePath(containerName, blob), body, { encoding: blob.httpProps['Content-Encoding'] })
return fs.outputFileAsync(env.diskStorageUri(containerName, blob), body, { encoding: blob.httpProps['Content-Encoding'] })
.then(() => {

@@ -205,4 +207,5 @@ return response;

updateBlob.size += body.length;
updateBlob.httpProps.ETag++;
coll.update(updateBlob);
return fs.appendFileAsync(this._getStoragePath(containerName, blob), body, { encoding: updateBlob.httpProps['Content-Encoding'] })
return fs.appendFileAsync(env.diskStorageUri(containerName, blob), body, { encoding: updateBlob.httpProps['Content-Encoding'] })
.then(() => {

@@ -218,3 +221,3 @@ return response;

new RootValidator({
requestBlob: { name: blob.name },
requestBlob: { publicName: () => { return blob.name } },
collection: coll

@@ -225,3 +228,3 @@ })

coll.chain().find({ 'name': { '$eq': blob.name } }).remove();
return fs.removeAsync(this._getStoragePath(containerName, blob));
return fs.removeAsync(env.diskStorageUri(containerName, blob));
});

@@ -243,3 +246,4 @@ }

const blob = coll.chain()
.find({ 'name': { '$eq': requestBlob.name } })
// FIXME: This query needs to include snapshot eq true if blob is a snapshot otherwise snapshot eq false
.find({ 'name': { '$eq': requestBlob.publicName() } })
.data()[0];

@@ -264,2 +268,3 @@ response.httpProps = blob.httpProps;

let blobs = coll.chain()
// FIXME: Depending on include=snapshots query needs to be adaped, per default snapshots are not shown (snapshot eq false)
.find({ 'name': { '$contains': options.prefix } })

@@ -300,2 +305,4 @@ .simplesort('name')

.data();
delete options.blob.httpProps['Content-Length'];
// We only create the blob in DB if it does not already exists.

@@ -341,7 +348,7 @@ if (parentBlobResult.length === 0) {

// Make sure that the parent blob exists on storage.
return fs.ensureFileAsync(this._getStoragePath(containerName, options.blob))
return fs.ensureFileAsync(env.diskStorageUri(containerName, options.blob))
.then(() => {
// Writing block to disk.
const blockPath = path.join(env.commitsPath, options.fileName);
return fs.outputFileAsync(this._escapeBlobDelimiter(blockPath), body, { encoding: options.blob.httpProps['Content-Encoding'] });
return fs.outputFileAsync(utils.escapeBlobDelimiter(blockPath), body, { encoding: options.blob.httpProps['Content-Encoding'] });
})

@@ -365,3 +372,3 @@ .then(() => {

validator.run(BlobExistsVal, {
requestBlob: { name: blockName }
requestBlob: { publicName: () => { return blockName } }
});

@@ -381,2 +388,3 @@ }

delete blob.httpProps['Content-Length'];
if (blobResult.length == 0) {

@@ -409,3 +417,3 @@ const newBlob = coll.insert({

return new BbPromise((resolve, reject) => {
const destinationStream = fs.createWriteStream(this._getStoragePath(containerName, blob));
const destinationStream = fs.createWriteStream(env.diskStorageUri(containerName, blob));
destinationStream

@@ -461,3 +469,3 @@ .on('error', (e) => {

.run(ContainerExistsVal, { containerName: containerName, collection: this.db.getCollection(StorageTables.Containers) })
.run(BlobExistsVal)
.run(BlobExistsVal, { requestBlob: { publicName: () => { return blobName } } })
.run(SupportedBlobTypeVal)

@@ -503,3 +511,3 @@ .run(IsOfBlobTypeVal, { blobType: BlobTypes.BlockBlob });

getBlobMetadata(containerName, blobName) {
getBlobMetadata(containerName, requestBlob) {
return BbPromise.try(() => {

@@ -512,6 +520,6 @@ new RootValidator()

.run(BlobExistsVal, {
requestBlob: { name: blobName },
requestBlob: requestBlob,
collection: this.db.getCollection(containerName)
});
const res = this._getCollectionAndBlob(containerName, blobName),
const res = this._getCollectionAndBlob(containerName, requestBlob.publicName()),
blob = res.blob,

@@ -557,5 +565,5 @@ httpProps = blob.httpProps,

getBlobProperties(containerName, blobName) {
getBlobProperties(containerName, requestBlob) {
// For block blobs return values are equal in Azurite
return this.getBlobMetadata(containerName, blobName);
return this.getBlobMetadata(containerName, requestBlob);
}

@@ -663,3 +671,3 @@

blobPath = path.join(env.localStoragePath, containerName, blob.name),
writeStream = fs.createWriteStream(this._escapeBlobDelimiter(blobPath), {
writeStream = fs.createWriteStream(utils.escapeBlobDelimiter(blobPath), {
flags: 'r+',

@@ -743,3 +751,3 @@ start: startByte,

pageRanges: pageRanges,
httpProps: res.blob.httpProps
size: res.blob.size
};

@@ -824,3 +832,3 @@ });

snapshotBlob.metaProps = requestBlob.metaProps;
snapshotBlob.ETag += 1;
snapshotBlob.httpProps.ETag += 1;
snapshotBlob.httpProps['Last-Modified'] = requestBlob.httpProps['Last-Modified'];

@@ -833,3 +841,3 @@ }

.then(() => {
return fs.copyAsync(this._getStoragePath(containerName, requestBlob), destPath);
return fs.copyAsync(env.diskStorageUri(containerName, requestBlob), destPath);
})

@@ -925,49 +933,4 @@ .then(() => {

}
/**
* Based on the blob name it creates the full path to the location on disk. Virtual directories
* are stored in a special folder that is not accessible through the Standard REST API. This is
* to make sure that not special characters or words need to be reserved in the regular blob workspace.
* Since virtual directories contain trailing slashes (which are invalid filename characters) we store the
* Base64 representation on disk.
*
* @param {any} containerName
* @param {any} blob
* @returns Full path on disk
*
* @memberof StorageManager
*/
_getStoragePath(containerName, blob) {
let containerPath;
if (blob.isVirtualDirectory()) {
containerPath = path.join(env.virtualDirPath, containerName);
} else if (blob.isSnapshot()) {
containerPath = path.join(env.snapshotPath, containerName);
} else {
containerPath = path.join(env.localStoragePath, containerName);
}
const blobPath = path.join(containerPath, blob.publicName());
return (blob.isVirtualDirectory())
? blobPath
: this._escapeBlobDelimiter(blobPath);
}
/**
* Not all allowed delimiters for blob names are valid file names. We thus replace those that are invalid with the valid
* delimiter @ on disk. Note that in our in-memory database and thus for the external interface we still
* use the originally chosen delimiter.
*/
_escapeBlobDelimiter(blobPath) {
if (process.platform === 'win32') {
const pathWithoutLetter = blobPath.substr(2);
if (pathWithoutLetter === '') {
return blobPath;
}
return (blobPath.substr(0, 2) + pathWithoutLetter.replace(/(::|:|\/|\||\/\/)/g, '@'));
} else {
return blobPath.replace(/(::|:|\||\$)/g, '@');
}
}
}
module.exports = new StorageManager;

@@ -23,4 +23,5 @@ 'use strict';

}
const name = options.requestBlob.name;
const name = options.requestBlob.publicName();
const coll = options.collection;
// FIXME: The query needs to include snapshot eq true if blob is a snapshot
if (!coll || coll.chain().find({ name: { '$eq': name } }).data().length !== 1) {

@@ -27,0 +28,0 @@ throw new AError(ErrorCodes.BlobNotFound);

{
"name": "azurite",
"version": "0.8.0",
"version": "0.8.1",
"description": "A lightweight server clone of Azure Blob Storage that simulates most of the commands supported by it with minimal dependencies.",

@@ -5,0 +5,0 @@ "scripts": {

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

expect(item).to.have.property('name', 'testItem');
expect(item.httpProps).to.have.property('ETag', 1);
expect(item.httpProps).to.have.property('ETag', 0);
expect(item.httpProps).to.have.property('Last-Modified');

@@ -33,3 +33,3 @@ expect(item.httpProps).to.have.property('Content-Type', 'application/octet-stream');

const item = new StorageItem('testItem', httpHeader);
expect(item.httpProps).to.have.property('ETag', 1);
expect(item.httpProps).to.have.property('ETag', 0);
expect(item.httpProps).to.have.property('Last-Modified');

@@ -36,0 +36,0 @@ expect(item.httpProps).to.have.property('Content-Type', 'ContentType');

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