From e072af41dfe841fc3539a76fef4c8f6b77ca0296 Mon Sep 17 00:00:00 2001 From: Loren Segal Date: Wed, 10 Dec 2014 11:41:07 -0800 Subject: [PATCH] Add Expect: 100-continue for large payloads in S3 by default. Fixes #135 in conjunction with the managed uploader (AWS.S3.upload) --- lib/http/node.js | 11 ++++++++++- lib/services/s3.js | 12 ++++++++++++ test/services/s3.spec.coffee | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/http/node.js b/lib/http/node.js index 87e5632f37..1b0936ee8a 100644 --- a/lib/http/node.js +++ b/lib/http/node.js @@ -9,6 +9,7 @@ require('../http'); */ AWS.NodeHttpClient = AWS.util.inherit({ handleRequest: function handleRequest(httpRequest, httpOptions, callback, errCallback) { + var self = this; var cbAlreadyCalled = false; var endpoint = httpRequest.endpoint; var pathPrefix = ''; @@ -61,7 +62,15 @@ AWS.NodeHttpClient = AWS.util.inherit({ errCallback.apply(this, arguments); }); - this.writeBody(stream, httpRequest); + var expect = httpRequest.headers.Expect || httpRequest.headers.expect; + if (expect === '100-continue') { + stream.on('continue', function() { + self.writeBody(stream, httpRequest); + }); + } else { + this.writeBody(stream, httpRequest); + } + return stream; }, diff --git a/lib/services/s3.js b/lib/services/s3.js index 52e94287f8..046db7ea18 100644 --- a/lib/services/s3.js +++ b/lib/services/s3.js @@ -30,6 +30,7 @@ AWS.util.update(AWS.S3.prototype, { request.addListener('build', this.computeContentMd5); request.onAsync('build', this.computeSha256); request.addListener('build', this.computeSseCustomerKeyMd5); + request.addListener('afterBuild', this.addExpect100Continue); request.removeListener('validate', AWS.EventListeners.Core.VALIDATE_REGION); request.addListener('extractError', this.extractError); @@ -101,6 +102,17 @@ AWS.util.update(AWS.S3.prototype, { } }, + /** + * Adds Expect: 100-continue header if payload is greater-or-equal 1MB + * @api private + */ + addExpect100Continue: function addExpect100Continue(req) { + var len = req.httpRequest.headers['Content-Length']; + if (AWS.util.isNode() && len >= 1024 * 1024) { + req.httpRequest.headers['Expect'] = '100-continue'; + } + }, + /** * Adds a default content type if none is supplied. * diff --git a/test/services/s3.spec.coffee b/test/services/s3.spec.coffee index 3defd0763c..6ea2f073a5 100644 --- a/test/services/s3.spec.coffee +++ b/test/services/s3.spec.coffee @@ -114,6 +114,23 @@ describe 'AWS.S3', -> req = build('listObjects', { Bucket: 'bucket', MaxKeys:123 }) expect(req.path).to.equal('/?max-keys=123') + describe 'adding Expect: 100-continue', -> + if AWS.util.isNode() + it 'does not add expect header to payloads less than 1MB', -> + req = build('putObject', Bucket: 'bucket', Key: 'key', Body: new Buffer(1024 * 1024 - 1)) + expect(req.headers['Expect']).not.to.exist + + it 'adds expect header to payloads greater than 1MB', -> + req = build('putObject', Bucket: 'bucket', Key: 'key', Body: new Buffer(1024 * 1024 + 1)) + expect(req.headers['Expect']).to.equal('100-continue') + + if AWS.util.isBrowser() + beforeEach -> helpers.spyOn(AWS.util, 'isBrowser').andReturn(true) + + it 'does not add expect header in the browser', -> + req = build('putObject', Bucket: 'bucket', Key: 'key', Body: new Buffer(1024 * 1024 + 1)) + expect(req.headers['Expect']).not.to.exist + describe 'adding Content-Type', -> beforeEach -> helpers.spyOn(AWS.util, 'isBrowser').andReturn(true)