2013-10-18 23:17:53 +02:00
|
|
|
var express = require('express')
|
|
|
|
, cookies = require('cookies')
|
|
|
|
, utils = require('./utils')
|
|
|
|
, Storage = require('./storage')
|
|
|
|
, Config = require('./config')
|
2014-09-10 19:55:26 +02:00
|
|
|
, Error = require('http-errors')
|
2013-10-18 23:17:53 +02:00
|
|
|
, Middleware = require('./middleware')
|
|
|
|
, Logger = require('./logger')
|
2013-11-24 18:06:01 +01:00
|
|
|
, Cats = require('./status-cats')
|
2013-10-18 23:17:53 +02:00
|
|
|
, validate_name = Middleware.validate_name
|
|
|
|
, media = Middleware.media
|
|
|
|
, expect_json = Middleware.expect_json
|
2014-05-07 00:40:21 +02:00
|
|
|
, fs = require('fs')
|
2014-09-02 01:09:08 +02:00
|
|
|
, Auth = require('./auth')
|
2013-05-31 08:26:11 +02:00
|
|
|
|
2014-02-01 09:08:48 +01:00
|
|
|
function match(regexp) {
|
|
|
|
return function(req, res, next, value, name) {
|
|
|
|
if (regexp.exec(value)) {
|
|
|
|
next()
|
|
|
|
} else {
|
|
|
|
next('route')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-08 03:16:28 +02:00
|
|
|
module.exports = function(config_hash) {
|
2013-10-26 14:18:36 +02:00
|
|
|
var config = new Config(config_hash)
|
2014-09-02 01:09:08 +02:00
|
|
|
, storage = new Storage(config)
|
|
|
|
, auth = new Auth(config)
|
2014-05-08 18:13:39 +02:00
|
|
|
|
2013-06-08 03:16:28 +02:00
|
|
|
var can = function(action) {
|
2013-06-14 09:10:50 +02:00
|
|
|
return function(req, res, next) {
|
2014-09-02 01:09:08 +02:00
|
|
|
if (config['allow_'+action](req.params.package, req.remote_user)) {
|
2013-10-26 14:18:36 +02:00
|
|
|
next()
|
2013-06-08 03:16:28 +02:00
|
|
|
} else {
|
2014-09-02 01:09:08 +02:00
|
|
|
if (!req.remote_user.name) {
|
|
|
|
if (req.remote_user.error) {
|
|
|
|
var message = "can't "+action+' restricted package, ' + req.remote_user.error
|
2013-12-15 21:38:16 +01:00
|
|
|
} else {
|
2014-07-22 21:31:01 +02:00
|
|
|
var message = "can't "+action+" restricted package without auth, did you forget 'npm set always-auth true'?"
|
2013-12-15 21:38:16 +01:00
|
|
|
}
|
2014-09-10 19:55:26 +02:00
|
|
|
next(Error[403](message))
|
2013-10-05 16:49:08 +02:00
|
|
|
} else {
|
2014-09-10 19:55:26 +02:00
|
|
|
next(Error[403]('user ' + req.remote_user.name
|
|
|
|
+ ' not allowed to ' + action + ' it'))
|
2013-10-05 16:49:08 +02:00
|
|
|
}
|
2013-06-08 03:16:28 +02:00
|
|
|
}
|
2013-10-26 14:18:36 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-01 00:57:28 +02:00
|
|
|
|
2013-10-26 14:18:36 +02:00
|
|
|
var app = express()
|
2013-10-11 11:49:00 +02:00
|
|
|
|
2013-12-12 00:19:40 +01:00
|
|
|
// run in production mode by default, just in case
|
|
|
|
// it shouldn't make any difference anyway
|
|
|
|
app.set('env', process.env.NODE_ENV || 'production')
|
|
|
|
|
2013-12-05 13:27:23 +01:00
|
|
|
function error_reporting_middleware(req, res, next) {
|
|
|
|
res.report_error = res.report_error || function(err) {
|
2013-10-11 11:49:00 +02:00
|
|
|
if (err.status && err.status >= 400 && err.status < 600) {
|
2014-08-08 04:17:05 +02:00
|
|
|
if (!res.headersSent) {
|
2013-10-26 14:18:36 +02:00
|
|
|
res.status(err.status)
|
2014-07-22 21:31:01 +02:00
|
|
|
res.send({error: err.message || 'unknown error'})
|
2013-10-11 11:49:00 +02:00
|
|
|
}
|
|
|
|
} else {
|
2013-10-18 23:17:53 +02:00
|
|
|
Logger.logger.error({err: err}, 'unexpected error: @{!err.message}\n@{err.stack}')
|
2013-12-05 13:31:21 +01:00
|
|
|
if (!res.status || !res.send) {
|
|
|
|
Logger.logger.error('this is an error in express.js, please report this')
|
|
|
|
res.destroy()
|
2014-08-08 04:17:05 +02:00
|
|
|
} else if (!res.headersSent) {
|
2013-10-26 14:18:36 +02:00
|
|
|
res.status(500)
|
|
|
|
res.send({error: 'internal server error'})
|
2014-06-20 06:12:37 +02:00
|
|
|
} else {
|
|
|
|
// socket should be already closed
|
2013-10-11 11:49:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-10-26 14:18:36 +02:00
|
|
|
next()
|
2013-12-05 13:27:23 +01:00
|
|
|
}
|
2013-10-11 11:49:00 +02:00
|
|
|
|
2013-12-05 13:27:23 +01:00
|
|
|
app.use(error_reporting_middleware)
|
2013-10-26 14:18:36 +02:00
|
|
|
app.use(Middleware.log_and_etagify)
|
2013-11-24 18:06:01 +01:00
|
|
|
app.use(function(req, res, next) {
|
2013-12-10 11:12:34 +01:00
|
|
|
res.setHeader('X-Powered-By', config.user_agent)
|
2013-11-24 18:06:01 +01:00
|
|
|
next()
|
|
|
|
})
|
|
|
|
app.use(Cats.middleware)
|
2014-09-02 01:09:08 +02:00
|
|
|
app.use(auth.middleware())
|
2014-01-18 20:04:12 +01:00
|
|
|
app.use(express.json({strict: false, limit: config.max_body_size || '10mb'}))
|
2013-10-26 14:18:36 +02:00
|
|
|
app.use(express.compress())
|
2013-12-09 04:59:31 +01:00
|
|
|
app.use(Middleware.anti_loop(config))
|
2013-06-20 19:10:33 +02:00
|
|
|
|
2014-02-01 09:08:48 +01:00
|
|
|
// validate all of these params as a package name
|
|
|
|
// this might be too harsh, so ask if it causes trouble
|
2013-10-26 14:18:36 +02:00
|
|
|
app.param('package', validate_name)
|
|
|
|
app.param('filename', validate_name)
|
2014-02-01 09:08:48 +01:00
|
|
|
app.param('tag', validate_name)
|
|
|
|
app.param('version', validate_name)
|
|
|
|
app.param('revision', validate_name)
|
|
|
|
|
|
|
|
// these can't be safely put into express url for some reason
|
|
|
|
app.param('_rev', match(/^-rev$/))
|
|
|
|
app.param('org_couchdb_user', match(/^org\.couchdb\.user:/))
|
2014-06-24 04:57:54 +02:00
|
|
|
app.param('anything', match(/.*/))
|
2013-05-31 08:26:11 +02:00
|
|
|
|
2014-05-12 17:43:18 +02:00
|
|
|
/* app.get('/-/all', function(req, res) {
|
2013-10-26 14:18:36 +02:00
|
|
|
var https = require('https')
|
|
|
|
var JSONStream = require('JSONStream')
|
2013-06-08 03:16:28 +02:00
|
|
|
var request = require('request')({
|
|
|
|
url: 'https://registry.npmjs.org/-/all',
|
|
|
|
})
|
|
|
|
.pipe(JSONStream.parse('*'))
|
|
|
|
.on('data', function(d) {
|
2013-10-26 14:18:36 +02:00
|
|
|
console.log(d)
|
|
|
|
})
|
|
|
|
})*/
|
2013-06-08 03:16:28 +02:00
|
|
|
|
2013-06-13 16:21:14 +02:00
|
|
|
// TODO: anonymous user?
|
|
|
|
app.get('/:package/:version?', can('access'), function(req, res, next) {
|
2013-12-09 04:58:25 +01:00
|
|
|
storage.get_package(req.params.package, {req: req}, function(err, info) {
|
2013-10-26 14:18:36 +02:00
|
|
|
if (err) return next(err)
|
|
|
|
info = utils.filter_tarball_urls(info, req, config)
|
2013-06-13 16:21:14 +02:00
|
|
|
|
2013-10-26 14:18:36 +02:00
|
|
|
var version = req.params.version
|
2014-01-18 19:57:44 +01:00
|
|
|
, t
|
2013-10-02 20:26:20 +02:00
|
|
|
if (!version) {
|
2013-10-26 14:18:36 +02:00
|
|
|
return res.send(info)
|
2013-10-02 20:26:20 +02:00
|
|
|
}
|
|
|
|
|
2014-01-18 19:57:44 +01:00
|
|
|
if ((t = utils.get_version(info, version)) != null) {
|
|
|
|
return res.send(t)
|
2013-10-02 20:26:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (info['dist-tags'] != null) {
|
|
|
|
if (info['dist-tags'][version] != null) {
|
2013-10-26 14:18:36 +02:00
|
|
|
version = info['dist-tags'][version]
|
2014-01-18 19:57:44 +01:00
|
|
|
if ((t = utils.get_version(info, version)) != null) {
|
|
|
|
return res.send(t)
|
2013-10-02 20:26:20 +02:00
|
|
|
}
|
2013-06-13 16:21:14 +02:00
|
|
|
}
|
|
|
|
}
|
2013-10-02 20:26:20 +02:00
|
|
|
|
2014-09-10 19:55:26 +02:00
|
|
|
return next(Error[404]('version not found: ' + req.params.version))
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
|
|
|
})
|
2013-06-01 00:57:28 +02:00
|
|
|
|
2013-06-08 03:16:28 +02:00
|
|
|
app.get('/:package/-/:filename', can('access'), function(req, res, next) {
|
2013-10-26 14:18:36 +02:00
|
|
|
var stream = storage.get_tarball(req.params.package, req.params.filename)
|
2014-03-07 20:39:20 +01:00
|
|
|
stream.on('content-length', function(v) {
|
|
|
|
res.header('Content-Length', v)
|
|
|
|
})
|
2013-06-20 15:07:34 +02:00
|
|
|
stream.on('error', function(err) {
|
2013-10-26 14:18:36 +02:00
|
|
|
return res.report_error(err)
|
|
|
|
})
|
2014-03-07 20:39:20 +01:00
|
|
|
res.header('Content-Type', 'application/octet-stream')
|
2013-10-26 14:18:36 +02:00
|
|
|
stream.pipe(res)
|
|
|
|
})
|
|
|
|
|
2014-04-12 19:20:26 +02:00
|
|
|
// searching packages
|
2014-06-24 04:57:54 +02:00
|
|
|
app.get('/-/all/:anything?', function(req, res, next) {
|
2014-06-22 16:12:13 +02:00
|
|
|
storage.search(req.param.startkey || 0, {req: req}, function(err, result) {
|
2014-04-12 19:20:26 +02:00
|
|
|
if (err) return next(err)
|
2014-06-22 16:34:51 +02:00
|
|
|
for (var pkg in result) {
|
2014-09-02 01:09:08 +02:00
|
|
|
if (!config.allow_access(pkg, req.remote_user)) {
|
2014-06-22 16:34:51 +02:00
|
|
|
delete result[pkg]
|
|
|
|
}
|
|
|
|
}
|
2014-04-12 19:20:26 +02:00
|
|
|
return res.send(result)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2013-05-31 08:26:11 +02:00
|
|
|
//app.get('/*', function(req, res) {
|
2014-05-12 17:43:18 +02:00
|
|
|
// proxy.request(req, res)
|
2013-10-26 14:18:36 +02:00
|
|
|
//})
|
|
|
|
|
2013-05-31 08:26:11 +02:00
|
|
|
// placeholder 'cause npm require to be authenticated to publish
|
|
|
|
// we do not do any real authentication yet
|
|
|
|
app.post('/_session', cookies.express(), function(req, res) {
|
|
|
|
res.cookies.set('AuthSession', String(Math.random()), {
|
|
|
|
// npmjs.org sets 10h expire
|
|
|
|
expires: new Date(Date.now() + 10*60*60*1000)
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
2014-02-23 18:20:50 +01:00
|
|
|
res.send({'ok':true,'name':'somebody','roles':[]})
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
2013-06-08 03:16:28 +02:00
|
|
|
|
2014-02-01 09:08:48 +01:00
|
|
|
app.get('/-/user/:org_couchdb_user', function(req, res, next) {
|
2013-10-26 14:18:36 +02:00
|
|
|
res.status(200)
|
2013-06-08 03:16:28 +02:00
|
|
|
return res.send({
|
2014-09-02 01:09:08 +02:00
|
|
|
ok: 'you are authenticated as "' + req.remote_user.name + '"',
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
|
|
|
})
|
2013-06-08 03:16:28 +02:00
|
|
|
|
2014-07-22 23:44:06 +02:00
|
|
|
app.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function(req, res, next) {
|
2014-09-02 01:09:08 +02:00
|
|
|
if (req.remote_user.name != null) {
|
2014-07-22 23:44:06 +02:00
|
|
|
res.status(201)
|
2014-07-21 15:02:02 +02:00
|
|
|
return res.send({
|
2014-09-02 01:09:08 +02:00
|
|
|
ok: 'you are authenticated as "' + req.remote_user.name + '"',
|
2014-07-21 15:02:02 +02:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
if (typeof(req.body.name) !== 'string' || typeof(req.body.password) !== 'string') {
|
2014-09-10 19:55:26 +02:00
|
|
|
return next(Error[400]('user/password is not found in request (npm issue?)'))
|
2014-07-21 15:02:02 +02:00
|
|
|
}
|
2014-09-02 01:09:08 +02:00
|
|
|
auth.add_user(req.body.name, req.body.password, function(err) {
|
2014-07-22 23:44:06 +02:00
|
|
|
if (err) {
|
|
|
|
if (err.status < 500 && err.message === 'this user already exists') {
|
|
|
|
// with npm registering is the same as logging in
|
|
|
|
// so we replace message in case of conflict
|
2014-09-10 19:55:26 +02:00
|
|
|
return next(Error[409]('bad username/password, access denied'))
|
2014-07-22 23:44:06 +02:00
|
|
|
}
|
|
|
|
return next(err)
|
|
|
|
}
|
2014-07-21 15:02:02 +02:00
|
|
|
|
|
|
|
res.status(201)
|
|
|
|
return res.send({
|
2014-07-22 21:48:15 +02:00
|
|
|
ok: 'user "' + req.body.name + '" created',
|
2014-07-21 15:02:02 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
2013-06-14 09:56:02 +02:00
|
|
|
|
2013-12-27 14:06:30 +01:00
|
|
|
// tagging a package
|
|
|
|
app.put('/:package/:tag', can('publish'), media('application/json'), function(req, res, next) {
|
|
|
|
if (typeof(req.body) !== 'string') return next('route')
|
|
|
|
|
2014-04-13 04:04:48 +02:00
|
|
|
var tags = {}
|
|
|
|
tags[req.params.tag] = req.body
|
|
|
|
storage.add_tags(req.params.package, tags, function(err) {
|
2013-12-27 14:06:30 +01:00
|
|
|
if (err) return next(err)
|
|
|
|
res.status(201)
|
|
|
|
return res.send({
|
|
|
|
ok: 'package tagged'
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2013-05-31 08:26:11 +02:00
|
|
|
// publishing a package
|
2013-10-11 07:32:12 +02:00
|
|
|
app.put('/:package/:_rev?/:revision?', can('publish'), media('application/json'), expect_json, function(req, res, next) {
|
2013-10-23 08:15:17 +02:00
|
|
|
var name = req.params.package
|
2013-10-02 20:01:18 +02:00
|
|
|
|
2013-10-22 09:29:57 +02:00
|
|
|
if (Object.keys(req.body).length == 1 && utils.is_object(req.body.users)) {
|
2014-09-10 19:55:26 +02:00
|
|
|
// 501 status is more meaningful, but npm doesn't show error message for 5xx
|
|
|
|
return next(Error[404]('npm star|unstar calls are not implemented'))
|
2013-10-02 20:01:18 +02:00
|
|
|
}
|
|
|
|
|
2013-06-01 00:57:28 +02:00
|
|
|
try {
|
2013-10-23 08:15:17 +02:00
|
|
|
var metadata = utils.validate_metadata(req.body, name)
|
2013-06-01 00:57:28 +02:00
|
|
|
} catch(err) {
|
2014-09-10 19:55:26 +02:00
|
|
|
return next(Error[422]('bad incoming package data'))
|
2013-05-31 08:26:11 +02:00
|
|
|
}
|
|
|
|
|
2013-10-11 07:32:12 +02:00
|
|
|
if (req.params._rev) {
|
2013-10-23 08:15:17 +02:00
|
|
|
storage.change_package(name, metadata, req.params.revision, function(err) {
|
2013-12-29 01:53:31 +01:00
|
|
|
after_change(err, 'package changed')
|
2013-10-23 08:15:17 +02:00
|
|
|
})
|
2013-10-11 07:32:12 +02:00
|
|
|
} else {
|
|
|
|
storage.add_package(name, metadata, function(err) {
|
2013-12-29 01:53:31 +01:00
|
|
|
after_change(err, 'created new package')
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function after_change(err, ok_message) {
|
2013-12-29 01:58:48 +01:00
|
|
|
// old npm behaviour
|
|
|
|
if (metadata._attachments == null) {
|
2013-10-23 08:15:17 +02:00
|
|
|
if (err) return next(err)
|
2013-10-26 14:18:36 +02:00
|
|
|
res.status(201)
|
2013-10-11 07:32:12 +02:00
|
|
|
return res.send({
|
2013-12-29 01:53:31 +01:00
|
|
|
ok: ok_message
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// npm-registry-client 0.3+ embeds tarball into the json upload
|
|
|
|
// https://github.com/isaacs/npm-registry-client/commit/e9fbeb8b67f249394f735c74ef11fe4720d46ca0
|
|
|
|
// issue #31, dealing with it here:
|
|
|
|
|
|
|
|
if (typeof(metadata._attachments) != 'object'
|
|
|
|
|| Object.keys(metadata._attachments).length != 1
|
|
|
|
|| typeof(metadata.versions) != 'object'
|
|
|
|
|| Object.keys(metadata.versions).length != 1) {
|
|
|
|
|
|
|
|
// npm is doing something strange again
|
|
|
|
// if this happens in normal circumstances, report it as a bug
|
2014-09-10 19:55:26 +02:00
|
|
|
return next(Error[400]('unsupported registry call'))
|
2013-12-29 01:53:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (err && err.status != 409) return next(err)
|
|
|
|
|
|
|
|
// at this point document is either created or existed before
|
|
|
|
var t1 = Object.keys(metadata._attachments)[0]
|
|
|
|
create_tarball(t1, metadata._attachments[t1], function(err) {
|
2013-12-29 07:41:31 +01:00
|
|
|
if (err) return next(err)
|
2013-12-29 01:53:31 +01:00
|
|
|
|
|
|
|
var t2 = Object.keys(metadata.versions)[0]
|
2014-09-25 05:56:31 +02:00
|
|
|
metadata.versions[t2].readme = metadata.readme != null ? String(metadata.readme) : ''
|
2013-12-29 01:53:31 +01:00
|
|
|
create_version(t2, metadata.versions[t2], function(err) {
|
2013-12-29 07:41:31 +01:00
|
|
|
if (err) return next(err)
|
2013-12-29 01:58:48 +01:00
|
|
|
|
2014-04-13 04:04:48 +02:00
|
|
|
add_tags(metadata['dist-tags'], function(err) {
|
|
|
|
if (err) return next(err)
|
|
|
|
|
|
|
|
res.status(201)
|
|
|
|
return res.send({
|
|
|
|
ok: ok_message
|
|
|
|
})
|
2013-12-29 01:53:31 +01:00
|
|
|
})
|
2013-10-23 08:15:17 +02:00
|
|
|
})
|
|
|
|
})
|
2013-10-11 07:32:12 +02:00
|
|
|
}
|
2013-12-29 01:53:31 +01:00
|
|
|
|
|
|
|
function create_tarball(filename, data, cb) {
|
|
|
|
var stream = storage.add_tarball(name, filename)
|
|
|
|
stream.on('error', function(err) {
|
|
|
|
cb(err)
|
|
|
|
})
|
|
|
|
stream.on('success', function() {
|
|
|
|
cb()
|
|
|
|
})
|
|
|
|
|
|
|
|
// this is dumb and memory-consuming, but what choices do we have?
|
|
|
|
stream.end(new Buffer(data.data, 'base64'))
|
|
|
|
stream.done()
|
|
|
|
}
|
|
|
|
|
|
|
|
function create_version(version, data, cb) {
|
2014-03-29 03:31:34 +01:00
|
|
|
storage.add_version(name, version, data, null, cb)
|
2013-12-29 01:53:31 +01:00
|
|
|
}
|
2014-04-13 04:04:48 +02:00
|
|
|
|
|
|
|
function add_tags(tags, cb) {
|
|
|
|
storage.add_tags(name, tags, cb)
|
|
|
|
}
|
2013-10-23 08:15:17 +02:00
|
|
|
})
|
2013-05-31 08:26:11 +02:00
|
|
|
|
2013-10-06 10:27:50 +02:00
|
|
|
// unpublishing an entire package
|
|
|
|
app.delete('/:package/-rev/*', can('publish'), function(req, res, next) {
|
|
|
|
storage.remove_package(req.params.package, function(err) {
|
2013-10-26 14:18:36 +02:00
|
|
|
if (err) return next(err)
|
|
|
|
res.status(201)
|
2013-10-06 10:27:50 +02:00
|
|
|
return res.send({
|
|
|
|
ok: 'package removed'
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2013-10-06 10:27:50 +02:00
|
|
|
|
2013-10-23 08:15:17 +02:00
|
|
|
// removing a tarball
|
|
|
|
app.delete('/:package/-/:filename/-rev/:revision', can('publish'), function(req, res, next) {
|
|
|
|
storage.remove_tarball(req.params.package, req.params.filename, req.params.revision, function(err) {
|
2013-10-26 14:18:36 +02:00
|
|
|
if (err) return next(err)
|
|
|
|
res.status(201)
|
2013-10-23 08:15:17 +02:00
|
|
|
return res.send({
|
|
|
|
ok: 'tarball removed'
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2013-10-23 08:15:17 +02:00
|
|
|
|
2013-05-31 08:26:11 +02:00
|
|
|
// uploading package tarball
|
2013-06-08 03:16:28 +02:00
|
|
|
app.put('/:package/-/:filename/*', can('publish'), media('application/octet-stream'), function(req, res, next) {
|
2013-10-26 14:18:36 +02:00
|
|
|
var name = req.params.package
|
2013-06-01 00:57:28 +02:00
|
|
|
|
2013-10-26 14:18:36 +02:00
|
|
|
var stream = storage.add_tarball(name, req.params.filename)
|
|
|
|
req.pipe(stream)
|
2013-09-24 08:28:26 +02:00
|
|
|
|
|
|
|
// checking if end event came before closing
|
2013-10-26 14:18:36 +02:00
|
|
|
var complete = false
|
2013-09-24 08:28:26 +02:00
|
|
|
req.on('end', function() {
|
2013-10-26 14:18:36 +02:00
|
|
|
complete = true
|
|
|
|
stream.done()
|
|
|
|
})
|
2013-09-24 08:28:26 +02:00
|
|
|
req.on('close', function() {
|
|
|
|
if (!complete) {
|
2013-10-26 14:18:36 +02:00
|
|
|
stream.abort()
|
2013-09-24 08:28:26 +02:00
|
|
|
}
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
2013-09-24 08:28:26 +02:00
|
|
|
|
2013-06-20 15:07:34 +02:00
|
|
|
stream.on('error', function(err) {
|
2013-10-26 14:18:36 +02:00
|
|
|
return res.report_error(err)
|
|
|
|
})
|
2013-09-27 13:31:28 +02:00
|
|
|
stream.on('success', function() {
|
2013-10-26 14:18:36 +02:00
|
|
|
res.status(201)
|
2013-06-01 00:57:28 +02:00
|
|
|
return res.send({
|
|
|
|
ok: 'tarball uploaded successfully'
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2013-05-31 08:26:11 +02:00
|
|
|
// adding a version
|
2013-06-08 03:16:28 +02:00
|
|
|
app.put('/:package/:version/-tag/:tag', can('publish'), media('application/json'), expect_json, function(req, res, next) {
|
2013-10-26 14:18:36 +02:00
|
|
|
var name = req.params.package
|
|
|
|
, version = req.params.version
|
|
|
|
, tag = req.params.tag
|
2013-05-31 08:26:11 +02:00
|
|
|
|
2013-06-01 00:57:28 +02:00
|
|
|
storage.add_version(name, version, req.body, tag, function(err) {
|
2013-10-26 14:18:36 +02:00
|
|
|
if (err) return next(err)
|
|
|
|
res.status(201)
|
2013-06-01 00:57:28 +02:00
|
|
|
return res.send({
|
|
|
|
ok: 'package published'
|
2013-10-26 14:18:36 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2013-05-31 08:26:11 +02:00
|
|
|
|
2014-08-14 23:37:46 +02:00
|
|
|
// hook for tests only
|
|
|
|
if (config._debug) {
|
|
|
|
app.get('/-/_debug', function(req, res) {
|
|
|
|
var do_gc = typeof(global.gc) !== 'undefined'
|
|
|
|
if (do_gc) global.gc()
|
|
|
|
res.send({
|
|
|
|
pid: process.pid,
|
|
|
|
main: process.mainModule.filename,
|
|
|
|
conf: config.self_path,
|
|
|
|
mem: process.memoryUsage(),
|
|
|
|
gc: do_gc,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2013-10-26 14:18:36 +02:00
|
|
|
app.use(app.router)
|
2013-06-01 00:57:28 +02:00
|
|
|
app.use(function(err, req, res, next) {
|
2013-12-05 13:27:23 +01:00
|
|
|
if (typeof(res.report_error) !== 'function') {
|
|
|
|
// in case of very early error this middleware may not be loaded before error is generated
|
|
|
|
// fixing that
|
|
|
|
error_reporting_middleware(req, res, function(){})
|
|
|
|
}
|
2013-10-26 14:18:36 +02:00
|
|
|
res.report_error(err)
|
|
|
|
})
|
2013-06-01 00:57:28 +02:00
|
|
|
|
2014-09-06 21:53:28 +02:00
|
|
|
if (config.web && config.web.enable) {
|
|
|
|
require('./index-web')(app, config, storage)
|
|
|
|
} else {
|
|
|
|
app.get('/', function(req, res) {
|
|
|
|
res.send('Web interface is a work-in-progress right now, '
|
|
|
|
+ 'so it is disabled by default. If you want to play with it, '
|
|
|
|
+ 'you can enable it in the config file.')
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2013-10-26 14:18:36 +02:00
|
|
|
return app
|
|
|
|
}
|
2013-05-31 08:26:11 +02:00
|
|
|
|