Promise based Fastly API client for Node.js
The callback based fastly package is still the most used client on NPM. However, I needed a client which allows me to perform request sequentially and parallelly without ending up in an untamable callback hell!
The fastly-promises
package uses the promise based HTTP client Axios to perform requests to the Fastly API. Axios supports the native JavaScript Promise API and automatically transforms the data into JSON. Each fastly-promises
API method returns a Promise which represents either the completion or failure of the request.
You'll need a Fastly API Token in order to use the fastly-promises
library. I recommend to use a token with a global scope to be able to use all fastly-promises
API methods.
This is a Node.js module available through the npm registry. Installation is done using the npm install
command:
$ npm install fastly-promises
const fastly = require('fastly-promises');
// create one or more instances
const service_1 = fastly('token', 'service_id_1');
const serivce_2 = fastly('token', 'service_id_2');
// read/write baseURL property
console.log(service_1.request.defaults.baseURL); // https://api.fastly.com
// read/write timeout property
console.log(service_1.request.defaults.timeout); // 3000
Purge all domains of the active version:
- Get all the versions
- Filter out the active version
- Get all the domains for the active version
- Purge all the domains
- Log the status text for each purge request
const fastly = require('fastly-promises');
const service = fastly('token', 'service_id');
function handler() {
service.readVersions()
.then(versions => {
const active = versions.data.filter(version => version.active)[0];
return service.readDomains(active.number);
})
.then(domains => {
return Promise.all(domains.data.map(domain => service.purgeIndividual(domain.name)));
})
.then(purges => {
purges.forEach(purge => console.log(purge.statusText));
})
.catch(e => {
console.log('Shoot!');
});
}
Update first_byte_timeout
property for every backend and service if the value is less than 5000 milliseconds:
- Get all the services associated with the Fastly API token
- Filter out the service IDs
- Iterate over all services synchronously
- Get all the versions
- Filter out the active version
- Get all the backends for the active version
- Filter out the affected backends
- Continue with the next service if there are no affected backends
- Clone the active version
- Update all the affected backends parallelly
- Activate the cloned version
const fastly = require('fastly-promises');
const account = fastly('token');
async function handler() {
try {
const services = await account.readServices();
const ids = services.data.map(service => service.id);
for (const id of ids) {
const service = fastly('token', id);
const versions = await service.readVersions();
const active = versions.data.filter(version => version.active)[0];
const backends = await service.readBackends(active.number);
const affected = backends.data.filter(backend => backend.first_byte_timeout < 5000);
if (!affected.length) continue;
const clone = await service.cloneVersion(active.number);
await Promise.all(affected.map(backend => service.updateBackend(clone.data.number, backend.name, { first_byte_timeout: 5000 })));
await service.activateVersion(clone.data.number);
}
} catch (e) {
console.log('Shoot!');
}
}
Each fastly-promises
API method returns the following response object:
{
// the HTTP status code from the server response
status: 200,
// the HTTP status message from the server response
statusText: 'OK',
// the headers that the server responded with
headers: {},
// the config that was provided to axios for the request
config: {},
// the request that generated the response
request: {},
// the response that was provided by the server
data: {}
}
- constructor(token, service_id)
Method for creating and initializing a new fastly-promises instance.
Example:
const fastly = require('fastly-promises');
// create one or more instances
const instance = fastly('token', 'service_id');
Kind: method
Param: token {string} The Fastly API token.
Param: service_id {string} The Fastly service ID.
Return: instance {object} A new fastly-promises instance.
The main entry point for the Fastly API.
Example:
// read/write baseURL property
console.log(instance.request.defaults.baseURL); // https://api.fastly.com
// in case the fastly api main entry point changes one day
instance.request.defaults.baseURL = 'https://api.fastly.com/v1';
Kind: property
Return: url {string} The main entry point for the Fastly API.
The number of milliseconds before the request times out.
Example:
// read/write timeout property
console.log(instance.request.defaults.timeout); // 3000
instance.request.defaults.timeout = 5000;
Kind: property
Return: milliseconds {number} The number of milliseconds before the request times out.
Instant Purge an individual URL.
Example:
instance.purgeIndividual('www.example.com')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: url {string} The URL to purge.
Return: schema {promise} The response object representing the completion or failure.
Instant Purge everything from a service.
Example:
instance.purgeAll()
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Return: schema {promise} The response object representing the completion or failure.
Instant Purge a particular service of items tagged with a Surrogate Key.
Example:
instance.purgeKey('key_1')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: key {string} The surrogate key to purge.
Return: schema {promise} The response object representing the completion or failure.
Instant Purge a particular service of items tagged with Surrogate Keys in a batch.
Example:
instance.purgeKeys(['key_2', 'key_3', 'key_4'])
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: keys {array} The array of surrogate keys to purge.
Return: schema {promise} The response object representing the completion or failure.
Soft Purge an individual URL.
Example:
instance.softPurgeIndividual('www.example.com/images')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: url {string} The URL to soft purge.
Return: schema {promise} The response object representing the completion or failure.
Soft Purge a particular service of items tagged with a Surrogate Key.
Example:
instance.softPurgeKey('key_5')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: key {string} The surrogate key to soft purge.
Return: schema {promise} The response object representing the completion or failure.
Get a list of all Fastly datacenters.
Example:
instance.dataCenters()
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Return: schema {promise} The response object representing the completion or failure.
Fastly's services IP ranges.
Example:
instance.publicIpList()
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Return: schema {promise} The response object representing the completion or failure.
Retrieve headers and MD5 hash of the content for a particular URL from each Fastly edge server.
Example:
instance.edgeCheck('api.example.com')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: url {string} Full URL (host and path) to check on all nodes. If protocol is omitted, http will be assumed.
Return: schema {promise} The response object representing the completion or failure.
Get a specific service by id.
Example:
instance.readService()
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Return: schema {promise} The response object representing the completion or failure.
List all services.
Example:
instance.readServices()
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Return: schema {promise} The response object representing the completion or failure.
List the versions for a particular service.
Example:
instance.readVersions()
.then(res => {
const active = res.data.filter(version => version.active);
console.log(active);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Return: schema {promise} The response object representing the completion or failure.
Clone the current configuration into a new version.
Example:
instance.cloneVersion('45')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: version {string} The version to be cloned.
Return: schema {promise} The response object representing the completion or failure.
Activate the current version.
Example:
instance.activateVersion('23')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: version {string} The version to be activated.
Return: schema {promise} The response object representing the completion or failure.
Checks the status of all domains for a particular service and version.
Example:
instance.domainCheckAll('182')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: version {string} The current version of a service.
Return: schema {promise} The response object representing the completion or failure.
List all the domains for a particular service and version.
Example:
instance.readDomains('182')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: version {string} The current version of a service.
Return: schema {promise} The response object representing the completion or failure.
List all backends for a particular service and version.
Example:
instance.readBackends('12')
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: version {string} The current version of a service.
Return: schema {promise} The response object representing the completion or failure.
Update the backend for a particular service and version.
Example:
instance.updateBackend('34', 'slow-server', { name: 'fast-server' })
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: version {string} The current version of a service.
Param: name {string} The name of the backend.
Param: data {object} The data to be sent as the request body.
Return: schema {promise} The response object representing the completion or failure.
Create a snippet for a particular service and version.
Example:
instance.createSnippet('36', {
name: 'your_snippet',
priority: 10,
dynamic: 1,
content: 'table referer_blacklist {}',
type: 'init'
})
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.message);
});
Kind: method
Param: version {string} The current version of a service.
Param: data {object} The data to be sent as the request body.
Return: schema {promise} The response object representing the completion or failure.
To run the test suite, first install the dependencies, then run the npm test
command:
$ npm install
$ npm test
PRs accepted. I am open to suggestions in improving this library. Commit by:
$ npm run commit
Licensed under the MIT License © 2017 Philipp Schulte