@cumulus/aws-client
Version:
Utilities for working with AWS
101 lines • 4.77 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const url_1 = require("url");
const uuid_1 = require("uuid");
const client_s3_1 = require("@aws-sdk/client-s3");
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
const logger_1 = __importDefault(require("@cumulus/logger"));
const S3_1 = require("./S3");
const client_1 = __importDefault(require("./client"));
// Code modified from https://github.com/nasa/harmony/blob/main/app/util/object-store.ts
const log = new logger_1.default({ sender: '@cumulus/aws-client/S3ObjectStore' });
const S3_LINK_EXPIRY_SECONDS_DEFAULT = 3600;
/**
* Class to use when interacting with S3
*
*/
class S3ObjectStore {
constructor(config) {
this.s3 = (0, client_1.default)(client_s3_1.S3, '2006-03-01', {
signatureVersion: 'v4',
})(config);
this.queryParams = {};
this.middlewareName = `customQueryParams${(0, uuid_1.v4)()}`;
}
getQueryParams() {
return this.queryParams;
}
setQueryParams(queryParams) {
this.queryParams = queryParams;
}
async getS3SignedUrlWithCustomQueryParams(command, presignOptions = {}) {
this.s3.middlewareStack.addRelativeTo((next) => (args) => {
const { request } = args;
request.query = {
...this.getQueryParams(),
...request.query,
};
return next(args);
}, {
name: this.middlewareName,
relation: 'before',
toMiddleware: 'presignInterceptMiddleware',
});
const signedUrl = await (0, s3_request_presigner_1.getSignedUrl)(this.s3, command, { expiresIn: S3_LINK_EXPIRY_SECONDS_DEFAULT, ...presignOptions });
this.s3.middlewareStack.remove(this.middlewareName);
return signedUrl;
}
/**
* Returns an HTTPS URL that can be used to perform a GET on the given object
* store URL
*
* @param {string} objectUrl - the URL of the object to sign
* @param {string} [options] - options to pass to S3.getObject
* @param {string} [queryParams] - a mapping of parameter key/values to put in the URL
* @param {RequestPresigningArguments} presignOptions - presignOptions
* @returns {Promise<string>} a signed URL
* @throws TypeError - if the URL is not a recognized protocol or cannot be parsed
*/
async signGetObject(objectUrl, options = {}, queryParams = {}, presignOptions = {}) {
log.info(`Executing signGetObject with objectUrl: ${objectUrl}, options: ${JSON.stringify(options)}, queryParams: ${JSON.stringify(queryParams)}`);
const url = new url_1.URL(objectUrl);
if (url.protocol.toLowerCase() !== 's3:') {
throw new TypeError(`Invalid S3 URL: ${objectUrl}`);
}
const { Bucket, Key } = (0, S3_1.parseS3Uri)(objectUrl);
await (0, S3_1.headObject)(Bucket, Key);
const command = new client_s3_1.GetObjectCommand({ Bucket, Key, ...options });
this.setQueryParams(queryParams);
const signedUrl = await this.getS3SignedUrlWithCustomQueryParams(command, presignOptions);
log.debug(`Signed GetObject request URL: ${signedUrl}`);
return signedUrl;
}
/**
* Returns an HTTPS URL that can be used to perform a HEAD on the given object
* store URL
*
* @param {string} objectUrl - the URL of the object to sign
* @param {string} [options] - options to pass to S3.getObject
* @param {string} [queryParams] - a mapping of parameter key/values to put in the URL
* @param {RequestPresigningArguments} presignOptions - presignOptions
* @returns {Promise<string>} a signed URL
* @throws TypeError - if the URL is not a recognized protocol or cannot be parsed
*/
async signHeadObject(objectUrl, options = {}, queryParams, presignOptions = {}) {
log.info(`Executing signHeadObject with objectUrl: ${objectUrl}, options: ${JSON.stringify(options)}, queryParams: ${JSON.stringify(queryParams)}`);
const url = new url_1.URL(objectUrl);
if (url.protocol.toLowerCase() !== 's3:') {
throw new TypeError(`Invalid S3 URL: ${objectUrl}`);
}
const { Bucket, Key } = (0, S3_1.parseS3Uri)(objectUrl);
const command = new client_s3_1.HeadObjectCommand({ Bucket, Key, ...options });
this.setQueryParams(queryParams);
const signedUrl = await this.getS3SignedUrlWithCustomQueryParams(command, presignOptions);
log.debug(`Signed HeadObject request URL: ${signedUrl}`);
return signedUrl;
}
}
module.exports = S3ObjectStore;
//# sourceMappingURL=S3ObjectStore.js.map
;