Skip to content

Commit

Permalink
option not to cache third party files
Browse files Browse the repository at this point in the history
ref #85
  • Loading branch information
rlidwka committed Aug 8, 2014
1 parent 060dcb4 commit a8dc1b2
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 43 deletions.
111 changes: 88 additions & 23 deletions lib/local-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ Storage.prototype._internal_error = function(err, file, message) {
}

Storage.prototype.add_package = function(name, metadata, callback) {
this.storage(name).create_json(info_file, get_boilerplate(name), function(err) {
var storage = this.storage(name)
if (!storage) return callback(new UError({
status: 404,
message: 'this package cannot be added'
}))
storage.create_json(info_file, get_boilerplate(name), function(err) {
if (err && err.code === 'EEXISTS') {
return callback(new UError({
status: 409,
Expand All @@ -60,7 +65,13 @@ Storage.prototype.add_package = function(name, metadata, callback) {
Storage.prototype.remove_package = function(name, callback) {
var self = this
self.logger.info({name: name}, 'unpublishing @{name} (all)')
self.storage(name).read_json(info_file, function(err, data) {

var storage = self.storage(name)
if (!storage) return callback(new UError({
status: 404,
message: 'no such package available',
}))
storage.read_json(info_file, function(err, data) {
if (err) {
if (err.code === 'ENOENT') {
return callback(new UError({
Expand All @@ -73,7 +84,7 @@ Storage.prototype.remove_package = function(name, callback) {
}
self._normalize_package(data)

self.storage(name).unlink(info_file, function(err) {
storage.unlink(info_file, function(err) {
if (err) return callback(err)

var files = Object.keys(data._attachments)
Expand All @@ -82,14 +93,14 @@ Storage.prototype.remove_package = function(name, callback) {
if (files.length === 0) return cb()

var file = files.shift()
self.storage(name).unlink(file, function() {
storage.unlink(file, function() {
unlinkNext(cb)
})
}

unlinkNext(function() {
// try to unlink the directory, but ignore errors because it can fail
self.storage(name).rmdir('.', function(err) {
storage.rmdir('.', function(err) {
callback(err)
})
})
Expand All @@ -99,7 +110,13 @@ Storage.prototype.remove_package = function(name, callback) {

Storage.prototype._read_create_package = function(name, callback) {
var self = this
self.storage(name).read_json(info_file, function(err, data) {
var storage = self.storage(name)
if (!storage) {
var data = get_boilerplate(name)
self._normalize_package(data)
return callback(null, data)
}
storage.read_json(info_file, function(err, data) {
// TODO: race condition
if (err) {
if (err.code === 'ENOENT') {
Expand Down Expand Up @@ -293,7 +310,8 @@ Storage.prototype.remove_tarball = function(name, filename, revision, callback)
}
}, function(err) {
if (err) return callback(err)
self.storage(name).unlink(filename, callback)
var storage = self.storage(name)
if (storage) storage.unlink(filename, callback)
})
}

Expand All @@ -305,6 +323,8 @@ Storage.prototype.add_tarball = function(name, filename) {
, length = 0
, shasum = crypto.createHash('sha1')

stream.abort = stream.done = function(){}

stream._transform = function(data) {
shasum.update(data)
length += data.length
Expand All @@ -313,13 +333,27 @@ Storage.prototype.add_tarball = function(name, filename) {

var self = this
if (name === info_file || name === '__proto__') {
stream.emit('error', new UError({
status: 403,
message: 'can\'t use this filename'
}))
process.nextTick(function() {
stream.emit('error', new UError({
status: 403,
message: 'can\'t use this filename'
}))
})
return stream
}

var wstream = this.storage(name).write_stream(filename)
var storage = self.storage(name)
if (!storage) {
process.nextTick(function() {
stream.emit('error', new UError({
status: 404,
message: 'can\'t upload this package'
}))
})
return stream
}

var wstream = storage.write_stream(filename)

wstream.on('error', function(err) {
if (err.code === 'EEXISTS') {
Expand Down Expand Up @@ -380,13 +414,25 @@ Storage.prototype.add_tarball = function(name, filename) {

Storage.prototype.get_tarball = function(name, filename, callback) {
assert(utils.validate_name(filename))
var self = this

var stream = new mystreams.ReadTarballStream()
stream.abort = function() {
rstream.abort()
if (rstream) rstream.abort()
}

var storage = self.storage(name)
if (!storage) {
process.nextTick(function() {
stream.emit('error', new UError({
status: 404,
message: 'no such file available',
}))
})
return stream
}

var rstream = this.storage(name).read_stream(filename)
var rstream = storage.read_stream(filename)
rstream.on('error', function(err) {
if (err && err.code === 'ENOENT') {
stream.emit('error', new UError({
Expand All @@ -412,8 +458,13 @@ Storage.prototype.get_package = function(name, options, callback) {
if (typeof(options) === 'function') callback = options, options = {}

var self = this
var storage = self.storage(name)
if (!storage) return callback(new UError({
status: 404,
message: 'no such package available'
}))

self.storage(name).read_json(info_file, function(err, result) {
storage.read_json(info_file, function(err, result) {
if (err) {
if (err.code === 'ENOENT') {
return callback(new UError({
Expand All @@ -433,13 +484,17 @@ Storage.prototype.get_recent_packages = function(startkey, callback) {
var self = this
var i = 0
var list = []
fs.readdir(self.storage('').path, function(err, files) {

var storage = self.storage('')
if (!storage) return callback(null, [])

fs.readdir(storage.path, function(err, files) {
if (err) return callback(null, [])

var filesL = files.length

files.forEach(function(file) {
fs.stat(self.storage(file).path, function(err, stats) {
fs.stat(storage.path, function(err, stats) {
if (err) return callback(err)
if (stats.mtime > startkey) {
list.push({
Expand Down Expand Up @@ -474,7 +529,12 @@ Storage.prototype.get_recent_packages = function(startkey, callback) {
//
Storage.prototype.update_package = function(name, updateFn, _callback) {
var self = this
self.storage(name).lock_and_read_json(info_file, function(err, fd, json) {
var storage = self.storage(name)
if (!storage) return callback(new UError({
status: 404,
message: 'no such package available',
}))
storage.lock_and_read_json(info_file, function(err, fd, json) {
function callback() {
var _args = arguments
if (fd) {
Expand Down Expand Up @@ -526,16 +586,21 @@ Storage.prototype._write_package = function(name, json, callback) {
var rev = json._rev.split('-')
json._rev = ((+rev[0] || 0) + 1) + '-' + crypto.pseudoRandomBytes(8).toString('hex')

this.storage(name).write_json(info_file, json, callback)
var storage = this.storage(name)
if (!storage) return callback()
storage.write_json(info_file, json, callback)
}

Storage.prototype.storage = function(package) {
var path = this.config.get_package_setting(package, 'storage')
if (path == null) path = this.config.storage
if (path == null || path === false) {
this.logger.debug({name: package}, 'this package has no storage defined: @{name}')
return null
}
return new Path_Wrapper(
Path.join(
Path.resolve(
Path.dirname(this.config.self_path),
this.config.get_package_setting(package, 'storage') || this.config.storage
),
Path.resolve(Path.dirname(this.config.self_path), path),
package
)
)
Expand Down
24 changes: 15 additions & 9 deletions lib/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,26 +250,32 @@ Storage.prototype.get_tarball = function(name, filename) {
}

var savestream = self.local.add_tarball(name, filename)
savestream.on('error', function(err) {
savestream.abort()
stream.emit('error', err)
})
savestream.on('open', function() {
function on_open() {
var rstream2 = uplink.get_url(file.url)
rstream2.on('error', function(err) {
savestream.abort()
if (savestream) savestream.abort()
savestream = null
stream.emit('error', err)
})
rstream2.on('end', function() {
savestream.done()
if (savestream) savestream.done()
})

rstream2.on('content-length', function(v) {
stream.emit('content-length', v)
savestream.emit('content-length', v)
if (savestream) savestream.emit('content-length', v)
})
rstream2.pipe(stream)
rstream2.pipe(savestream)
if (savestream) rstream2.pipe(savestream)
}

savestream.on('open', function() {
on_open()
})
savestream.on('error', function() {
if (savestream) savestream.abort()
savestream = null
on_open()
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ keywords:
- server

scripts:
test: mocha ./test/functional ./test/unit
test: mocha -R dot ./test/functional ./test/unit
lint: eslint -c ./.eslint.yaml ./lib
#prepublish: js-yaml package.yaml > package.json

Expand Down
6 changes: 6 additions & 0 deletions test/functional/config-1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ packages:
allow_publish: all
proxy_access: express

'test-nullstorage*':
allow_access: all
allow_publish: all
proxy_access: server2
storage: false

'baduplink':
allow_access: all
allow_publish: all
Expand Down
4 changes: 4 additions & 0 deletions test/functional/config-2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ packages:
allow_publish: test anonymous
proxy_access: server1

'test-nullstorage*':
allow_access: all
allow_publish: all

'*':
allow_access: test anonymous
allow_publish: test anonymous
Expand Down
1 change: 1 addition & 0 deletions test/functional/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe('Func', function() {
require('./incomplete')()
require('./mirror')()
require('./newnpmreg')()
require('./nullstorage')()
require('./race')()
require('./racycrash')()
require('./security')()
Expand Down
78 changes: 78 additions & 0 deletions test/functional/nullstorage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
require('./lib/startup')

var assert = require('assert')
, async = require('async')
, crypto = require('crypto')

function readfile(x) {
return require('fs').readFileSync(__dirname + '/' + x)
}

module.exports = function() {
var server = process.server
var server2 = process.server2

it('trying to fetch non-existent package / null storage', function(cb) {
server.get_package('test-nullstorage-nonexist', function(res, body) {
assert.equal(res.statusCode, 404)
assert(~body.error.indexOf('no such package'))
cb()
})
})

describe('test-nullstorage on server2', function() {
before(server2.add_package.bind(server2, 'test-nullstorage2'))

it('creating new package - server2', function(){/* test for before() */})

it('downloading non-existent tarball', function(cb) {
server.get_tarball('test-nullstorage2', 'blahblah', function(res, body) {
assert.equal(res.statusCode, 404)
assert(~body.error.indexOf('no such file'))
cb()
})
})

describe('tarball', function() {
before(function(cb) {
server2.put_tarball('test-nullstorage2', 'blahblah', readfile('fixtures/binary'), function(res, body) {
assert.equal(res.statusCode, 201)
assert(body.ok)
cb()
})
})

before(function(cb) {
var pkg = require('./lib/package')('test-nullstorage2')
pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex')
server2.put_version('test-nullstorage2', '0.0.1', pkg, function(res, body) {
assert.equal(res.statusCode, 201)
assert(~body.ok.indexOf('published'))
cb()
})
})

it('uploading new tarball', function(){/* test for before() */})

it('downloading newly created tarball', function(cb) {
server.get_tarball('test-nullstorage2', 'blahblah', function(res, body) {
assert.equal(res.statusCode, 200)
assert.deepEqual(body, readfile('fixtures/binary').toString('utf8'))
cb()
})
})

it('downloading newly created package', function(cb) {
server.get_package('test-nullstorage2', function(res, body) {
assert.equal(res.statusCode, 200)
assert.equal(body.name, 'test-nullstorage2')
assert.equal(body.versions['0.0.1'].name, 'test-nullstorage2')
assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/test-nullstorage2/-/blahblah')
assert.deepEqual(body['dist-tags'], {latest: '0.0.1'})
cb()
})
})
})
})
}

10 changes: 0 additions & 10 deletions test/start.sh

This file was deleted.

0 comments on commit a8dc1b2

Please sign in to comment.