• Stars
    star
    405
  • Rank 104,574 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A compact AWS client for modern JS environments

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:

ES Modules:

https://unpkg.com/[email protected]/dist/aws4fetch.esm.js

OR

https://unpkg.com/[email protected]/dist/aws4fetch.esm.mjs

UMD:

https://unpkg.com/[email protected]/dist/aws4fetch.umd.js

CommonJS:

https://unpkg.com/[email protected]/dist/aws4fetch.cjs.js

More Repositories

1

alpine-node

Minimal Node.js Docker Images built on Alpine Linux
Dockerfile
2,452
star
2

react-server-example

A simple example of how to do server-side rendering with React (no compilation needed)
JavaScript
1,792
star
3

kinesalite

An implementation of Amazon's Kinesis built on LevelDB
JavaScript
796
star
4

aws4

Signs and prepares Node.js requests using AWS Signature Version 4
JavaScript
663
star
5

react-server-routing-example

An example using universal client/server routing and data in React with AWS DynamoDB
JavaScript
299
star
6

simple-relay-starter

A very simple starter for React Relay using Browserify
JavaScript
156
star
7

kinesis

A Node.js stream implementation of Amazon's Kinesis
JavaScript
149
star
8

epipebomb

Ignore EPIPE errors when stdout runs through a truncated pipe (such as `head`) in Node.js
JavaScript
63
star
9

awscred

Node.js module to resolve AWS credentials/region using env, ini files and IAM roles
JavaScript
45
star
10

gelf-stream

A node.js stream to send JS objects to a Graylog2 server (in GELF format)
JavaScript
28
star
11

StringStream

Encode and decode streams into string streams in node.js
JavaScript
27
star
12

dynamo-table

A lightweight module to map JS objects and queries to DynamoDB tables
JavaScript
24
star
13

gelfling

Create and send GELF (Graylog2) messages in node.js, including chunking
JavaScript
8
star
14

awslogger

A CLI tool to send lines from stdin to AWS CloudWatch Logs
JavaScript
7
star
15

aws2

Signs and prepares node.js http(s) requests using AWS Signature Version 2
JavaScript
6
star
16

deep_learning_glossary

Simple, opinionated explanations of various things encountered in Deep Learning
6
star
17

pdf2png-demo

A demo of Container Image Support in AWS Lambda
Go
6
star
18

test-ci-project

Shell
2
star
19

aws3

Signs and prepares node.js http(s) requests using AWS Signature Version 3
JavaScript
1
star