|
1 | 1 | const nodeFetch = require('node-fetch'); |
2 | | -const AWS = require('aws-sdk'); |
| 2 | +const { SignatureV4 } = require('@aws-sdk/signature-v4'); |
| 3 | +const { HttpRequest } = require('@aws-sdk/protocol-http'); |
| 4 | +const { Sha256 } = require('@aws-crypto/sha256-js'); |
3 | 5 | const xml2js = require('xml2js'); |
| 6 | +const { URL } = require('url'); |
4 | 7 | const { getCredentials } = require('../support/credentials'); |
5 | 8 |
|
6 | 9 | const { config } = require('../../../../../lib/Config'); |
7 | 10 |
|
8 | 11 | const skipIfRateLimitDisabled = config.rateLimiting.enabled ? describe : describe.skip; |
9 | 12 |
|
| 13 | +function buildHttpRequest(method, host, rawPath, body = '') { |
| 14 | + const endpoint = new URL(`http://${host}`); |
| 15 | + const target = new URL(rawPath, `http://${host}`); |
| 16 | + |
| 17 | + const query = {}; |
| 18 | + target.searchParams.forEach((value, key) => { |
| 19 | + if (Object.prototype.hasOwnProperty.call(query, key)) { |
| 20 | + const current = query[key]; |
| 21 | + query[key] = Array.isArray(current) ? current.concat(value) : [current, value]; |
| 22 | + } else { |
| 23 | + query[key] = value ?? ''; |
| 24 | + } |
| 25 | + }); |
| 26 | + |
| 27 | + const request = new HttpRequest({ |
| 28 | + method: method.toUpperCase(), |
| 29 | + protocol: endpoint.protocol, |
| 30 | + hostname: endpoint.hostname, |
| 31 | + port: endpoint.port ? Number(endpoint.port) : undefined, |
| 32 | + path: target.pathname, |
| 33 | + query: Object.keys(query).length ? query : undefined, |
| 34 | + headers: { |
| 35 | + host, |
| 36 | + }, |
| 37 | + body: body || undefined, |
| 38 | + }); |
| 39 | + |
| 40 | + return { request, target }; |
| 41 | +} |
| 42 | + |
10 | 43 | async function sendRateLimitRequest(method, host, path, body = '') { |
11 | | - const service = 's3'; |
12 | | - const endpoint = new AWS.Endpoint(host); |
13 | | - |
14 | | - const request = new AWS.HttpRequest(endpoint); |
15 | | - request.method = method.toUpperCase(); |
16 | | - request.path = path; |
17 | | - request.body = body; |
18 | | - request.headers.Host = host; |
19 | | - request.headers['X-Amz-Date'] = new Date().toISOString().replace(/[:\-]|\.\d{3}/g, ''); |
20 | | - const sha256hash = AWS.util.crypto.sha256(request.body || '', 'hex'); |
21 | | - request.headers['X-Amz-Content-SHA256'] = sha256hash; |
22 | | - request.region = 'us-east-1'; |
23 | | - |
24 | | - const signer = new AWS.Signers.V4(request, service); |
| 44 | + const { request, target } = buildHttpRequest(method, host, path, body); |
| 45 | + |
25 | 46 | const credentials = getCredentials('lisa'); |
26 | | - const awsCredentials = new AWS.Credentials( |
27 | | - credentials.accessKeyId, |
28 | | - credentials.secretAccessKey |
29 | | - ); |
30 | | - signer.addAuthorization(awsCredentials, new Date()); |
| 47 | + const signer = new SignatureV4({ |
| 48 | + credentials, |
| 49 | + region: 'us-east-1', |
| 50 | + service: 's3', |
| 51 | + sha256: Sha256, |
| 52 | + }); |
| 53 | + const signedRequest = await signer.sign(request); |
31 | 54 |
|
32 | | - const url = `http://${host}${path}`; |
| 55 | + const url = target.href; |
33 | 56 | const options = { |
34 | | - method: request.method, |
35 | | - headers: request.headers, |
| 57 | + method: signedRequest.method, |
| 58 | + headers: signedRequest.headers, |
36 | 59 | }; |
37 | 60 |
|
38 | | - if (method !== 'GET' && method !== 'DELETE') { |
39 | | - options.body = request.body; |
| 61 | + if (signedRequest.body && method !== 'GET' && method !== 'DELETE') { |
| 62 | + options.body = signedRequest.body; |
40 | 63 | } |
41 | 64 |
|
42 | 65 | const response = await nodeFetch(url, options); |
|
0 commit comments