Ver Fonte

Add a "unsignedUrls" option to the GCS persistor

This boolean option disables URL signing. Instead, getRedirectUrl()
returns the plain GCS download URL.
Eric Mc Sween há 6 anos atrás
pai
commit
9089d332ab

+ 1 - 0
libraries/object-persistor/README.md

@@ -293,6 +293,7 @@ GCS authentication is configured automatically via the local service account, or
 - `gcs.unlockBeforeDelete`: unlock an event-based hold before deleting. default false (see notes)
 - `gcs.deletedBucketSuffix`: if present, copy the object to a bucket with this suffix before deletion (see notes)
 - `gcs.deleteConcurrency`: when recursively deleting a directory, the maximum number of delete requests that will be used at once (default 50)
+- `gcs.unsignedUrls`: For testing - do not sign GCS download URLs
 - `gcs.endpoint.apiEndpoint`: For testing - specify a different GCS endpoint to use
 - `gcs.endpoint.apiScheme`: For testing - specify a scheme to use for the GCS endpoint (`http` or `https`)
 - `gcs.endpoint.projectId`: For testing - the GCS project ID to supply to the overridden backend

+ 8 - 0
libraries/object-persistor/src/GcsPersistor.js

@@ -125,6 +125,14 @@ module.exports = class GcsPersistor extends AbstractPersistor {
   }
 
   async getRedirectUrl(bucketName, key) {
+    if (this.settings.unsignedUrls) {
+      // Construct a direct URL to the object download endpoint
+      // (see https://cloud.google.com/storage/docs/request-endpoints#json-api)
+      const apiScheme = this.settings.endpoint.apiScheme || 'https://'
+      const apiEndpoint =
+        this.settings.endpoint.apiEndpoint || 'storage.googleapis.com'
+      return `${apiScheme}://${apiEndpoint}/download/storage/v1/b/${bucketName}/o/${key}?alt=media`
+    }
     try {
       const [url] = await this.storage
         .bucket(bucketName)

+ 26 - 7
libraries/object-persistor/test/unit/GcsPersistorTests.js

@@ -260,16 +260,35 @@ describe('GcsPersistorTests', function () {
   describe('getRedirectUrl', function () {
     let signedUrl
 
-    beforeEach(async function () {
-      signedUrl = await GcsPersistor.getRedirectUrl(bucket, key)
-    })
+    describe('with signed URLs', function () {
+      beforeEach(async function () {
+        signedUrl = await GcsPersistor.getRedirectUrl(bucket, key)
+      })
 
-    it('should request a signed URL', function () {
-      expect(GcsFile.getSignedUrl).to.have.been.called
+      it('should request a signed URL', function () {
+        expect(GcsFile.getSignedUrl).to.have.been.called
+      })
+
+      it('should return the url', function () {
+        expect(signedUrl).to.equal(redirectUrl)
+      })
     })
 
-    it('should return the url', function () {
-      expect(signedUrl).to.equal(redirectUrl)
+    describe('with unsigned URLs', function () {
+      beforeEach(async function () {
+        GcsPersistor.settings.unsignedUrls = true
+        GcsPersistor.settings.endpoint = {
+          apiScheme: 'http',
+          apiEndpoint: 'custom.endpoint'
+        }
+        signedUrl = await GcsPersistor.getRedirectUrl(bucket, key)
+      })
+
+      it('should return a plain URL', function () {
+        expect(signedUrl).to.equal(
+          `http://custom.endpoint/download/storage/v1/b/${bucket}/o/${key}?alt=media`
+        )
+      })
     })
   })