Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle fallbackRegistryUrl for ~info and ~preview #380

Merged
merged 10 commits into from
Mar 10, 2017
52 changes: 33 additions & 19 deletions src/registry/domain/url-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,62 @@ var querystring = require('querystring');
var url = require('url');
var _ = require('underscore');

function componentForType(component, baseUrl, type) {
if (_.isString(component)) {
component = {name: component};
}

var href = url.resolve(baseUrl, component.name) + '/';

if (!!component.version) {
href += component.version + '/';
}

href += '~' + type;

return href;
}

var build = {
component: function(component, baseUrl){
if(_.isString(component)){
component = { name: component };
component: function (component, baseUrl) {
if (_.isString(component)) {
component = {name: component};
}

var componentUrl = url.resolve(baseUrl, component.name);

if(component.version){
if (component.version) {
componentUrl += '/' + component.version;
}

componentUrl += build.queryString(component.parameters);

return componentUrl;
},
componentPreview: function(component, baseUrl){
var href = baseUrl + component.name + '/';

if(!!component.version){
href += component.version + '/';
}

href += '~preview/';

if(!!component.parameters && !_.isEmpty(component.parameters)){
href += '?' + querystring.stringify(component.parameters);
componentInfo: function (component, baseUrl) {
return componentForType(component, baseUrl, 'info');
},
componentPreview: function (component, baseUrl) {
var href = componentForType(component, baseUrl, 'preview');
if (!!component.parameters && !_.isEmpty(component.parameters)) {
href += '/?' + querystring.stringify(component.parameters);
} else {
href += '/';
}

return href;
},
queryString: function(parameters){
queryString: function (parameters) {
var qs = '';

if(_.keys(parameters).length > 0){
if (_.keys(parameters).length > 0) {
qs += '?';

_.forEach(parameters, function(parameter, key){
_.forEach(parameters, function (parameter, key) {
qs += key + '=' + encodeURIComponent(parameter) + '&';
});

if(_.keys(parameters).length > 0){
if (_.keys(parameters).length > 0) {
qs = qs.slice(0, -1);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/registry/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ module.exports.create = function(app, conf, repository){
var routes = {
component: new ComponentRoute(conf, repository),
components: new ComponentsRoute(conf, repository),
componentInfo: new ComponentInfoRoute(repository),
componentPreview: new ComponentPreviewRoute(repository),
componentInfo: new ComponentInfoRoute(conf, repository),
componentPreview: new ComponentPreviewRoute(conf, repository),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those two endpoints now need configuration for fallbackRegistryUrl

listComponents: new ListComponentsRoute(repository),
publish: new PublishRoute(repository),
staticRedirector: new StaticRedirectorRoute(repository)
Expand Down
105 changes: 63 additions & 42 deletions src/registry/routes/component-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,82 @@ var parseAuthor = require('parse-author');
var _ = require('underscore');

var urlBuilder = require('../domain/url-builder');
var getComponentFallback = require('./helpers/get-component-fallback');

module.exports = function(repository){
return function(req, res){
function getParams(component) {
var params = {};
if(!!component.oc.parameters){
var mandatoryParams = _.filter(_.keys(component.oc.parameters), function(paramName){
var param = component.oc.parameters[paramName];
return !!param.mandatory && !!param.example;
});

params = _.mapObject(_.pick(component.oc.parameters, mandatoryParams), function(param){
return param.example;
});
}

return params;
}

repository.getComponent(req.params.componentName, req.params.componentVersion, function(err, component){
function getParsedAuthor(component) {
var author = component.author || {};
return _.isString(author) ? parseAuthor(author) : author;
}

if(err){
res.errorDetails = err;
return res.status(404).json({ err: err });
function addGetRepositoryUrlFunction(component) {
component.getRepositoryUrl = function() {
if (_.isObject(this.repository)) {
if (this.repository.url) {
return this.repository.url;
}
}
if (_.isString(this.repository)) {
return this.repository;
}
return null;
};
}

var isHtmlRequest = !!req.headers.accept && req.headers.accept.indexOf('text/html') >= 0;
function componentInfo(err, req, res, component) {
if(err) {
res.errorDetails = err.registryError || err;
return res.status(404).json(err);
}

if(isHtmlRequest && !!res.conf.discovery){
var isHtmlRequest = !!req.headers.accept && req.headers.accept.indexOf('text/html') >= 0;

var params = {},
author = component.author || {},
parsedAuthor = _.isString(author) ? parseAuthor(author) : author;
if(isHtmlRequest && !!res.conf.discovery){

if(!!component.oc.parameters){
var mandatoryParams = _.filter(_.keys(component.oc.parameters), function(paramName){
var param = component.oc.parameters[paramName];
return !!param.mandatory && !!param.example;
});
var params = getParams(component);
var parsedAuthor = getParsedAuthor(component);
addGetRepositoryUrlFunction(component);

params = _.mapObject(_.pick(component.oc.parameters, mandatoryParams), function(param){
return param.example;
});
}
return res.render('component-info', {
component: component,
dependencies: _.keys(component.dependencies),
href: res.conf.baseUrl,
parsedAuthor: parsedAuthor,
sandBoxDefaultQs: urlBuilder.queryString(params)
});

component.getRepositoryUrl = function() {
if (_.isObject(this.repository)) {
if (this.repository.url) {
return this.repository.url;
}
}
if (_.isString(this.repository)) {
return this.repository;
}
return null;
};
} else {
res.status(200).json(_.extend(component, {
requestVersion: req.params.componentVersion || ''
}));
}
}

return res.render('component-info', {
component: component,
dependencies: _.keys(component.dependencies),
href: res.conf.baseUrl,
parsedAuthor: parsedAuthor,
sandBoxDefaultQs: urlBuilder.queryString(params)
module.exports = function(conf, repository){
return function(req, res){
repository.getComponent(req.params.componentName, req.params.componentVersion, function(registryError, component){
if(registryError && conf.fallbackRegistryUrl) {
return getComponentFallback.getComponentInfo(conf, req, res, registryError, function(fallbackError, fallbackComponent){
componentInfo(fallbackError, req, res, fallbackComponent);
});

} else {
res.status(200).json(_.extend(component, {
requestVersion: req.params.componentVersion || ''
}));
}

componentInfo(registryError, req, res, component);
});
};
};
48 changes: 30 additions & 18 deletions src/registry/routes/component-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,46 @@
var _ = require('underscore');

var urlBuilder = require('../domain/url-builder');
var getComponentFallback = require('./helpers/get-component-fallback');

module.exports = function(repository){
return function(req, res){

repository.getComponent(req.params.componentName, req.params.componentVersion, function(err, component){

if(err){
res.errorDetails = err;
function componentPreview(err, req, res, component) {
if(err) {
res.errorDetails = err.registryError || err;
res.errorCode = 'NOT_FOUND';
return res.status(404).json({ err: err });
}
return res.status(404).json(err);
}

var isHtmlRequest = !!req.headers.accept && req.headers.accept.indexOf('text/html') >= 0;

var isHtmlRequest = !!req.headers.accept && req.headers.accept.indexOf('text/html') >= 0;
if(isHtmlRequest && !!res.conf.discovery){

if(isHtmlRequest && !!res.conf.discovery){

return res.render('component-preview', {
component: component,
dependencies: _.keys(component.dependencies),
href: res.conf.baseUrl,
qs: urlBuilder.queryString(req.query)
component: component,
dependencies: _.keys(component.dependencies),
href: res.conf.baseUrl,
qs: urlBuilder.queryString(req.query)
});

} else {
} else {
res.status(200).json(_.extend(component, {
requestVersion: req.params.componentVersion || ''
requestVersion: req.params.componentVersion || ''
}));
}
}

module.exports = function(conf, repository){
return function(req, res){

repository.getComponent(req.params.componentName, req.params.componentVersion, function(registryError, component){

if(registryError && conf.fallbackRegistryUrl) {
return getComponentFallback.getComponentPreview(conf, req, res, registryError, function(fallbackError, fallbackComponent){
componentPreview(fallbackError, req, res, fallbackComponent);
});
}

componentPreview(registryError, req, res, component);

});
};
};
79 changes: 59 additions & 20 deletions src/registry/routes/helpers/get-component-fallback.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,69 @@

var request = require('minimal-request');
var url = require('url');
var urlBuilder = require('../../domain/url-builder');
var _ = require('underscore');

module.exports = function(fallbackRegistryUrl, headers, component, callback) {
function getComponentFallbackForViewType(buildUrl, conf, req, res, registryError, callback) {
var path = buildUrl({
name: req.params.componentName,
version: req.params.componentVersion
}, conf.fallbackRegistryUrl);

return request({
method: 'post',
url: fallbackRegistryUrl,
headers: _.extend({}, headers, {'host': url.parse(fallbackRegistryUrl).host}),
json: true,
body: {
components: [
component
]
method: 'get',
url: path,
headers: _.extend({}, req.headers, {
'host': url.parse(conf.fallbackRegistryUrl).host,
'accept': 'application/json'
})
}, function (fallbackErr, fallbackResponse) {
if (fallbackErr === 304) {
return res.status(304).send('');
}
}, function(err, res) {
if(err || !res || res.length === 0) {
return callback({
status: 404,
response: {
code: 'NOT_FOUND',
error: err
}
});

if (fallbackErr) {
return callback({registryError: registryError, fallbackError: fallbackErr});
}

return callback(res[0]);
try {
return callback(null, JSON.parse(fallbackResponse));
} catch (parseError) {
return callback({registryError: registryError, fallbackError: 'Could not parse fallback response: ' + fallbackResponse});
}
});
};
}

module.exports = {
getComponent: function (fallbackRegistryUrl, headers, component, callback) {
return request({
method: 'post',
url: fallbackRegistryUrl,
headers: _.extend({}, headers, {'host': url.parse(fallbackRegistryUrl).host}),
json: true,
body: {
components: [
component
]
}
}, function (err, res) {
if (err || !res || res.length === 0) {
return callback({
status: 404,
response: {
code: 'NOT_FOUND',
error: err
}
});
}

return callback(res[0]);
});
},
getComponentPreview: function (conf, req, res, registryError, callback) {
getComponentFallbackForViewType(urlBuilder.componentPreview, conf, req, res, registryError, callback);
},
getComponentInfo: function (conf, req, res, registryError, callback) {
getComponentFallbackForViewType(urlBuilder.componentInfo, conf, req, res, registryError, callback);
}
};
2 changes: 1 addition & 1 deletion src/registry/routes/helpers/get-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module.exports = function(conf, repository){
// check route exist for component and version
if(err){
if(conf.fallbackRegistryUrl) {
return getComponentFallback(conf.fallbackRegistryUrl, options.headers, requestedComponent, callback);
return getComponentFallback.getComponent(conf.fallbackRegistryUrl, options.headers, requestedComponent, callback);
}

return callback({
Expand Down
Loading