Configure redirect routes in Fastly

This commit is contained in:
Ray Schamp 2016-04-19 18:42:03 -04:00
parent b4a7a2884f
commit b8bfe46890
3 changed files with 97 additions and 21 deletions

View file

@ -77,12 +77,17 @@ var getAppRouteCondition = function (pathToStatic, routes, additionalPaths) {
return pathsToCondition(allPaths); return pathsToCondition(allPaths);
}; };
var getConditionNameForView = function (view) { var getConditionNameForRoute = function (route, type) {
return 'routes/' + view; return 'routes/' + route.pattern + ' (' + type + ')';
}; };
var getHeaderNameForView = function (view) { var getHeaderNameForRoute = function (route) {
return 'rewrites/' + view; if (route.view) return 'rewrites/' + route.view;
if (route.redirect) return 'redirects/' + route.pattern;
};
var getResponseNameForRoute = function (route) {
return 'redirects/' + route.pattern;
}; };
async.auto({ async.auto({
@ -167,7 +172,7 @@ async.auto({
var conditions = {}; var conditions = {};
async.forEachOf(routes, function (route, id, cb2) { async.forEachOf(routes, function (route, id, cb2) {
var condition = { var condition = {
name: getConditionNameForView(route.view), name: getConditionNameForRoute(route, 'request'),
statement: 'req.url ~ "' + route.pattern + '"', statement: 'req.url ~ "' + route.pattern + '"',
type: 'REQUEST', type: 'REQUEST',
priority: id priority: id
@ -185,21 +190,60 @@ async.auto({
appRouteHeaders: ['version', 'appRouteRequestConditions', function (cb, results) { appRouteHeaders: ['version', 'appRouteRequestConditions', function (cb, results) {
var headers = {}; var headers = {};
async.forEachOf(routes, function (route, id, cb2) { async.forEachOf(routes, function (route, id, cb2) {
var header = { if (route.redirect) {
name: getHeaderNameForView(route.view), async.auto({
action: 'set', responseCondition: function (cb3) {
ignore_if_set: 0, var condition = {
type: 'request', name: getConditionNameForRoute(route, 'response'),
dst: 'url', statement: 'req.url ~ "' + route.pattern + '"',
src: '"/' + route.view + '.html"', type: 'RESPONSE',
request_condition: results.appRouteRequestConditions[id].name, priority: id
priority: 10 };
}; fastly.setCondition(results.version, condition, cb3);
fastly.setFastlyHeader(results.version, header, function (err, response) { },
if (err) return cb2(err); responseObject: function (cb3) {
headers[id] = response; var responseObject = {
cb2(null, response); name: getResponseNameForRoute(route),
}); status: 301,
response: 'Moved Permanently',
request_condition: getConditionNameForRoute(route, 'request')
};
fastly.setResponseObject(results.version, responseObject, cb3);
},
redirectHeader: ['responseCondition', function (cb3, redirectResults) {
var header = {
name: getHeaderNameForRoute(route),
action: 'set',
ignore_if_set: 0,
type: 'RESPONSE',
dst: 'http.Location',
src: '"' + route.redirect + '"',
response_condition: redirectResults.responseCondition.name
};
fastly.setFastlyHeader(results.version, header, cb3);
}]
}, function (err, redirectResults) {
if (err) return cb2(err);
headers[id] = redirectResults.redirectHeader;
cb2(null, redirectResults);
});
} else {
var header = {
name: getHeaderNameForRoute(route, 'request'),
action: 'set',
ignore_if_set: 0,
type: 'REQUEST',
dst: 'url',
src: '"/' + route.view + '.html"',
request_condition: results.appRouteRequestConditions[id].name,
priority: 10
};
fastly.setFastlyHeader(results.version, header, function (err, response) {
if (err) return cb2(err);
headers[id] = response;
cb2(null, response);
});
}
}, function (err) { }, function (err) {
if (err) return cb(err); if (err) return cb(err);
cb(null, headers); cb(null, headers);

View file

@ -110,6 +110,38 @@ module.exports = function (apiKey, serviceId) {
}.bind(this)); }.bind(this));
}; };
/*
* setResponseObject: Upsert a Fastly response object
* Attempts to PUT and POSTs if the PUT request is a 404
*
* @param {number} Version number
* @param {object} Response object sent to the API
* @param {callback} Callback for fastly.request
*/
fastly.setResponseObject = function (version, responseObj, cb) {
if (!this.serviceId) {
cb('Failed to set response object. No serviceId configured');
}
var name = responseObj.name;
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object/' + encodeURIComponent(name);
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object';
return this.request('PUT', putUrl, responseObj, function (err, response) {
if (err && err.statusCode === 404) {
this.request('POST', postUrl, responseObj, function (err, response) {
if (err) {
return cb('Failed to insert response object: ' + err);
}
return cb(null, response);
});
return;
}
if (err) {
return cb('Failed to update response object: ' + err);
}
return cb(null, response);
}.bind(this));
};
/* /*
* cloneVersion: Clone a version to create a new version * cloneVersion: Clone a version to create a new version
* *

View file

@ -45,7 +45,7 @@
"title": "LEGO WeDo 2.0" "title": "LEGO WeDo 2.0"
}, },
{ {
"pattern": "/info/donate/", "pattern": "^/info/donate",
"redirect": "https://secure.donationpay.org/scratchfoundation/" "redirect": "https://secure.donationpay.org/scratchfoundation/"
} }
] ]