-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(s3): implement putObject (#11513)
- Loading branch information
1 parent
0c43bb3
commit 9efe09a
Showing
11 changed files
with
702 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
export { default } from './listObjectsV2'; | ||
import listObjectsV2Case from './listObjectsV2'; | ||
import putObjectCase from './putObject'; | ||
|
||
export default [...listObjectsV2Case, ...putObjectCase]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
packages/storage/__tests__/AwsClients/S3/cases/putObject.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { putObject } from '../../../../src/AwsClients/S3'; | ||
import { ApiFunctionalTestCase } from '../../testUtils/types'; | ||
import { | ||
defaultConfig, | ||
DEFAULT_RESPONSE_HEADERS, | ||
expectedMetadata, | ||
} from './shared'; | ||
|
||
const putObjectRequest = { | ||
Bucket: 'bucket', | ||
Key: 'key', | ||
Body: 'body', | ||
ServerSideEncryption: 'ServerSideEncryption', | ||
SSECustomerAlgorithm: 'SSECustomerAlgorithm', | ||
SSECustomerKey: 'SSECustomerKey', | ||
SSECustomerKeyMD5: 'SSECustomerKeyMD5', | ||
SSEKMSKeyId: 'SSEKMSKeyId', | ||
ACL: 'public-read', | ||
CacheControl: 'CacheControl', | ||
ContentDisposition: 'ContentDisposition', | ||
ContentEncoding: 'ContentEncoding', | ||
ContentType: 'ContentType', | ||
Expires: new Date('2020-01-01'), | ||
Metadata: { | ||
Param1: 'value 1', | ||
}, | ||
Tagging: 'Tagging', | ||
}; | ||
|
||
const expectedPutObjectRequestHeaders = { | ||
'x-amz-server-side-encryption': 'ServerSideEncryption', | ||
'x-amz-server-side-encryption-customer-algorithm': 'SSECustomerAlgorithm', | ||
'x-amz-server-side-encryption-customer-key': 'SSECustomerKey', | ||
'x-amz-server-side-encryption-customer-key-md5': 'SSECustomerKeyMD5', | ||
'x-amz-server-side-encryption-aws-kms-key-id': 'SSEKMSKeyId', | ||
'x-amz-acl': 'public-read', | ||
'cache-control': 'CacheControl', | ||
'content-disposition': 'ContentDisposition', | ||
'content-encoding': 'ContentEncoding', | ||
'content-type': 'ContentType', | ||
expires: 'Wed, 01 Jan 2020 00:00:00 GMT', | ||
'x-amz-tagging': 'Tagging', | ||
'x-amz-meta-param1': 'value 1', | ||
}; | ||
|
||
const putObjectHappyCase: ApiFunctionalTestCase<typeof putObject> = [ | ||
'happy case', | ||
'putObject', | ||
putObject, | ||
defaultConfig, | ||
putObjectRequest, | ||
expect.objectContaining({ | ||
url: expect.objectContaining({ | ||
href: 'https://bucket.s3.us-east-1.amazonaws.com/key', | ||
}), | ||
headers: expect.objectContaining(expectedPutObjectRequestHeaders), | ||
body: 'body', | ||
}), | ||
{ | ||
status: 200, | ||
headers: { | ||
...DEFAULT_RESPONSE_HEADERS, | ||
'x-amz-version-id': 'versionId', | ||
etag: 'etag', | ||
}, | ||
body: '', | ||
}, | ||
{ | ||
$metadata: expect.objectContaining(expectedMetadata), | ||
ETag: 'etag', | ||
VersionId: 'versionId', | ||
}, | ||
]; | ||
|
||
export default [putObjectHappyCase]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
export const EMPTY_SHA256 = | ||
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'; | ||
|
||
export const MOCK_REQUEST_ID = 'requestId'; | ||
export const MOCK_EXTENDED_REQUEST_ID = 'requestId2'; | ||
export const DEFAULT_RESPONSE_HEADERS = { | ||
'x-amz-id-2': MOCK_EXTENDED_REQUEST_ID, | ||
'x-amz-request-id': MOCK_REQUEST_ID, | ||
}; | ||
|
||
export const expectedMetadata = { | ||
attempts: 1, | ||
requestId: MOCK_REQUEST_ID, | ||
extendedRequestId: MOCK_EXTENDED_REQUEST_ID, | ||
httpStatusCode: 200, | ||
}; | ||
|
||
export const defaultConfig = { | ||
region: 'us-east-1', | ||
credentials: { | ||
accessKeyId: 'key', | ||
secretAccessKey: 'secret', | ||
}, | ||
}; | ||
|
||
export const defaultRequiredRequestHeaders = { | ||
authorization: expect.stringContaining('Signature'), | ||
host: 'bucket.s3.us-east-1.amazonaws.com', | ||
'x-amz-content-sha256': EMPTY_SHA256, | ||
'x-amz-date': expect.stringMatching(/^\d{8}T\d{6}Z/), | ||
'x-amz-user-agent': expect.stringContaining('aws-amplify'), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { | ||
Endpoint, | ||
HttpRequest, | ||
HttpResponse, | ||
parseMetadata, | ||
} from '@aws-amplify/core/internals/aws-client-utils'; | ||
import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; | ||
|
||
import { defaultConfig } from './base'; | ||
import type { PutObjectCommandInput, PutObjectCommandOutput } from './types'; | ||
import { | ||
map, | ||
parseXmlError, | ||
s3TransferHandler, | ||
serializeObjectConfigsToHeaders, | ||
} from './utils'; | ||
import type { S3ProviderPutConfig } from '../../types'; | ||
|
||
/** | ||
* Reference: {@link S3ProviderPutConfig} | ||
*/ | ||
export type PutObjectInput = Pick< | ||
PutObjectCommandInput, | ||
| 'Bucket' | ||
| 'Key' | ||
| 'Body' | ||
| 'ServerSideEncryption' | ||
| 'SSECustomerAlgorithm' | ||
| 'SSECustomerKey' | ||
| 'SSECustomerKeyMD5' | ||
| 'SSEKMSKeyId' | ||
| 'ACL' | ||
| 'CacheControl' | ||
| 'ContentDisposition' | ||
| 'ContentEncoding' | ||
| 'ContentType' | ||
| 'Expires' | ||
| 'Metadata' | ||
| 'Tagging' | ||
>; | ||
|
||
export type PutObjectOutput = Pick< | ||
PutObjectCommandOutput, | ||
// PutObject output is not exposed in public API, but only logged in the debug mode | ||
// so we only expose $metadata, ETag and VersionId for debug purpose. | ||
'$metadata' | 'ETag' | 'VersionId' | ||
>; | ||
|
||
const putObjectSerializer = ( | ||
input: PutObjectInput, | ||
endpoint: Endpoint | ||
): HttpRequest => { | ||
const headers = serializeObjectConfigsToHeaders(input); | ||
const url = new URL(endpoint.url.toString()); | ||
url.hostname = `${input.Bucket}.${url.hostname}`; | ||
url.pathname = `/${input.Key}`; | ||
return { | ||
method: 'PUT', | ||
headers, | ||
url, | ||
body: input.Body, | ||
}; | ||
}; | ||
|
||
const putObjectDeserializer = async ( | ||
response: HttpResponse | ||
): Promise<PutObjectOutput> => { | ||
if (response.statusCode >= 300) { | ||
const error = await parseXmlError(response); | ||
throw error; | ||
} else { | ||
return { | ||
...map(response.headers, { | ||
ETag: 'etag', | ||
VersionId: 'x-amz-version-id', | ||
}), | ||
$metadata: parseMetadata(response), | ||
}; | ||
} | ||
}; | ||
|
||
export const putObject = composeServiceApi( | ||
s3TransferHandler, | ||
putObjectSerializer, | ||
putObjectDeserializer, | ||
{ ...defaultConfig, responseType: 'text' } | ||
); |
Oops, something went wrong.