Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/next-release/feature-S3-7c5b7c23.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "feature",
"category": "S3",
"description": "Add an option to enable/disable \"Expect: 100-continue\" headers for large payloads."
}
6 changes: 5 additions & 1 deletion lib/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ export abstract class ConfigurationOptions {
* Whether to disable S3 body signing when using signature version v4.
*/
s3DisableBodySigning?: boolean
/**
* Whether to add "Expect: 100-Continue" HTTP headers when sending large payloads.
*/
s3AddExpect100ContinueHeaders?: boolean
/**
* Whether to force path style URLs for S3 objects.
*/
Expand Down Expand Up @@ -277,7 +281,7 @@ export abstract class ConfigurationOptions {
*/
dynamoDbCrc32?: boolean;
/**
* Whether to enable endpoint discovery for operations that allow optionally using an endpoint returned by
* Whether to enable endpoint discovery for operations that allow optionally using an endpoint returned by
* the service.
*/
endpointDiscoveryEnabled?: boolean;
Expand Down
9 changes: 8 additions & 1 deletion lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ var PromisesDependency;
* @return [Boolean] whether to disable S3 body signing when using signature version `v4`.
* Body signing can only be disabled when using https. Defaults to `true`.
*
* @!attribute s3AddExpect100ContinueHeaders
* @return [Boolean] whether to add "Expect: 100-Continue" HTTP headers when sending large payloads.
* Defaults to `true`.
*
* @!attribute useAccelerateEndpoint
* @note This configuration option is only compatible with S3 while accessing
* dns-compatible buckets.
Expand Down Expand Up @@ -235,7 +239,9 @@ AWS.Config = AWS.util.inherit({
* @option options s3DisableBodySigning [Boolean] whether S3 body signing
* should be disabled when using signature version `v4`. Body signing
* can only be disabled when using https. Defaults to `true`.
*
* @option options s3AddExpect100ContinueHeaders [Boolean] whether
* to add "Expect: 100-Continue" HTTP headers when sending large payloads.
* Defaults to `true`.
* @option options retryDelayOptions [map] A set of options to configure
* the retry delay on retryable errors. Currently supported options are:
*
Expand Down Expand Up @@ -518,6 +524,7 @@ AWS.Config = AWS.util.inherit({
s3ForcePathStyle: false,
s3BucketEndpoint: false,
s3DisableBodySigning: true,
s3AddExpect100ContinueHeaders: true,
computeChecksums: true,
convertResponseTypes: true,
correctClockSkew: false,
Expand Down
12 changes: 11 additions & 1 deletion lib/services/s3.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ AWS.util.update(AWS.S3.prototype, {
return false;
},

/**
* @api private
*/
shouldAddExpect100ContinueHeaders: function shouldAddExpect100ContinueHeaders() {
return this.config.s3AddExpect100ContinueHeaders === true;
},

/**
* @api private
*/
Expand All @@ -110,7 +117,10 @@ AWS.util.update(AWS.S3.prototype, {
request.addListener('build', this.populateURI);
request.addListener('build', this.computeContentMd5);
request.addListener('build', this.computeSseCustomerKeyMd5);
request.addListener('afterBuild', this.addExpect100Continue);
if (this.shouldAddExpect100ContinueHeaders())
{
request.addListener('afterBuild', this.addExpect100Continue);
}
request.removeListener('validate',
AWS.EventListeners.Core.VALIDATE_REGION);
request.addListener('extractError', this.extractError);
Expand Down
18 changes: 9 additions & 9 deletions scripts/region-checker/whitelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var whitelist = {
'/config.js': [
24,
25,
184
188
],
'/credentials/cognito_identity_credentials.js': [
78,
Expand All @@ -27,14 +27,14 @@ var whitelist = {
'/services/s3.js': [
68,
69,
515,
517,
516,
636,
647,
648,
649,
654
525,
527,
526,
646,
657,
658,
659,
664
]
};

Expand Down
6 changes: 6 additions & 0 deletions test/config.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,12 @@ describe('AWS.Config', function() {
});
});

describe('s3AddExpect100ContinueHeaders', function() {
it('defaults to true', function() {
expect(configure().s3AddExpect100ContinueHeaders).to.equal(true);
});
});

describe('set', function() {
it('should set a default value for a key', function() {
var config = new AWS.Config();
Expand Down
61 changes: 60 additions & 1 deletion test/services/s3.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -758,9 +758,13 @@ describe('AWS.S3', function() {
});
});

describe('adding Expect: 100-continue', function() {
describe('with s3AddExpect100ContinueHeaders set to true', function() {
if (AWS.util.isNode()) {
it('does not add expect header to payloads less than 1MB', function() {
s3 = new AWS.S3({
s3AddExpect100ContinueHeaders: true,
signatureVersion: 'v4'
});
var req = build('putObject', {
Bucket: 'bucket',
Key: 'key',
Expand All @@ -770,6 +774,10 @@ describe('AWS.S3', function() {
});

it('adds expect header to payloads greater than 1MB', function() {
s3 = new AWS.S3({
s3AddExpect100ContinueHeaders: true,
signatureVersion: 'v4'
});
var req = build('putObject', {
Bucket: 'bucket',
Key: 'key',
Expand All @@ -785,6 +793,10 @@ describe('AWS.S3', function() {
});

it('does not add expect header in the browser', function() {
s3 = new AWS.S3({
s3AddExpect100ContinueHeaders: true,
signatureVersion: 'v4'
});
var req = build('putObject', {
Bucket: 'bucket',
Key: 'key',
Expand All @@ -794,7 +806,54 @@ describe('AWS.S3', function() {
});
}
});
describe('with s3AddExpect100ContinueHeaders set to false', function() {
if (AWS.util.isNode()) {
it('does not add expect header to payloads less than 1MB', function() {
s3 = new AWS.S3({
s3AddExpect100ContinueHeaders: false,
signatureVersion: 'v4'
});
var req = build('putObject', {
Bucket: 'bucket',
Key: 'key',
Body: new Buffer(1024 * 1024 - 1)
});
expect(req.headers['Expect']).not.to.exist;
});

it('does not add expect header to payloads greater than 1MB', function() {
s3 = new AWS.S3({
s3AddExpect100ContinueHeaders: false,
signatureVersion: 'v4'
});
var req = build('putObject', {
Bucket: 'bucket',
Key: 'key',
Body: new Buffer(1024 * 1024 + 1)
});
expect(req.headers['Expect']).not.to.exist;
});
}

if (AWS.util.isBrowser()) {
beforeEach(function() {
helpers.spyOn(AWS.util, 'isBrowser').andReturn(true);
});

it('does not add expect header in the browser', function() {
s3 = new AWS.S3({
s3AddExpect100ContinueHeaders: false,
signatureVersion: 'v4'
});
var req = build('putObject', {
Bucket: 'bucket',
Key: 'key',
Body: new Buffer(1024 * 1024 + 1)
});
expect(req.headers['Expect']).not.to.exist;
});
}
});
describe('with s3DisableBodySigning set to true', function() {
it('will disable body signing when using signature version 4 and the endpoint uses https', function() {
s3 = new AWS.S3({
Expand Down
3 changes: 2 additions & 1 deletion ts/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ AWS.config.update({
},
s3BucketEndpoint: false,
s3DisableBodySigning: false,
s3AddExpect100ContinueHeaders: true,
s3ForcePathStyle: true,
signatureCache: false,
signatureVersion: 'v4',
Expand All @@ -92,7 +93,7 @@ var config = AWS.config.loadFromPath('/to/path');

// test update allowing unknown keys
AWS.config.update({
fake: 'fake'
fake: 'fake'
}, true);

//Test httpOption interface
Expand Down