actual code: https://github.com/HenrikJoreteg/google-cloud-signedurl-test-case
I am trying to add the ability of my API to return signed URLs for direct upload to Google Cloud Storage from a client.
Serverside, I use the gcloud SDK for this:
const gcloud = require('gcloud') const gcs = gcloud.storage({ projectId: 'my project', keyFilename: __dirname + '/path/to/JSON/file.json' }) const bucket = gcs.bucket('bucket-name') bucket.file('IMG_2540.png').getSignedUrl({ action: 'write', expires: Date.now() + 60000 }, (error, signedUrl) => { if (error == null) { console.log(signedUrl) } })
Then in the browser I have <input type='file'/> with which I selected the file, then I will try to send it to the URL generated from my server side script as follows:
function upload(blobOrFile, url) { var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.onload = function(e) { console.log('DONE!') }; xhr.upload.onprogress = function(e) { if (e.lengthComputable) { console.log((e.loaded / e.total) * 100) } }; xhr.send(blobOrFile); }
What's happening?
Answer:
<Error> <Code>SignatureDoesNotMatch</Code> <Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message> <StringToSign>PUT image/png 1476631908 /bucket-name/IMG_2540.png</StringToSign> </Error>
I reloaded the JSON key file to make sure it exists and has the appropriate permissions for this bucket, and I don't get any errors or anything when creating the signed URL.
The client code seems to initiate the download correctly (I see that the process updates are complete), then I get the 403 error above. File names match, content types seem to match expected values, expiration time seems reasonable.
The official SDK created the url, so it seems that everything will be alright.
I'm stuck, any help was appreciated.