From 91ae4731c38ebafd59f09daf1ec392eecbffcb41 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Mon, 11 May 2015 00:23:28 +0200 Subject: [PATCH 1/4] storage: add response-content-type and response-content-disposition parameters to signed url --- lib/storage/file.js | 26 ++++++++++++++++++++++++-- test/storage/file.js | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/storage/file.js b/lib/storage/file.js index ed210a54af2..f0793d3984f 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -1019,12 +1019,18 @@ File.prototype.getSignedPolicy = function(options, callback) { * link will expire. * @param {string=} options.extensionHeaders - If these headers are used, the * server will check to make sure that the client provides matching values. + * @param {string=} options.responseDisposition - If you provide this value, + * the response-content-disposition parameter of the signed url is set + * accordingly. + * @param {string=} options.responseType - If you provide this value, the + * response-content-type parameter of the signed url is set accordingly. * @param {function=} callback - The callback function. * * @example * file.getSignedUrl({ * action: 'read', - * expires: Math.round(Date.now() / 1000) + (60 * 60 * 24 * 14) // 2 weeks. + * expires: Math.round(Date.now() / 1000) + (60 * 60 * 24 * 14), // 2 weeks. + * responseDisposition: 'attachment; filename="filename.ext"' * }, function(err, url) {}); */ File.prototype.getSignedUrl = function(options, callback) { @@ -1060,11 +1066,27 @@ File.prototype.getSignedUrl = function(options, callback) { ].join('\n')); var signature = sign.sign(credentials.private_key, 'base64'); + var responseContentType = ''; + if (util.is(options.responseType, 'string')) { + responseContentType = + '&response-content-type=' + + encodeURIComponent(options.responseType); + } + + var responseContentDisposition = ''; + if (util.is(options.responseDisposition, 'string')) { + responseContentDisposition = + '&response-content-disposition=' + + encodeURIComponent(options.responseDisposition); + } + callback(null, [ 'https://storage.googleapis.com' + options.resource, '?GoogleAccessId=' + credentials.client_email, '&Expires=' + options.expires, - '&Signature=' + encodeURIComponent(signature) + '&Signature=' + encodeURIComponent(signature), + responseContentType, + responseContentDisposition ].join('')); }); }; diff --git a/test/storage/file.js b/test/storage/file.js index 619b30193bf..00347fc4ed7 100644 --- a/test/storage/file.js +++ b/test/storage/file.js @@ -1350,6 +1350,30 @@ describe('File', function() { }); }); + it('should add response content disposition parameter', function(done) { + var disposition = 'attachment; filename="fname.ext"'; + directoryFile.getSignedUrl({ + action: 'read', + expires: Math.round(Date.now() / 1000) + 5, + responseDisposition: disposition + }, function(err, signedUrl) { + assert(signedUrl.indexOf(encodeURIComponent(disposition)) > -1); + done(); + }); + }); + + it('should add response content type parameter', function(done) { + var type = 'application/json'; + directoryFile.getSignedUrl({ + action: 'read', + expires: Math.round(Date.now() / 1000) + 5, + responseType: type + }, function(err, signedUrl) { + assert(signedUrl.indexOf(encodeURIComponent(type)) > -1); + done(); + }); + }); + describe('expires', function() { var nowInSeconds = Math.floor(Date.now() / 1000); From 30360868128c2d4b271333c8c5881b2af5fbcbcc Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Mon, 11 May 2015 23:41:51 +0200 Subject: [PATCH 2/4] storage: add promptSaveAs option to getSignedUrl --- lib/storage/file.js | 21 ++++++++++++--- test/storage/file.js | 62 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/lib/storage/file.js b/lib/storage/file.js index f0793d3984f..f473d45a0da 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -1019,9 +1019,13 @@ File.prototype.getSignedPolicy = function(options, callback) { * link will expire. * @param {string=} options.extensionHeaders - If these headers are used, the * server will check to make sure that the client provides matching values. + * @param {string=} options.promptSaveAs - If you provide this value the SaveAs + * prompt will be displayed when accessing the signed url and the file name + * will be set to the provided value. If options.responseDisposition is set + * this option is ignored. * @param {string=} options.responseDisposition - If you provide this value, - * the response-content-disposition parameter of the signed url is set - * accordingly. + * the response-content-disposition parameter (http://goo.gl/yMWxQV) of the + * signed url is set accordingly. * @param {string=} options.responseType - If you provide this value, the * response-content-type parameter of the signed url is set accordingly. * @param {function=} callback - The callback function. @@ -1030,7 +1034,7 @@ File.prototype.getSignedPolicy = function(options, callback) { * file.getSignedUrl({ * action: 'read', * expires: Math.round(Date.now() / 1000) + (60 * 60 * 24 * 14), // 2 weeks. - * responseDisposition: 'attachment; filename="filename.ext"' + * promptSaveAs: 'filename.ext' * }, function(err, url) {}); */ File.prototype.getSignedUrl = function(options, callback) { @@ -1074,7 +1078,18 @@ File.prototype.getSignedUrl = function(options, callback) { } var responseContentDisposition = ''; + if (util.is(options.promptSaveAs, 'string')) { + responseContentDisposition = + '&response-content-disposition=attachment; filename="' + + encodeURIComponent(options.promptSaveAs) + '"'; + } if (util.is(options.responseDisposition, 'string')) { + if (responseContentDisposition !== '') { + console.warn([ + 'getSignedUrl: the promptSaveAs option is ignored', + 'when responseDisposition is provided.' + ].join(' ')); + } responseContentDisposition = '&response-content-disposition=' + encodeURIComponent(options.responseDisposition); diff --git a/test/storage/file.js b/test/storage/file.js index 00347fc4ed7..09960e11603 100644 --- a/test/storage/file.js +++ b/test/storage/file.js @@ -1350,27 +1350,63 @@ describe('File', function() { }); }); - it('should add response content disposition parameter', function(done) { - var disposition = 'attachment; filename="fname.ext"'; + it('should add response-content-type parameter', function(done) { + var type = 'application/json'; directoryFile.getSignedUrl({ action: 'read', expires: Math.round(Date.now() / 1000) + 5, - responseDisposition: disposition + responseType: type }, function(err, signedUrl) { - assert(signedUrl.indexOf(encodeURIComponent(disposition)) > -1); + assert(signedUrl.indexOf(encodeURIComponent(type)) > -1); done(); }); }); - it('should add response content type parameter', function(done) { - var type = 'application/json'; - directoryFile.getSignedUrl({ - action: 'read', - expires: Math.round(Date.now() / 1000) + 5, - responseType: type - }, function(err, signedUrl) { - assert(signedUrl.indexOf(encodeURIComponent(type)) > -1); - done(); + describe('promptSaveAs', function() { + it('should add response-content-disposition', function(done) { + var disposition = 'attachment; filename="fname.ext"'; + directoryFile.getSignedUrl({ + action: 'read', + expires: Math.round(Date.now() / 1000) + 5, + promptSaveAs: 'fname.ext' + }, function(err, signedUrl) { + assert(signedUrl.indexOf(disposition) > -1); + done(); + }); + }); + }); + + describe('responseDisposition', function() { + it('should add response-content-disposition', function(done) { + var disposition = 'attachment; filename="fname.ext"'; + directoryFile.getSignedUrl({ + action: 'read', + expires: Math.round(Date.now() / 1000) + 5, + responseDisposition: disposition + }, function(err, signedUrl) { + assert(signedUrl.indexOf(encodeURIComponent(disposition)) > -1); + done(); + }); + }); + + it('should warn and ignore promptSaveAs if set', function(done) { + var disposition = 'attachment; filename="fname.ext"'; + var saveAs = 'fname2.ext'; + var oldWarn = console.warn; + console.warn = function(message) { + assert(message.indexOf('promptSaveAs') > -1); + console.warn = oldWarn; + }; + directoryFile.getSignedUrl({ + action: 'read', + expires: Math.round(Date.now() / 1000) + 5, + promptSaveAs: saveAs, + responseDisposition: disposition + }, function(err, signedUrl) { + assert(signedUrl.indexOf(encodeURIComponent(disposition)) > -1); + assert(signedUrl.indexOf(encodeURIComponent(saveAs)) === -1); + done(); + }); }); }); From 35aae43f40f1e15faf2426dc38e617d286ae0e99 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Tue, 12 May 2015 16:21:06 +0200 Subject: [PATCH 3/4] storage: update getSignedUrl docs, minor fix in test --- lib/storage/file.js | 17 ++++++++--------- test/storage/file.js | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/storage/file.js b/lib/storage/file.js index f473d45a0da..c1e73dbd13e 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -1019,15 +1019,14 @@ File.prototype.getSignedPolicy = function(options, callback) { * link will expire. * @param {string=} options.extensionHeaders - If these headers are used, the * server will check to make sure that the client provides matching values. - * @param {string=} options.promptSaveAs - If you provide this value the SaveAs - * prompt will be displayed when accessing the signed url and the file name - * will be set to the provided value. If options.responseDisposition is set - * this option is ignored. - * @param {string=} options.responseDisposition - If you provide this value, - * the response-content-disposition parameter (http://goo.gl/yMWxQV) of the - * signed url is set accordingly. - * @param {string=} options.responseType - If you provide this value, the - * response-content-type parameter of the signed url is set accordingly. + * @param {string=} options.promptSaveAs - The filename to prompt the user to + * save the file as when the signed url is accessed. This is ignored if + * options.responseDisposition is set. + * @param {string=} options.responseDisposition - The + * response-content-disposition parameter (http://goo.gl/yMWxQV) of the + * signed url. + * @param {string=} options.responseType - The response-content-type parameter + * of the signed url. * @param {function=} callback - The callback function. * * @example diff --git a/test/storage/file.js b/test/storage/file.js index 09960e11603..a7b4f398820 100644 --- a/test/storage/file.js +++ b/test/storage/file.js @@ -1405,6 +1405,7 @@ describe('File', function() { }, function(err, signedUrl) { assert(signedUrl.indexOf(encodeURIComponent(disposition)) > -1); assert(signedUrl.indexOf(encodeURIComponent(saveAs)) === -1); + assert.equal(console.warn, oldWarn); done(); }); }); From 744a3a11fe4889a0ecfa438faf254d04fde97369 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Tue, 12 May 2015 23:24:44 +0200 Subject: [PATCH 4/4] storage: remove warning log from getSignedUrl --- lib/storage/file.js | 6 ------ test/storage/file.js | 8 +------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/lib/storage/file.js b/lib/storage/file.js index c1e73dbd13e..d64aa09c725 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -1083,12 +1083,6 @@ File.prototype.getSignedUrl = function(options, callback) { encodeURIComponent(options.promptSaveAs) + '"'; } if (util.is(options.responseDisposition, 'string')) { - if (responseContentDisposition !== '') { - console.warn([ - 'getSignedUrl: the promptSaveAs option is ignored', - 'when responseDisposition is provided.' - ].join(' ')); - } responseContentDisposition = '&response-content-disposition=' + encodeURIComponent(options.responseDisposition); diff --git a/test/storage/file.js b/test/storage/file.js index a7b4f398820..9913f3c20e7 100644 --- a/test/storage/file.js +++ b/test/storage/file.js @@ -1389,14 +1389,9 @@ describe('File', function() { }); }); - it('should warn and ignore promptSaveAs if set', function(done) { + it('should ignore promptSaveAs if set', function(done) { var disposition = 'attachment; filename="fname.ext"'; var saveAs = 'fname2.ext'; - var oldWarn = console.warn; - console.warn = function(message) { - assert(message.indexOf('promptSaveAs') > -1); - console.warn = oldWarn; - }; directoryFile.getSignedUrl({ action: 'read', expires: Math.round(Date.now() / 1000) + 5, @@ -1405,7 +1400,6 @@ describe('File', function() { }, function(err, signedUrl) { assert(signedUrl.indexOf(encodeURIComponent(disposition)) > -1); assert(signedUrl.indexOf(encodeURIComponent(saveAs)) === -1); - assert.equal(console.warn, oldWarn); done(); }); });