You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Mar 3, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Mar 3, 2026. It is now read-only.
File uploading does not respect apiEndpoint or the environment variable STORAGE_EMULATOR_HOST. Instead it uses a hardcoded constant STORAGE_UPLOAD_BASE_URL
Environment details
OS: Mac 10.14.6
Node.js version: 12.12.0
npm version: 6.11.3
@google-cloud/storage version: 4.0.0
Reacted by Filip Fabiszak, Julian Fell, Simon Detheridge and Yannick Adam
After a little investigation I can see why it was done this way:
In @google-cloud/common the ServiceObject function request_ builds a uri based on the object id and its parent id. Unless an absolute URL is provided. If the absolute URL wasn't provided in
Thanks for digging into that, and sharing the solution you found! Is STORAGE_EMULATOR_HOST an official env var? That follows the format from Datastore, although unlike Datastore, I haven't found an official Storage API emulator.
@frankyn what is the extent of support we want to provide for this use case?
Would it work if it followed the same creation method as Buckets? ie the bucket.create() method calls the Service.createBucket method. If a File called Bucket.createFile(aka startSimpleUpload_) then when the uri is built inside Bucket.request({ uri: '/o' }) it would end up building the correct url.
@frankyn In our other APIs, options.apiEndpoint and the corresponding emulator environment variable are expected to have the same side effects when set-- everything is appended to that "base" URL.
Currently in Storage, however, the emulator environment variable replaces https://storage.googleapis.com/storage/v1, while options.apiEndpoint only replaces storage.googleapis.com.
Since options.apiEndpoint was designed for the same purpose as the environment variable and STORAGE_EMULATOR_HOST isn't an official environment variable, can we rethink this to have both behave equally?
In any case, what would be the correct URL to send the upload request to:
I think we should keep upload requests at the /upload endpoint, as-per GCS documentation. For the particular use case of fake-gcs-server by @chrisrecalis, this endpoint is supported.
+1 to STORAGE_EMULATOR_HOST mapping to options.apiEndpoint, question is which one should take precedence?
If this can help anyone, the workaround provided will not work with: File.createWriteStream() as it uses startResumableUpload_ instead of startSimpleUpload_.
You can use File.createWriteStream({resumable: false}) in the meantime.
Activity
[-]File upload & downloading don't respect apiEndpoint[/-][+]Simple file upload doesn't respect apiEndpoint[/+]chrisrecalis commentedon Oct 24, 2019
After a little investigation I can see why it was done this way:
In
@google-cloud/commontheServiceObjectfunctionrequest_builds a uri based on the object id and its parent id. Unless an absolute URL is provided. If the absolute URL wasn't provided innodejs-storage/src/file.ts
Lines 3398 to 3403 in f2d567f
The request uri would build to be something like
https://{apiEndpoint}/storage/v1/b/my-bucket/o/myfile.txtwhen trying to upload a filemyfile.txt. Which doesn't conform to https://cloud.google.com/storage/docs/json_api/v1/objects/insert.I've since just used an interceptor instead:
stephenplusplus commentedon Oct 24, 2019
Thanks for digging into that, and sharing the solution you found! Is
STORAGE_EMULATOR_HOSTan official env var? That follows the format from Datastore, although unlike Datastore, I haven't found an official Storage API emulator.@frankyn what is the extent of support we want to provide for this use case?
chrisrecalis commentedon Oct 24, 2019
I'm currently using
fake-gcs-serveras my emulator. The environment variable was dug up in source code:nodejs-storage/src/storage.ts
Lines 375 to 379 in f2d567f
chrisrecalis commentedon Oct 24, 2019
Would it work if it followed the same creation method as
Buckets? ie thebucket.create()method calls theService.createBucketmethod. If aFilecalledBucket.createFile(akastartSimpleUpload_) then when the uri is built insideBucket.request({ uri: '/o' })it would end up building the correct url.frankyn commentedon Oct 24, 2019
@stephenplusplus,
STORAGE_EMULATOR_HOSTenv var was introduced for benchmarking by @jadekler. We don't have an official GCS emulator at the moment.IIUC,
STORAGE_EMULATOR_HOSTshould have the same effect as setting apiEndpoint.stephenplusplus commentedon Oct 24, 2019
Ah, nice, I didn't know that slipped in there. I think we can figure this out. I'll assign to myself and update everyone accordingly for reviews!
stephenplusplus commentedon Oct 29, 2019
@frankyn In our other APIs,
options.apiEndpointand the corresponding emulator environment variable are expected to have the same side effects when set-- everything is appended to that "base" URL.Currently in Storage, however, the emulator environment variable replaces
https://storage.googleapis.com/storage/v1, whileoptions.apiEndpointonly replacesstorage.googleapis.com.Since
options.apiEndpointwas designed for the same purpose as the environment variable andSTORAGE_EMULATOR_HOSTisn't an official environment variable, can we rethink this to have both behave equally?In any case, what would be the correct URL to send the upload request to:
https://${userProvidedOverride}/upload/storage/v1/b/${this.bucket.name}/ohttps://${userProvidedOverride}/b/${this.bucket.name}/o(the/upload/prefix removed, otherwise/storage/v1/is duplicated)Hope this made sense!
jkwlui commentedon Nov 7, 2019
@frankyn let me know if you think otherwise:
I think we should keep upload requests at the
/uploadendpoint, as-per GCS documentation. For the particular use case offake-gcs-serverby @chrisrecalis, this endpoint is supported.+1 to
STORAGE_EMULATOR_HOSTmapping tooptions.apiEndpoint, question is which one should take precedence?yannickadam commentedon Mar 20, 2020
If this can help anyone, the workaround provided will not work with:
File.createWriteStream()as it uses startResumableUpload_ instead of startSimpleUpload_.You can use
File.createWriteStream({resumable: false})in the meantime.