Skip to content

Commit

Permalink
chore: Add internal getUrl API (#13882)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimblanc authored Oct 3, 2024
1 parent 1c5fc0f commit cced539
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 7 deletions.
75 changes: 75 additions & 0 deletions packages/storage/__tests__/internals/apis/getUrl.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { AmplifyClassV6 } from '@aws-amplify/core';

import { getUrl as advancedGetUrl } from '../../../src/internals';
import { getUrl as getUrlInternal } from '../../../src/providers/s3/apis/internal/getUrl';

jest.mock('../../../src/providers/s3/apis/internal/getUrl');
const mockedGetUrlInternal = jest.mocked(getUrlInternal);

const MOCK_URL = new URL('https://s3.aws/mock-presigned-url');
const MOCK_DATE = new Date();
MOCK_DATE.setMonth(MOCK_DATE.getMonth() + 1);

describe('getUrl (internal)', () => {
beforeEach(() => {
mockedGetUrlInternal.mockResolvedValue({
url: MOCK_URL,
expiresAt: MOCK_DATE,
});
});

afterEach(() => {
jest.clearAllMocks();
});

it('should pass through advanced options to the internal getUrl', async () => {
const useAccelerateEndpoint = true;
const validateObjectExistence = false;
const expiresIn = 300; // seconds
const contentDisposition = 'inline; filename="example.jpg"';
const contentType = 'image/jpeg';
const bucket = { bucketName: 'bucket', region: 'us-east-1' };
const locationCredentialsProvider = async () => ({
credentials: {
accessKeyId: 'akid',
secretAccessKey: 'secret',
sessionToken: 'token',
expiration: new Date(),
},
});
const result = await advancedGetUrl({
path: 'input/path/to/mock/object',
options: {
useAccelerateEndpoint,
bucket,
validateObjectExistence,
expiresIn,
contentDisposition,
contentType,
locationCredentialsProvider,
},
});
expect(mockedGetUrlInternal).toHaveBeenCalledTimes(1);
expect(mockedGetUrlInternal).toHaveBeenCalledWith(
expect.any(AmplifyClassV6),
{
path: 'input/path/to/mock/object',
options: {
useAccelerateEndpoint,
bucket,
validateObjectExistence,
expiresIn,
contentDisposition,
contentType,
locationCredentialsProvider,
},
},
);
expect(result).toEqual({
url: MOCK_URL,
expiresAt: MOCK_DATE,
});
});
});
30 changes: 30 additions & 0 deletions packages/storage/src/internals/apis/getUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { Amplify } from '@aws-amplify/core';

import { getUrl as getUrlInternal } from '../../providers/s3/apis/internal/getUrl';
import { GetUrlInput } from '../types/inputs';
import { GetUrlOutput } from '../types/outputs';

/**
* @internal
*/
export function getUrl(input: GetUrlInput) {
return getUrlInternal(Amplify, {
path: input.path,
options: {
useAccelerateEndpoint: input?.options?.useAccelerateEndpoint,
bucket: input?.options?.bucket,
validateObjectExistence: input?.options?.validateObjectExistence,
expiresIn: input?.options?.expiresIn,
contentDisposition: input?.options?.contentDisposition,
contentType: input?.options?.contentType,

// Advanced options
locationCredentialsProvider: input?.options?.locationCredentialsProvider,
},
// Type casting is necessary because `getPropertiesInternal` supports both Gen1 and Gen2 signatures, but here
// given in input can only be Gen2 signature, the return can only ben Gen2 signature.
}) as Promise<GetUrlOutput>;
}
3 changes: 3 additions & 0 deletions packages/storage/src/internals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ export {
GetDataAccessInput,
ListCallerAccessGrantsInput,
GetPropertiesInput,
GetUrlInput,
CopyInput,
RemoveInput,
} from './types/inputs';
export {
GetDataAccessOutput,
ListCallerAccessGrantsOutput,
GetPropertiesOutput,
GetUrlOutput,
RemoveOutput,
} from './types/outputs';

export { getDataAccess } from './apis/getDataAccess';
export { listCallerAccessGrants } from './apis/listCallerAccessGrants';
export { getProperties } from './apis/getProperties';
export { getUrl } from './apis/getUrl';
export { remove } from './apis/remove';

/*
Expand Down
11 changes: 11 additions & 0 deletions packages/storage/src/internals/types/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import {
CopyWithPathInput,
GetPropertiesWithPathInput,
GetUrlWithPathInput,
RemoveWithPathInput,
} from '../../providers/s3';

Expand Down Expand Up @@ -58,6 +59,16 @@ export type GetPropertiesInput = ExtendInputWithAdvancedOptions<
}
>;

/**
* @internal
*/
export type GetUrlInput = ExtendInputWithAdvancedOptions<
GetUrlWithPathInput,
{
locationCredentialsProvider?: CredentialsProvider;
}
>;

/**
* @internal
*/
Expand Down
6 changes: 6 additions & 0 deletions packages/storage/src/internals/types/outputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import {
GetPropertiesWithPathOutput,
GetUrlWithPathOutput,
RemoveWithPathOutput,
} from '../../providers/s3/types';

Expand All @@ -23,6 +24,11 @@ export type GetDataAccessOutput = LocationCredentials;
*/
export type GetPropertiesOutput = GetPropertiesWithPathOutput;

/**
* @internal
*/
export type GetUrlOutput = GetUrlWithPathOutput;

/**
* @internal
*/
Expand Down
11 changes: 4 additions & 7 deletions packages/storage/src/providers/s3/apis/internal/getUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
import { AmplifyClassV6 } from '@aws-amplify/core';
import { StorageAction } from '@aws-amplify/core/internals/utils';

import {
GetUrlInput,
GetUrlOutput,
GetUrlWithPathInput,
GetUrlWithPathOutput,
} from '../../types';
import { GetUrlInput, GetUrlOutput, GetUrlWithPathOutput } from '../../types';
import { StorageValidationErrorCode } from '../../../../errors/types/validation';
import { getPresignedGetObjectUrl } from '../../utils/client/s3data';
import {
Expand All @@ -23,12 +18,14 @@ import {
STORAGE_INPUT_KEY,
} from '../../utils/constants';
import { constructContentDisposition } from '../../utils/constructContentDisposition';
// TODO: Remove this interface when we move to public advanced APIs.
import { GetUrlInput as GetUrlWithPathInputWithAdvancedOptions } from '../../../../internals';

import { getProperties } from './getProperties';

export const getUrl = async (
amplify: AmplifyClassV6,
input: GetUrlInput | GetUrlWithPathInput,
input: GetUrlInput | GetUrlWithPathInputWithAdvancedOptions,
): Promise<GetUrlOutput | GetUrlWithPathOutput> => {
const { options: getUrlOptions } = input;
const { s3Config, keyPrefix, bucket, identityId } =
Expand Down

0 comments on commit cced539

Please sign in to comment.