问题
I have been trying to debug a Google Cloud Function that should return a signedUrl for uploading a file to Google Cloud Storage.
I have an https cloud function:
exports.gcpSecureURL = functions.https.onCall((data, res) => {
const bucketName = data.bucket;
const fileName = data.filename;
let signedUrl = generateV4UploadSignedUrl(bucketName, fileName)
.then(value => {
console.log("VALUE: ", value);
return value
})
res.send(signedUrl)
});
Value is never reached and signedUrl is always a Promise.
In the generateV4UploadSignedUrl function I have:
async function generateV4UploadSignedUrl(bucketName, fileName) {
// These options will allow temporary uploading of the file with outgoing
// Content-Type: application/octet-stream header.
const options = {
version: 'v4',
action: 'write',
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
contentType: 'application/octet-stream',
};
// Get a v4 signed URL for uploading file
const [url] = await storage
.bucket(bucketName)
.file(fileName)
.getSignedUrl(options)
return url;
};
The param bucketName is correct and fileName is just the name of the file I want to upload so at the stage where I generate the url should not matter?
I don't get why the signedUrl() method is not returning anything at all. I changed the permission on my bucket to StorageAdmin for AllUsers and my function is set to allow unauthenticated.
There is a TypeError in generateV4UploadSignedUrl in the cloud function logs:
TypeError: (intermediate value) is not iterable
at generateV4UploadSignedUrl (/workspace/index.js:51:19)
I have no idea what is happening and the function logs seem pretty opaque. What am I doing wrong please?
回答1:
You have two problems here.
First, you're using a callable type function, but you appear to be using it as if you are writing an HTTP function. If you want to write a callable function, please be sure to review the documentation for that. They work differently than HTTP functions. With callable functions, you must return a promise with the data to send to the caller. With HTTP functions, you invoke res.send()
or equivalent to send a response after all the async work is complete. Be sure you understand the difference between the two.
Value is never reached and signedUrl is always a Promise.
signedUrl
is always a promise because generateV4UploadSignedUrl
is async
, and all async
functions always return a promise. You will have to await the promise to get the resolved value from the promise.
Your function should use async/await, and look more like this:
exports.gcpSecureURL = functions.https.onCall(async (data, context) => {
const bucketName = data.bucket;
const fileName = data.filename;
let signedUrl = await generateV4UploadSignedUrl(bucketName, fileName)
console.log("VALUE: ", signedUrl);
return signedUrl
});
While this might not do exactly what you want (be sure that the entire contents of signedUrl
is what you want to send to the client), it should get you closer to what you want.
来源:https://stackoverflow.com/questions/62817559/cant-resolve-getsignedurl-promise-in-cloud-function