Skip to content

Instantly share code, notes, and snippets.

@i-like-robots
Created March 17, 2019 11:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save i-like-robots/8913dad2204f95f0d4044b338092a584 to your computer and use it in GitHub Desktop.
Save i-like-robots/8913dad2204f95f0d4044b338092a584 to your computer and use it in GitHub Desktop.
Signed AWS requests with node fetch
const nodeFetch = require('node-fetch');
const httpsAgent = require('./httpsAgent');
const handleResponse = require('./handleResponse');
module.exports = async (url, options = {}) => {
const response = await nodeFetch(url, {
...options,
agent: httpsAgent
});
return handleResponse(response);
};
module.exports = (response) => {
if (response.ok) {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return response.json();
} else {
return response.text();
}
} else {
throw Error(`Request to ${response.url} responded with a ${response.status}`);
}
};
const https = require('https');
module.exports = new https.Agent({ keepAlive: true });
const aws4 = require('aws4');
const { URL } = require('url');
const fetch = require('./fetch');
const resolveCname = require('./resolveCname');
module.exports = async (url, options = {}, credentials = {}) => {
const parsedURL = new URL(url);
// Ensure we sign the actual service URL and not a load balancer URL
const hostname = await resolveCname(parsedURL.host);
const signedOptions = {
method: options.method,
host: hostname,
path: parsedURL.pathname + parsedURL.search,
body: options.body,
headers: options.headers
};
aws4.sign(signedOptions, {
accessKeyId: credentials.awsAccessKey,
secretAccessKey: credentials.awsSecretAccessKey
});
options.headers = signedOptions.headers;
return fetch(`https://${signedOptions.host}${signedOptions.path}`, options);
};
{
"name": "signed-aws-fetch",
"version": "1.0.0",
"description": "",
"engines": {
"node": ">= 8.0.0"
},
"main": "index.js",
"dependencies": {
"aws4": "^1.8.0",
"lru-cache": "^5.1.0",
"node-fetch": "^2.3.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Matt Hinchliffe",
"license": "ISC"
}
const dns = require('dns');
const util = require('util');
const LRU = require('lru-cache');
const cache = new LRU({ maxAge: 1000 * 60, stale: true });
const resolveCname = util.promisify(dns.resolveCname);
module.exports = async (domain) => {
if (/\.amazonaws\.com$/.test(domain)) {
return domain;
}
if (cache.has(domain)) {
return cache.get(domain);
}
const [ resolvedName ] = await resolveCname(domain);
if (resolvedName) {
cache.set(domain, resolvedName);
return resolvedName;
} else {
throw Error(`Could not resolve CNAME for ${domain}`);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment