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,16 +74,84 @@ 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: {
var notPassCondition = {
name: getNotPassRequestConditionName(),
statement: getAppRouteCondition('../static/*', routes, extraAppRoutes),
type: 'REQUEST',
priority: 10
};
var passCondition = {
name: getPassRequestConditionName(),
statement: fastly.negateConditionStatement(notPassCondition.statement),
type: 'REQUEST',
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
};
async.waterfall([
fastly.getLatestVersion.bind(fastly),
function (version, next) {
if (version.active) return next('Latest version is active. Will not modify.');
if (version.locked) return next('Latest version is locked. Cannot modify.');
async.parallel([
function (cb) {
async.series([
async.apply(fastly.setCondition.bind(fastly), version.number, notPassCondition),
async.apply(fastly.setFastlyHeader.bind(fastly), version.number, bucketNameHeader)
], cb)
},
function (cb) {
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), name: getConditionNameForView(route.view),
statement: 'req.url ~ "' + route.pattern + '"', statement: 'req.url ~ "' + route.pattern + '"',
type: 'REQUEST', type: 'REQUEST',
priority: 10 priority: 10
}, };
header: { var header = {
name: getHeaderNameForView(route.view), name: getHeaderNameForView(route.view),
action: 'set', action: 'set',
ignore_if_set: 0, ignore_if_set: 0,
@ -91,132 +160,18 @@ var getRouteHeaderConditionPairs = function (routes) {
src: '"/' + route.view + '.html"', src: '"/' + route.view + '.html"',
request_condition: getConditionNameForView(route.view), request_condition: getConditionNameForView(route.view),
priority: id 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);
}; }], function (err, responses) {
var notPassCondition = {
name: getNotPassRequestConditionName(),
statement: getAppRouteCondition('../static/*', routes, extraAppRoutes),
type: 'REQUEST',
priority: 10
};
var passCondition = {
name: getPassRequestConditionName(),
statement: fastly.negateConditionStatement(notPassCondition.statement),
type: 'REQUEST',
priority: 10
};
var routeHeaderConditionPairs = getRouteHeaderConditionPairs(routes);
fastly.getLatestVersion(function (err, version) {
if (err) return console.error(err);
if (version.active) return console.error('Latest version is active. Will not modify.');
if (version.locked) return console.error('Latest version is locked. Cannot modify.');
fastly.setCondition(
version.number, notPassCondition.name, notPassCondition,
function (err) {
if (err) { if (err) {
console.error('Failed to set !(Pass) request condition:'); console.log(err);
console.dir(err);
console.error('Could not set bucket header without setting !(Pass) condition');
process.exit(1);
}
var bucketNameHeaderName = 'Bucket name';
fastly.setHeader(
version.number, bucketNameHeaderName,
{
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); 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",