Add a "unsignedUrls" option to the GCS persistor

This boolean option disables URL signing. Instead, getRedirectUrl()
returns the plain GCS download URL.
This commit is contained in:
Eric Mc Sween 2020-09-22 15:59:13 -04:00
parent 2574b16116
commit 9089d332ab
3 changed files with 35 additions and 7 deletions

View file

@ -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

View file

@ -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)

View file

@ -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 return the url', function () {
expect(signedUrl).to.equal(redirectUrl)
})
})
it('should request a signed URL', function () {
expect(GcsFile.getSignedUrl).to.have.been.called
})
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 the url', function () {
expect(signedUrl).to.equal(redirectUrl)
it('should return a plain URL', function () {
expect(signedUrl).to.equal(
`http://custom.endpoint/download/storage/v1/b/${bucket}/o/${key}?alt=media`
)
})
})
})