aws4fetch
A compact (6.4kb minified, 2.5kb gzipped) AWS client for environments that support
fetch
and
SubtleCrypto
โ that is, modern web browsers and
JS platforms like Cloudflare Workers. Also retries
requests with an exponential backoff with full jitter
strategy by default.
Example
import { AwsClient } from 'aws4fetch'
// https://developers.cloudflare.com/workers/reference/apis/environment-variables/#secrets
const aws = new AwsClient({ accessKeyId: MY_ACCESS_KEY, secretAccessKey: MY_SECRET_KEY })
// https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html
const LAMBDA_FN_API = 'https://lambda.us-east-1.amazonaws.com/2015-03-31/functions'
async function invokeMyLambda(event) {
const res = await aws.fetch(`${LAMBDA_FN_API}/my-lambda/invocations`, { body: JSON.stringify(event) })
// `res` is a standard Response object: https://developer.mozilla.org/en-US/docs/Web/API/Response
return res.json()
}
invokeMyLambda({my: 'event'}).then(json => console.log(json))
You can see a more detailed example, a Cloudflare Worker script you can use as
a replacement for API Gateway, in the example
directory.
API
aws4fetch
exports two classes: AwsClient
and AwsV4Signer
new AwsClient(options)
You can use the same instance of AwsClient
for all your service calls as the service and region will be determined
at fetch time โ or you can create separate instances if you have different needs, eg no retrying for some service.
import { AwsClient } from 'aws4fetch'
const aws = new AwsClient({
accessKeyId, // required, akin to AWS_ACCESS_KEY_ID
secretAccessKey, // required, akin to AWS_SECRET_ACCESS_KEY
sessionToken, // akin to AWS_SESSION_TOKEN if using temp credentials
service, // AWS service, by default parsed at fetch time
region, // AWS region, by default parsed at fetch time
cache, // credential cache, defaults to `new Map()`
retries, // number of retries before giving up, defaults to 10, set to 0 for no retrying
initRetryMs, // defaults to 50 โย timeout doubles each retry
})
Promise<Response> aws.fetch(input[, init])
Has the same signature as the global fetch function
import { AwsClient } from 'aws4fetch'
const aws = new AwsClient(opts)
async function doFetch() {
const response = await aws.fetch(url, {
method, // if not supplied, will default to 'POST' if there's a body, otherwise 'GET'
headers, // standard JS object literal, or Headers instance
body, // optional, String or ArrayBuffer/ArrayBufferView โ ie, remember to stringify your JSON
// and any other standard fetch options, eg keepalive, etc
// optional, largely if you want to override options in the AwsClient instance
aws: {
signQuery, // set to true to sign the query string instead of the Authorization header
accessKeyId, // same as in AwsClient constructor above
secretAccessKey, // same as in AwsClient constructor above
sessionToken, // same as in AwsClient constructor above
service, // same as in AwsClient constructor above
region, // same as in AwsClient constructor above
cache, // same as in AwsClient constructor above
datetime, // defaults to now, to override use the form '20150830T123600Z'
appendSessionToken, // set to true to add X-Amz-Security-Token after signing, defaults to true for iot
allHeaders, // set to true to force all headers to be signed instead of the defaults
singleEncode, // set to true to only encode %2F once (usually only needed for testing)
},
})
console.log(await response.json())
}
NB: Due to the way bodies are handled in Request
instances, it's faster to invoke the function as above โ using a URL as the input
argument and passing the body
in the init
argument โ instead of the form of
invocation that uses a Request
object directly as input
.
If you don't know which URL to call for the AWS service you want, the full list of AWS endpoints can be found here: https://docs.aws.amazon.com/general/latest/gr/rande.html
And the APIs are documented here: https://docs.aws.amazon.com/ (the REST APIs are usually documented under "API Reference" for each service)
Promise<Request> aws.sign(input[, init])
Returns a Promise that resolves to an
AWS4
signed Request
โ
has the same signature as fetch
. Use this to create a Request
you can send
using fetch()
yourself.
import { AwsClient } from 'aws4fetch'
const aws = new AwsClient(opts)
async function doFetch() {
const request = await aws.sign(url, {
method, // if not supplied, will default to 'POST' if there's a body, otherwise 'GET'
headers, // standard JS object literal, or Headers instance
body, // optional, String or ArrayBuffer/ArrayBufferView โ ie, remember to stringify your JSON
// and any other standard fetch options, eg keepalive, etc
// optional, largely if you want to override options in the AwsClient instance
aws: {
signQuery, // set to true to sign the query string instead of the Authorization header
accessKeyId, // same as in AwsClient constructor above
secretAccessKey, // same as in AwsClient constructor above
sessionToken, // same as in AwsClient constructor above
service, // same as in AwsClient constructor above
region, // same as in AwsClient constructor above
cache, // same as in AwsClient constructor above
datetime, // defaults to now, to override use the form '20150830T123600Z'
appendSessionToken, // set to true to add X-Amz-Security-Token after signing, defaults to true for iot
allHeaders, // set to true to force all headers to be signed instead of the defaults
singleEncode, // set to true to only encode %2F once (usually only needed for testing)
},
})
const response = await fetch(request)
console.log(await response.json())
}
new AwsV4Signer(options)
The underlying signing class for a request โย use this if you just want to deal with the raw AWS4 signed method/url/headers/body.
import { AwsV4Signer } from 'aws4fetch'
const signer = new AwsV4Signer({
url, // required, the AWS endpoint to sign
accessKeyId, // required, akin to AWS_ACCESS_KEY_ID
secretAccessKey, // required, akin to AWS_SECRET_ACCESS_KEY
sessionToken, // akin to AWS_SESSION_TOKEN if using temp credentials
method, // if not supplied, will default to 'POST' if there's a body, otherwise 'GET'
headers, // standard JS object literal, or Headers instance
body, // optional, String or ArrayBuffer/ArrayBufferView โ ie, remember to stringify your JSON
signQuery, // set to true to sign the query string instead of the Authorization header
service, // AWS service, by default parsed at fetch time
region, // AWS region, by default parsed at fetch time
cache, // credential cache, defaults to `new Map()`
datetime, // defaults to now, to override use the form '20150830T123600Z'
appendSessionToken, // set to true to add X-Amz-Security-Token after signing, defaults to true for iot
allHeaders, // set to true to force all headers to be signed instead of the defaults
singleEncode, // set to true to only encode %2F once (usually only needed for testing)
})
Promise<{ method, url, headers, body }> signer.sign()
Actually perform the signing of the request and return a Promise that resolves to an object containing the signed method, url, headers and body.
method
will be a String
, url
will be an instance of URL
,
headers
will be an instance of Headers
and
body
will unchanged from the argument you supply to the constructor.
import { AwsV4Signer } from 'aws4fetch'
const signer = new AwsV4Signer(opts)
async function sign() {
const { method, url, headers, body } = await signer.sign()
console.log(method, url, [...headers], body)
}
Promise<String> signer.authHeader()
Returns a Promise that resolves to the signed string to use in the
Authorization
header
Used by the sign()
method โย you shouldn't need to access this directly unless you're constructing your own requests.
Promise<String> signer.signature()
Returns a Promise that resolves to the hex signature
Used by the sign()
method โย you shouldn't need to access this directly unless you're constructing your own requests.
Installation
With npm do:
npm install aws4fetch
Or you can also reference different formats straight from unpkg.com:
https://unpkg.com/[email protected]/dist/aws4fetch.esm.js
OR
https://unpkg.com/[email protected]/dist/aws4fetch.esm.mjs
UMD: