Introduction#

  • Create signature v4
  • Create request with fetch, axios
  • Parse stream and normal response to file

This is the full script

s3-wo-sdk.js
// create aws credentials from demo profile
import { fromIni } from '@aws-sdk/credential-provider-ini'
import { HttpRequest } from '@aws-sdk/protocol-http'
import { SignatureV4 } from '@smithy/signature-v4'
import { Sha256 } from '@aws-crypto/sha256-js'
import axios from 'axios'
import * as fs from 'fs'
const s3ObjectUrl =
'https://s3.us-east-1.amazonaws.com/$BUCKET/web-css/osaka-street.jpeg'
const getObjectFromS3 = async () => {
// create a http request from @aws/http-protocol
const request = new HttpRequest({
method: 'GET',
protocol: 'https:',
hostname: new URL(s3ObjectUrl).hostname,
path: new URL(s3ObjectUrl).pathname,
headers: {
host: new URL(s3ObjectUrl).hostname
}
})
// load aws credentials from profile
const credentials = fromIni({ profile: 'demo' })
const creds = await credentials.call()
console.log(creds.accessKeyId, creds.secretAccessKey, creds.sessionToken)
// create a signaturev4 signer from smithy/signature-v4
const signer = new SignatureV4({
service: 's3',
region: 'us-east-1',
credentials: {
accessKeyId: creds.accessKeyId,
secretAccessKey: creds.secretAccessKey,
sessionToken: creds.sessionToken
},
sha256: Sha256
})
// sign the request using the signer signature v4
const signed = await signer.sign(request, {})
// axios
// const response = await axios.get(s3ObjectUrl, {
// headers: signed.headers,
// responseType: "arraybuffer",
// });
// fs.writeFileSync("test.jpeg", response.data);
// response.data.pipe(fs.createWriteStream("./hehe.jpg"));
const response = await fetch(s3ObjectUrl, {
headers: signed.headers,
responseType: 'arraybuffer'
})
// write response array buffer to file
// const data = await response.arrayBuffer();
// fs.writeFileSync("test.jpeg", Buffer.from(data));
// streaming chunk by chunk
const reader = response.body.getReader()
const writer = fs.createWriteStream('test.jpeg')
while (true) {
const { done, value } = await reader.read()
if (done) {
break
}
console.log(value)
writer.write(value)
}
reader.releaseLock()
}
const main = async () => {
await getObjectFromS3()
}
main()

And here is package.json

package.json
{
"name": "nodejs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@aws-crypto/sha256-js": "^5.2.0",
"@aws-sdk/credential-provider-ini": "^3.529.1",
"@aws-sdk/protocol-http": "^3.374.0",
"@smithy/signature-v4": "^2.1.4",
"axios": "^1.6.7"
}
}

Create Request#

Let create a HTTPRequest

const s3ObjectUrl =
'https://s3.us-east-1.amazonaws.com/$BUCKET/web-css/osaka-street.jpeg'
const request = new HttpRequest({
method: 'GET',
protocol: 'https:',
hostname: new URL(s3ObjectUrl).hostname,
path: new URL(s3ObjectUrl).pathname,
headers: {
host: new URL(s3ObjectUrl).hostname
}
})

Sign Request#

Let create signature v4 signer

const credentials = fromIni({ profile: 'demo' })
const creds = await credentials.call()
// create a signaturev4 signer from smithy/signature-v4
const signer = new SignatureV4({
service: 's3',
region: 'us-east-1',
credentials: {
accessKeyId: creds.accessKeyId,
secretAccessKey: creds.secretAccessKey,
sessionToken: creds.sessionToken
},
sha256: Sha256
})
// sign the request using the signer signature v4
const signed = await signer.sign(request, {})

Parse Request#

Let send and parse

  • normal response
  • stream response
const response = await fetch(s3ObjectUrl, {
headers: signed.headers,
responseType: 'arraybuffer'
})
const reader = response.body.getReader()
const writer = fs.createWriteStream('test.jpeg')
while (true) {
const { done, value } = await reader.read()
if (done) {
break
}
console.log(value)
writer.write(value)
}
reader.releaseLock()

Referece#

  • s3 GetObject api docs