UNPKG

azurite

Version:

A lightweight server clone of Azure Blob Storage that simulates most of the commands supported by it with minimal dependencies.

92 lines (84 loc) 3.38 kB
'use strict'; const storageManager = require('./../StorageManager'), env = require('./../env'), request = require('request'), path = require('path'); class GetBlob { constructor() { } process(req, res, container, blob) { const range = req.headers['x-ms-range'] || req.headers['range'] || undefined; let x_ms_range_get_content_md5 = req.headers['x-ms-range-get-content-md5']; // If this header is specified without the Range header, // the service returns status code 400 (Bad Request). if (x_ms_range_get_content_md5 && req.headers['range'] === undefined) { res.status(400).send(); return; } // If this header is set to true _and_ the range exceeds 4 MB in size, // the service returns status code 400 (Bad Request). if (x_ms_range_get_content_md5 && this._isRangeExceeded(range)) { res.status(400).send(); return; } storageManager.getBlob(container, blob) .then((result) => { const l = path.join(container, blob); const body = []; request(this._addRequestHeader(env.storageUrl(env.port, container, blob), range)) .on('response', (staticResponse) => { this._addResponseHeader(res, result, result.httpProps, result.metaProps); if (range) { res.writeHead(206); } else { res.writeHead(200); } }) .pipe(res); }) .catch((e) => { if (e.code === 'ENOENT') { res.status(404).send(); } else { res.status(500).send(); throw e; } }); } /* * Checks whether the range is bigger than 4MB (which is not allowed when * x-ms-range-get-content-md5 is set to true ) * If there is invalid data in that string, function returns false * since boolean expression will contain at least one 'NaN'' in any invalid case. */ _isRangeExceeded(range) { const pair = range.split('=')[1].split('-'); const startByte = parseInt(pair[0]); const endByte = parseInt(pair[1]); return endByte - startByte > 4194304; } _addResponseHeader(res, result, httpProps, metaProps) { const header = {}; Object.keys(metaProps).forEach((key) => { header[key] = metaProps[key]; }); header.ETag = result.ETag; header['Content-Encoding'] = httpProps['Content-Encoding']; header['Content-Type'] = httpProps['Content-Type']; header['x-ms-version'] = '2013-08-15'; header['Last-Modified'] = httpProps.lastModified; header['Content-MD5'] = httpProps.ContentMD5; header['Accept-Ranges'] = 'bytes'; res.set(header); } _addRequestHeader(url, range) { const request = {}; request.headers = {}; request.url = url; if (range) { request.headers.Range = range } return request; } } module.exports = new GetBlob();