Skip to content
This repository has been archived by the owner on Jun 2, 2024. It is now read-only.

Commit

Permalink
feat(sync): enable none syncModel proxy all public packages
Browse files Browse the repository at this point in the history
Fixes #589 #581
  • Loading branch information
fengmk2 committed Feb 2, 2015
1 parent d83c52b commit 24d6831
Show file tree
Hide file tree
Showing 13 changed files with 181 additions and 53 deletions.
12 changes: 7 additions & 5 deletions config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,19 @@ var config = {
* registry mode config
*/

// enable private mode, only admin can publish, other use just can sync package from source npm
enablePrivate: true,
// enable private mode or not
// private mode: only admins can publish, other users just can sync package from source npm
// public mode: all users can publish
enablePrivate: false,

// registry scopes, if don't set, means do not support scopes
scopes: [
'@cnpm',
'@cnpmtest'
],

// force user publish with scope
// but admins still can publish without scope
// force users publish with scope
// and admins still can publish without scope
forcePublishWithScope: true,

// some registry already have some private packages in global scope
Expand Down Expand Up @@ -205,7 +207,7 @@ var config = {
syncByInstall: true,

// sync mode select
// none: do not sync any module
// none: do not sync any module, proxy all public modules from sourceNpmRegistry
// exist: only sync exist modules
// all: sync all modules
syncModel: 'exist', // 'none', 'all', 'exist'
Expand Down
19 changes: 7 additions & 12 deletions controllers/registry/package/dist_tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,6 @@

var packageService = require('../../../services/package');

function* getTags(ctx) {
var name = ctx.params.name || ctx.params[0];
var rows = yield* packageService.listModuleTags(name);
var tags = {};
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
tags[row.tag] = row.version;
}
return tags;
}

function ok() {
return {
ok: "dist-tags updated"
Expand All @@ -35,7 +24,13 @@ function ok() {

// GET /-/package/:pkg/dist-tags -- returns the package's dist-tags
exports.index = function* () {
var tags = yield* getTags(this);
var name = this.params.name || this.params[0];
var rows = yield* packageService.listModuleTags(name);
var tags = {};
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
tags[row.tag] = row.version;
}
this.body = tags;
};

Expand Down
25 changes: 4 additions & 21 deletions controllers/registry/package/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@

var debug = require('debug')('cnpmjs.org:controllers:registry:package:list');
var packageService = require('../../../services/package');
var npmService = require('../../../services/npm');
var config = require('../../../config');
var setDownloadURL = require('../../../lib/common').setDownloadURL;
var common = require('../../../lib/common');
var SyncModuleWorker = require('../../sync_module_worker');
var utils = require('../../utils');

/**
* list all version of a module
Expand Down Expand Up @@ -114,23 +113,7 @@ module.exports = function* list() {
var logId = yield* SyncModuleWorker.sync(name, 'sync-by-install');
debug('start sync %s, get log id %s', name, logId);

// try to get package from official registry
var r = yield* npmService.request('/' + name, {
registry: config.officialNpmRegistry
});

debug('requet from officialNpmRegistry response %s', r.status);
if (r.status !== 200) {
this.status = 404;
this.body = {
error: 'not_found',
reason: 'document not found'
};
return;
}

this.body = r.data;
return;
return yield utils.proxyToNpmRegistry(this);
}

var latestMod = null;
Expand All @@ -150,7 +133,7 @@ module.exports = function* list() {
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
var pkg = row.package;
setDownloadURL(pkg, this);
common.setDownloadURL(pkg, this);
pkg._cnpm_publish_time = row.publish_time;
versions[pkg.version] = pkg;

Expand Down
18 changes: 6 additions & 12 deletions controllers/sync_module_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ SyncModuleWorker.prototype.start = function () {
return;
}

if (config.syncModel === 'none') {
return;
}

var arr = [];
for (var i = 0; i < that.concurrency; i++) {
arr.push(that.next(i));
Expand Down Expand Up @@ -389,7 +393,7 @@ SyncModuleWorker.prototype._unpublished = function* (name, unpublishedInfo) {
var mods = yield* packageService.listModulesByName(name);
this.log(' [%s] start unpublished %d versions from local cnpm registry',
name, mods.length);
if (this._isLocalModule(mods)) {
if (common.isLocalModule(mods)) {
// publish on cnpm, dont sync this version package
this.log(' [%s] publish on local cnpm registry, don\'t sync', name);
return [];
Expand Down Expand Up @@ -427,16 +431,6 @@ SyncModuleWorker.prototype._unpublished = function* (name, unpublishedInfo) {
this.log(' [%s] delete nfs files: %j success', name, keys);
};

SyncModuleWorker.prototype._isLocalModule = function (mods) {
for (var i = 0; i < mods.length; i++) {
var r = mods[i];
if (r.package && r.package._publish_on_cnpm) {
return true;
}
}
return false;
};

SyncModuleWorker.prototype._sync = function* (name, pkg) {
var that = this;
var hasModules = false;
Expand All @@ -451,7 +445,7 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
var existsStarUsers = result[2];
var existsNpmMaintainers = result[3];

if (that._isLocalModule(moduleRows)) {
if (common.isLocalModule(moduleRows)) {
// publish on cnpm, dont sync this version package
that.log(' [%s] publish on local cnpm registry, don\'t sync', name);
return [];
Expand Down
17 changes: 17 additions & 0 deletions controllers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var utility = require('utility');
var ms = require('humanize-ms');
var moment = require('moment');
var downloadTotalService = require('../services/download_total');
var npmService = require('../services/npm');
var nfs = require('../common/nfs');
var config = require('../config');

Expand Down Expand Up @@ -159,3 +160,19 @@ exports.getOssLicenseUrlFromName = function (name) {
return licenseMap[name.toLowerCase()] ?
base + licenseMap[name.toLowerCase()] : base + name;
};

exports.proxyToNpmRegistry = function* (ctx) {
var r = yield* npmService.request(ctx.url);
if (!r.status && r.status < 200) {
r.status = 502;
r.body = {
error: 'remote_npm_registry_error',
reason: 'status: ' + r.status + ' body: ' + (r.data ? r.data.toString() : '[empty]'),
};
return;
}

ctx.status = r.status;
ctx.body = r.data;
return;
};
10 changes: 10 additions & 0 deletions lib/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,13 @@ exports.isMaintainer = function (user, maintainers) {

return match.length > 0;
};

exports.isLocalModule = function (mods) {
for (var i = 0; i < mods.length; i++) {
var r = mods[i];
if (r.package && r.package._publish_on_cnpm) {
return true;
}
}
return false;
};
2 changes: 1 addition & 1 deletion middleware/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module.exports = function *login(next) {
this.status = 401;
this.body = {
error: 'unauthorized',
reason: 'Login first.'
reason: 'Login first'
};
return;
}
Expand Down
50 changes: 50 additions & 0 deletions middleware/proxy_to_npm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**!
* cnpmjs.org - middleware/proxy_to_npm.js
*
* Copyright(c) Alibaba Group Holding Limited.
*
* Authors:
* 苏千 <[email protected]> (http://fengmk2.com)
*/

'use strict';

/**
* Module dependencies.
*/

var debug = require('debug')('cnpmjs.org:middleware:proxy_to_npm');
var config = require('../config');

var proxyUrls = [
// /:pkg, dont contains scoped package
/^\/[\w\-\.]+$/,
// /-/package/:pkg/dist-tags
/^\/\-\/package\/[\w\-\.]+\/dist-tags/,
];

module.exports = function* proxyToNpm(next) {
if (config.syncModel !== 'none') {
return yield* next;
}
// only proxy read requests
if (this.method !== 'GET' && this.method !== 'HEAD') {
return yield* next;
}

var pathname = this.path;
var match;
for (var i = 0; i < proxyUrls.length; i++) {
match = proxyUrls[i].test(pathname);
if (match) {
break;
}
}
if (!match) {
return yield* next;
}

var url = config.sourceNpmRegistry + this.url;
debug('proxy to %s', url);
this.redirect(url);
};
2 changes: 2 additions & 0 deletions servers/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var auth = require('../middleware/auth');
var staticCache = require('../middleware/static');
var notFound = require('../middleware/registry_not_found');
var cors = require('../middleware/cors');
var proxyToNpm = require('../middleware/proxy_to_npm');

app.use(block());
middlewares.jsonp(app);
Expand All @@ -36,6 +37,7 @@ app.use(staticCache);

app.keys = ['todokey', config.sessionSecret];
app.proxy = true;
app.use(proxyToNpm);
app.use(middlewares.bodyParser({jsonLimit: config.jsonLimit}));
app.use(cors({
methods: 'GET,HEAD'
Expand Down
2 changes: 1 addition & 1 deletion services/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
var urllib = require('../common/urllib');
var config = require('../config');

var USER_AGENT = 'cnpmjs.org/' + config.version + ' ' + urllib.USER_AGENT;
var USER_AGENT = 'npm_service.cnpmjs.org/' + config.version + ' ' + urllib.USER_AGENT;

function* request(url, options) {
options = options || {};
Expand Down
3 changes: 2 additions & 1 deletion test/controllers/registry/package/dist_tag.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ var pedding = require('pedding');
var should = require('should');
var app = require('../../../../servers/registry');
var utils = require('../../../utils');
var config = require('../../../../config');

describe('controllers/registry/package.dist_tag.test.js', function () {
describe('controllers/registry/package/dist_tag.test.js', function () {
afterEach(mm.restore);

describe('index()', function () {
Expand Down
9 changes: 9 additions & 0 deletions test/controllers/registry/package/list.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ describe('controllers/registry/package/list.test.js', function () {
});
});

before(function (done) {
var worker = new SyncModuleWorker({
name: 'baidu',
noDep: true,
});
worker.start();
worker.on('end', done);
});

it('should return all versions', function (done) {
request(app.listen())
.get('/testmodule-list-1')
Expand Down
65 changes: 65 additions & 0 deletions test/middleware/proxy_to_npm.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**!
* cnpmjs.org - test/middleware/proxy_to_npm.test.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <[email protected]> (http://fengmk2.github.com)
*/

'use strict';

/**
* Module dependencies.
*/

var request = require('supertest');
var mm = require('mm');
var app = require('../../servers/registry');
var config = require('../../config');

describe('middleware/proxy_to_npm.test.js', function () {
beforeEach(function () {
mm(config, 'syncModel', 'none');
});

afterEach(mm.restore);

describe('package', function () {
it('should proxy to source registry when package not exists', function (done) {
request(app.listen())
.get('/ms')
.expect('location', config.sourceNpmRegistry + '/ms')
.expect(302, done);
});

it('should proxy to source registry when package is not local', function (done) {
request(app.listen())
.get('/baidu?write=true')
.expect('location', config.sourceNpmRegistry + '/baidu?write=true')
.expect(302, done);
});

it('should not proxy to source registry when package is scoped', function (done) {
request(app.listen())
.get('/@scoped/test-package-name')
.expect(404, done);
});
});

describe('dist-tags', function () {
it('should proxy to source registry when package not exists', function (done) {
request(app.listen())
.get('/-/package/ms/dist-tags')
.expect('location', config.sourceNpmRegistry + '/-/package/ms/dist-tags')
.expect(302, done);
});

it('should dont proxy scoped package', function (done) {
request(app.listen())
.get('/-/package/@scoped/ms/dist-tags')
.expect(404, done);
});
});
});

0 comments on commit 24d6831

Please sign in to comment.