Comparing version 0.4.2 to 0.4.3
@@ -25,6 +25,7 @@ 'use strict'; | ||
init(options) { | ||
env.localStoragePath = options.l || options.location || './'; | ||
env.port = options.p || options.port || 10000; | ||
return storageManager.init(env.localStoragePath) | ||
return env.init(options) | ||
.then(() => { | ||
return storageManager.init(env.localStoragePath) | ||
}) | ||
.then(() => { | ||
let app = express(); | ||
@@ -35,3 +36,7 @@ app.use((req, res, next) => { | ||
}); | ||
app.use(bodyParser.raw()); | ||
app.use(bodyParser.raw({ | ||
inflate: true, | ||
limit: '64000kb', // Maximum limit of size as per spec. | ||
type: '*/*' | ||
})); | ||
app.use(express.static(env.localStoragePath)); | ||
@@ -38,0 +43,0 @@ require('./routes/AccountRoute')(app); |
'use strict'; | ||
exports.emulatedStorageAccountName = 'devstoreaccount1'; | ||
const path = require('path'), | ||
BbPromise = require('bluebird'), | ||
fs = BbPromise.promisifyAll(require("fs-extra")); | ||
exports.localStoragePath = './'; | ||
let initialized = false; | ||
exports.port = 10000; | ||
class Environment { | ||
constructor() { | ||
} | ||
exports.storageUrl = (port, container, blob) => { | ||
return `http://localhost:${port}/${container}/${blob}`; | ||
} | ||
init(options) { | ||
if (initialized) { | ||
return; | ||
} | ||
initialized = true; | ||
this.azuriteRootPath = options.l || options.location || './'; | ||
this.dbName = '__azurite_db__.json'; | ||
this.localStoragePath = path.join(this.azuriteRootPath, '__blobstorage__'); | ||
this.commitsPath = path.join(this.azuriteRootPath, '__commits__'); | ||
this.azuriteDBPath = path.join(this.azuriteRootPath, this.dbName); | ||
this.emulatedStorageAccountName = 'devstoreaccount1'; | ||
this.port = options.p || options.port || 10000; | ||
return fs.mkdirsAsync(this.localStoragePath) | ||
.then(() => { | ||
return fs.mkdirsAsync(this.commitsPath); | ||
}) | ||
} | ||
storageUrl(port, container, blob) { | ||
return `http://localhost:${port}/${container}/${blob}`; | ||
} | ||
} | ||
module.exports = new Environment(); |
@@ -12,3 +12,4 @@ 'use strict'; | ||
contentMD5, | ||
cacheControl) { | ||
cacheControl, | ||
committed) { | ||
super(etag, lastModified); | ||
@@ -20,2 +21,6 @@ if (contentType) this['Content-Type'] = contentType; | ||
if (cacheControl) this['Cache-Control'] = cacheControl; | ||
// Internal flag to determine whether a blob has been committed. | ||
// This is only needed for "PUT Block" and "PUT Block List" operations. | ||
// In case of "PUT Blob" operations it is set to true per default. | ||
this.committed = (committed) ? committed : false; | ||
} | ||
@@ -22,0 +27,0 @@ } |
'use strict'; | ||
const env = require('./../env'), | ||
createBlockBlobHandler = require('./../api/CreateBlockBlob'), | ||
deleteBlobHandler = require('./../api/DeleteBlob'), | ||
getBlobHandler = require('./../api/GetBlob'); | ||
createBlockBlobHandler = require('./../api/CreateBlockBlob'), | ||
deleteBlobHandler = require('./../api/DeleteBlob'), | ||
getBlobHandler = require('./../api/GetBlob'), | ||
putBlockHandler = require('./../api/PutBlock'); | ||
@@ -22,3 +23,7 @@ /* | ||
const blobType = req.headers['x-ms-blob-type']; | ||
if (blobType === 'BlockBlob') { | ||
// PUT Block | ||
if (req.query.comp === 'block') { | ||
putBlockHandler.process(req, res, req.params.container, req.params.blob, req.query.blockid); | ||
// PUT Blob | ||
} else if (blobType === 'BlockBlob') { | ||
createBlockBlobHandler.process(req, res, req.params.container, req.params.blob); | ||
@@ -25,0 +30,0 @@ } else { |
@@ -8,5 +8,7 @@ 'use strict'; | ||
fs = BbPromise.promisifyAll(require("fs-extra")), | ||
md5 = require('md5'); | ||
md5 = require('md5'), | ||
BlobHttpProperties = require('./model/BlobHttpProperties'); | ||
const CONTAINERS_COL_NAME = 'Containers'; | ||
const CONTAINERS_COL_NAME = 'Containers', | ||
COMMITS = 'Commits'; | ||
@@ -19,7 +21,6 @@ class StorageManager { | ||
init(localStoragePath) { | ||
this.dbPath = path.join(localStoragePath, this.dbName); | ||
this.db = BbPromise.promisifyAll(new Loki(this.dbPath, { autosave: true, autosaveInterval: 5000 })); | ||
return fs.statAsync(this.dbPath) | ||
this.db = BbPromise.promisifyAll(new Loki(env.azuriteDBPath, { autosave: true, autosaveInterval: 5000 })); | ||
return fs.statAsync(env.azuriteDBPath) | ||
.then((stat) => { | ||
return this.db.loadDatabaseAsync(this.dbName); | ||
return this.db.loadDatabaseAsync(env.dbName); | ||
}) | ||
@@ -36,2 +37,3 @@ .then((data) => { | ||
this.db.addCollection(CONTAINERS_COL_NAME); | ||
this.db.addCollection(COMMITS); | ||
return this.db.saveDatabaseAsync(); | ||
@@ -80,3 +82,3 @@ } | ||
createBlockBlob(container, blobName, body, httpProps, metaProps, content) { | ||
createBlockBlob(container, blobName, body, httpProps, metaProps) { | ||
let containerPath = path.join(env.localStoragePath, container); | ||
@@ -168,10 +170,10 @@ let blobPath = path.join(containerPath, blobName); | ||
let blobs = coll.chain() | ||
.find({ 'name': { '$contains': options.prefix }}) | ||
.find({ 'name': { '$contains': options.prefix } }) | ||
.simplesort('name') | ||
.limit(options.maxresults); | ||
if (options.marker) { | ||
let offset = parseInt(options.marker); | ||
offset *= (options.maxresults || 1000) ; | ||
blobs.offset(offset); | ||
} | ||
if (options.marker) { | ||
let offset = parseInt(options.marker); | ||
offset *= (options.maxresults || 1000); | ||
blobs.offset(offset); | ||
} | ||
const result = blobs.data(); | ||
@@ -181,4 +183,71 @@ return result; | ||
} | ||
putBlock(containerName, blobName, body, options) { | ||
const response = {}; | ||
const blobPath = path.join(env.localStoragePath, containerName, blobName); | ||
// Make sure that the parent blob exists on storage. | ||
return fs.ensureFileAsync(blobPath) | ||
.then(() => { | ||
let coll = this.db.getCollection(containerName); | ||
if (!coll) { | ||
coll = this.db.addCollection(containerName); | ||
} | ||
const blobResult = coll.chain() | ||
.find({ 'name': { '$eq': blobName } }) | ||
.data(); | ||
// We only create the blob in DB if it does not already exists. | ||
if (blobResult.length === 0) { | ||
const httpProps = new BlobHttpProperties(); | ||
httpProps.committed = false; | ||
coll.insert({ | ||
name: blobName, | ||
http_props: httpProps | ||
}); | ||
} | ||
// Checking MD5 in case 'Content-MD5' header was set. | ||
const sourceMD5 = options.httpProps['Content-MD5']; | ||
const targetMD5 = md5(body); | ||
response['Content-MD5'] = targetMD5; | ||
if (sourceMD5) { | ||
if (targetMD5 !== sourceMD5) { | ||
const err = new Error('MD5 hash corrupted.'); | ||
err.name = 'md5'; | ||
throw err; | ||
} | ||
} | ||
}) | ||
.then(() => { | ||
// Writing block to disk. | ||
const blockPath = path.join(env.commitsPath, options.fileName); | ||
return fs.outputFileAsync(blockPath, body, { encoding: options.httpProps['Content-Encoding'] }); | ||
}) | ||
.then(() => { | ||
// Storing block information in DB. | ||
const coll = this.db.getCollection(COMMITS); | ||
const blobResult = coll.chain() | ||
.find({ 'name': { '$eq': options.fileName } }) | ||
.data(); | ||
if (blobResult.length === 0) { | ||
const newBlob = coll.insert({ | ||
name: options.fileName, | ||
parent: options.parent, | ||
http_props: options.httpProps | ||
}); | ||
response.ETag = newBlob.meta.revision; | ||
response.lastModified = options.httpProps.lastModified; | ||
} else { | ||
const updateBlob = blobResult[0]; | ||
updateBlob.http_props = options.httpProps; | ||
coll.update(updateBlob); | ||
response.ETag = updateBlob.meta.revision; | ||
response.lastModified = options.httpProps.lastModified; | ||
} | ||
return response; | ||
}); | ||
} | ||
} | ||
module.exports = new StorageManager; |
{ | ||
"name": "azurite", | ||
"version": "0.4.2", | ||
"version": "0.4.3", | ||
"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": { |
@@ -105,3 +105,3 @@ # Azurite | ||
## Put Block | ||
## Put Block [DONE] | ||
Block blobs only | ||
@@ -108,0 +108,0 @@ Creates a new block to be committed as part of a block blob. |
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
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
45853
25
947
3