Comparing version 1.3.1 to 1.3.2
{ | ||
"name": "castor", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "An ES7 [CAS designed](https://en.wikipedia.org/wiki/Content-addressable_storage) file storage for nodejs with a simple API and robust implementation.", | ||
@@ -5,0 +5,0 @@ "main": "store.js", |
78
store.js
@@ -5,2 +5,4 @@ 'use strict'; | ||
const fs = require('fs'); | ||
const http = require('http'); | ||
const os = require('os'); | ||
const path = require('path'); | ||
@@ -14,6 +16,7 @@ const url = require('url'); | ||
const eachIteratorLimit = require('nyks/async/eachIteratorLimit'); | ||
const retryUntil = require('nyks/async/retryUntil'); | ||
const sleep = require('nyks/async/sleep'); | ||
const promisify = require('nyks/function/promisify'); | ||
const md5File = promisify(require('nyks/fs/md5File')); | ||
const guid = require('mout/random/randString'); | ||
const createWriteStream = require('nyks/fs/createWriteStream'); | ||
@@ -25,2 +28,3 @@ const rename = require('nyks/fs/rename'); | ||
const readdir = require('nyks/fs/readdir'); | ||
const debug = require('debug'); | ||
@@ -130,11 +134,43 @@ const Index = require('./index'); | ||
async isWritable(socket_name) { | ||
let server = await retryUntil(() => { | ||
const pipeDir = process.platform == 'win32' ? '\\\\?\\pipe' : os.tmpdir(); | ||
const socketPath = path.join(pipeDir, socket_name); | ||
const server = http.createServer(); | ||
server.unref(); | ||
return new Promise((resolve, reject) => { | ||
server.on('error', (err) => { | ||
if(err.code === 'EADDRINUSE') | ||
resolve(false); | ||
else | ||
reject(err); | ||
}); | ||
server.listen(socketPath, resolve.bind(null, server)); | ||
}); | ||
}, 1000 * 120, 100); | ||
return server; | ||
} | ||
async download(file_url, file_md5, allowResume) { | ||
var file_path = this.getFilePathFromMd5(file_md5); | ||
var server = await this.isWritable(`castor_${file_md5}`); | ||
if(typeof file_url == 'string') | ||
file_url = url.parse(file_url); | ||
file_url.headers = {...file_url.headers}; | ||
file_url.followRedirect = true; | ||
try { | ||
const {size} = fs.statSync(file_path); | ||
if(size == 0 && file_md5 != MD5_EMPTY_FILE) | ||
if(size == 0 && file_md5 != MD5_EMPTY_FILE) { | ||
fs.unlinkSync(file_path); | ||
else | ||
} else { | ||
await new Promise((resolve) => server.close(resolve)); | ||
return false; | ||
} | ||
} catch(err) {} | ||
@@ -144,3 +180,3 @@ | ||
var tmp_path = `${file_path}.tmp.${guid()}`; | ||
var tmp_path = `${file_path}.tmp`; | ||
var current_size = 0; | ||
@@ -152,15 +188,21 @@ var hash = crypto.createHash('md5'); | ||
try { | ||
if(typeof file_url == 'string') | ||
file_url = url.parse(file_url); | ||
if(fs.existsSync(tmp_path)) { | ||
if(allowResume) { | ||
current_size = fs.statSync(tmp_path).size; | ||
file_url.headers = {...file_url.headers}; | ||
file_url.followRedirect = true; | ||
await pipe(fs.createReadStream(tmp_path), hash); | ||
file_url.headers['Range'] = `bytes=${current_size}-`; | ||
} else { | ||
fs.unlinkSync(tmp_path); | ||
} | ||
} | ||
var attempt = 0; | ||
var res = await request(file_url); | ||
var expected_size = parseInt(res.headers['content-length']); | ||
allowResume &= !!res.headers['accept-ranges']; | ||
allowResume &= !!res.headers['accept-ranges']; | ||
do { | ||
if(!(res.statusCode >= 200 && res.statusCode < 300)) | ||
@@ -172,3 +214,2 @@ throw `Invalid status code '${res.statusCode}'`; | ||
pipe(res, hash, {end : false}).catch(() => false); | ||
@@ -185,6 +226,10 @@ | ||
let {size} = fs.statSync(tmp_path); | ||
allowResume &= size != current_size; | ||
if(size == current_size) | ||
attempt++; | ||
else | ||
attempt = 0; | ||
allowResume &= attempt < 10; | ||
current_size = size; | ||
@@ -197,4 +242,5 @@ | ||
await sleep(Math.min(attempt, 10) * 1000); | ||
res = await request(file_url); | ||
allowResume &= current_size < expected_size; | ||
@@ -217,4 +263,5 @@ } while(allowResume); | ||
throw err; | ||
} finally { | ||
await new Promise((resolve) => server.close(resolve)); | ||
} | ||
} | ||
@@ -224,3 +271,2 @@ | ||
module.exports = Store; |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
15065
284
1