Untangle the requests a bit with help from async

This commit is contained in:
Ray Schamp 2016-04-16 12:49:48 -04:00
parent 87da93f9ea
commit 0aa9b7c587
3 changed files with 137 additions and 141 deletions

View file

@ -1,3 +1,4 @@
var async = require('async');
var defaults = require('lodash.defaults'); var defaults = require('lodash.defaults');
var glob = require('glob'); var glob = require('glob');
var path = require('path'); var path = require('path');
@ -73,28 +74,9 @@ var getPassCacheConditionName = function () {
return 'Cache ' + getPassRequestConditionName(); return 'Cache ' + getPassRequestConditionName();
}; };
var getRouteHeaderConditionPairs = function (routes) { var getBucketNameHeaderName = function () {
return routes.map(function (route, id) { return 'Bucket name';
return { }
condition: {
name: getConditionNameForView(route.view),
statement: 'req.url ~ "' + route.pattern + '"',
type: 'REQUEST',
priority: 10
},
header: {
name: getHeaderNameForView(route.view),
action: 'set',
ignore_if_set: 0,
type: 'request',
dst: 'url',
src: '"/' + route.view + '.html"',
request_condition: getConditionNameForView(route.view),
priority: id
},
}
});
};
var notPassCondition = { var notPassCondition = {
name: getNotPassRequestConditionName(), name: getNotPassRequestConditionName(),
@ -102,121 +84,94 @@ var notPassCondition = {
type: 'REQUEST', type: 'REQUEST',
priority: 10 priority: 10
}; };
var passCondition = { var passCondition = {
name: getPassRequestConditionName(), name: getPassRequestConditionName(),
statement: fastly.negateConditionStatement(notPassCondition.statement), statement: fastly.negateConditionStatement(notPassCondition.statement),
type: 'REQUEST', type: 'REQUEST',
priority: 10 priority: 10
}; };
var passCacheCondition = defaults({name: getPassCacheConditionName(), type: 'CACHE'}, passCondition);
var bucketNameHeader = {
name: getBucketNameHeaderName(),
action: 'set',
ignore_if_set: 0,
type: 'REQUEST',
dst: 'http.host',
src: '"' + s3Bucket + '"',
request_condition: notPassCondition.name,
priority: 1
};
var routeHeaderConditionPairs = getRouteHeaderConditionPairs(routes); async.waterfall([
fastly.getLatestVersion.bind(fastly),
fastly.getLatestVersion(function (err, version) { function (version, next) {
if (err) return console.error(err); if (version.active) return next('Latest version is active. Will not modify.');
if (version.active) return console.error('Latest version is active. Will not modify.'); if (version.locked) return next('Latest version is locked. Cannot modify.');
if (version.locked) return console.error('Latest version is locked. Cannot modify.'); async.parallel([
fastly.setCondition( function (cb) {
version.number, notPassCondition.name, notPassCondition, async.series([
function (err) { async.apply(fastly.setCondition.bind(fastly), version.number, notPassCondition),
if (err) { async.apply(fastly.setFastlyHeader.bind(fastly), version.number, bucketNameHeader)
console.error('Failed to set !(Pass) request condition:'); ], cb)
console.dir(err); },
console.error('Could not set bucket header without setting !(Pass) condition'); function (cb) {
process.exit(1); async.series([
async.apply(fastly.setCondition.bind(fastly), version.number, passCondition),
function (cb) {
async.parallel([
async.apply(
fastly.request.bind(fastly), 'PUT',
fastly.getFastlyAPIPrefix(serviceId, version.number) + '/request_settings/Pass',
{request_condition: passCondition.name}
),
async.apply(
fastly.request.bind(fastly), 'PUT',
fastly.getFastlyAPIPrefix(serviceId, version.number) + '/backend/femto',
{request_condition: passCondition.name}
)
], cb)
}
], cb)
},
function (cb) {
async.series([
async.apply(fastly.setCondition.bind(fastly), version.number, passCacheCondition),
async.apply(
fastly.request.bind(fastly), 'PUT',
fastly.getFastlyAPIPrefix(serviceId, version.number) + '/cache_settings/Pass',
{request_condition: passCacheCondition.name}
),
], cb)
},
function (cb) {
async.forEachOf(routes, function (route, id, cb) {
var condition = {
name: getConditionNameForView(route.view),
statement: 'req.url ~ "' + route.pattern + '"',
type: 'REQUEST',
priority: 10
};
var header = {
name: getHeaderNameForView(route.view),
action: 'set',
ignore_if_set: 0,
type: 'request',
dst: 'url',
src: '"/' + route.view + '.html"',
request_condition: getConditionNameForView(route.view),
priority: id
};
async.series([
async.apply(fastly.setCondition.bind(fastly), version.number, condition),
async.apply(fastly.setFastlyHeader.bind(fastly), version.number, header)
], cb);
}, cb)
} }
], next);
var bucketNameHeaderName = 'Bucket name'; }], function (err, responses) {
fastly.setHeader( if (err) {
version.number, bucketNameHeaderName, console.log(err);
{ process.exit(1);
name: bucketNameHeaderName,
action: 'set',
ignore_if_set: 0,
type: 'REQUEST',
dst: 'http.host',
src: '"' + s3Bucket + '"',
request_condition: notPassCondition.name,
priority: 1
},
function (err) {
if (err) {
console.error('Failed to set Bucket name header:', err);
process.exit(1);
}
}
);
} }
); }
fastly.setCondition( );
version.number, passCondition.name, passCondition,
function (err) {
if (err) return console.error('Failed to set Pass condition:', err);
fastly.request(
'PUT',
fastly.getFastlyAPIPrefix(serviceId, version.number) + '/backend/femto',
{request_condition: passCondition.name},
function (err) {
if (err) {
console.error('Failed to set femto backend to use Pass condition.', err);
process.exit(1);
}
}
);
fastly.request(
'PUT',
fastly.getFastlyAPIPrefix(serviceId, version.number) + '/request_settings/Pass',
{request_condition: passCondition.name},
function (err) {
if (err) {
console.error('Failed to set Pass request setting to use Pass condition.', err);
process.exit(1);
}
}
);
}
);
var passCacheCondition = defaults({name: getPassCacheConditionName(), type: 'CACHE'}, passCondition);
fastly.setCondition(
version.number, getPassCacheConditionName(), passCacheCondition,
function (err) {
if (err) {
console.error('Failed to set Cache Pass condition:', err, passCacheCondition);
process.exit(1);
}
fastly.request(
'PUT',
fastly.getFastlyAPIPrefix(serviceId, version.number),
{cache_condition: getPassCacheConditionName()},
function (err) {
if (err) {
console.error('Failed to set Pass cache setting to use Cache Pass condition', err);
process.exit(1);
}
}
);
}
);
routeHeaderConditionPairs.forEach(function (pair) {
var condition = pair.condition;
var header = pair.header;
fastly.setCondition(
version.number, condition.name, condition,
function (err, response) {
if (err) {
console.error('Failed to set route condition', condition.name, err);
process.exit(1);
}
fastly.setHeader(
version.number, header.name, header,
function (err) {
if (err) {
console.error('Failed to set route rewrite header', header.name, err);
process.exit(1);
}
}
)
}
);
});
});

View file

@ -13,10 +13,16 @@ module.exports = function (apiKey, serviceId) {
}; };
fastly.getLatestVersion = function (cb) { fastly.getLatestVersion = function (cb) {
if (!this.serviceId) return cb('No serviceId configured'); if (!this.serviceId) {
console.error('Failed to get latest version.');
return cb('No serviceId configured');
}
var url = '/service/'+ encodeURIComponent(this.serviceId) +'/version'; var url = '/service/'+ encodeURIComponent(this.serviceId) +'/version';
this.request('GET', url, function (err, versions) { this.request('GET', url, function (err, versions) {
if (err) return cb(err); if (err) {
console.error('Failed to get versions', err);
return cb(err);
}
var latestVersion = versions.reduce(function (latestVersion, version) { var latestVersion = versions.reduce(function (latestVersion, version) {
if (!latestVersion) return version; if (!latestVersion) return version;
if (version.number > latestVersion.number) return version; if (version.number > latestVersion.number) return version;
@ -26,24 +32,58 @@ module.exports = function (apiKey, serviceId) {
}); });
}; };
fastly.setCondition = function (version, name, condition, cb) { fastly.setCondition = function (version, condition, cb) {
if (!this.serviceId) return callback('No serviceId configured'); if (!this.serviceId) {
console.error('Failed to set condition', condition);
return cb('No serviceId configured');
}
var name = condition.name;
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition/' + encodeURIComponent(name); var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition/' + encodeURIComponent(name);
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition'; var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition';
return this.request('PUT', putUrl, condition, function (err, response) { return this.request('PUT', putUrl, condition, function (err, response) {
if (err && err.statusCode === 404) return this.request('POST', postUrl, condition, cb); if (err && err.statusCode === 404) {
return cb(err, response); this.request('POST', postUrl, condition, function (err, response) {
if (err) {
console.log('Failed to POST header', header);
return cb(err);
}
return cb(null, response);
});
return;
}
if (err) {
console.error('Failed to PUT condition', condition);
return cb(err);
}
return cb(null, response);
}.bind(this)); }.bind(this));
}; };
fastly.setHeader = function (version, name, header, cb) { fastly.setFastlyHeader = function (version, header, cb) {
if (!this.serviceId) {
console.error('Failed to set header', header);
cb('No serviceId configured');
}
var name = header.name;
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header/' + encodeURIComponent(name); var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header/' + encodeURIComponent(name);
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header'; var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header';
return this.request('PUT', putUrl, header, function (err, response) { return this.request('PUT', putUrl, header, function (err, response) {
if (err && err.statusCode === 404) return this.request('POST', postUrl, header, cb); if (err && err.statusCode === 404) {
return cb(err, response); this.request('POST', postUrl, header, function (err, response) {
if (err) {
console.error('Failed to POST header', header);
return cb(err);
}
return cb(null, response);
});
return;
}
if (err) {
console.error('Failed to PUT header', header);
return cb(err);
}
return cb(null, response);
}.bind(this)); }.bind(this));
}; };
return fastly; return fastly;
}; };

View file

@ -31,6 +31,7 @@
"raven": "0.10.0" "raven": "0.10.0"
}, },
"devDependencies": { "devDependencies": {
"async": "1.5.2",
"autoprefixer": "6.3.6", "autoprefixer": "6.3.6",
"classnames": "2.1.3", "classnames": "2.1.3",
"cookie": "0.2.2", "cookie": "0.2.2",