Я создаю приложение для Интернета, размещенное на Firebase, где я пытаюсь разрешить неаутентифицированным пользователям загружать изображение в хранилище (после передачи reCAPTCHA).
Для этого у меня есть веб-сайт React и функция Firebase, которая проверяет reCAPTCHA и затем генерирует подписанный URL-адрес для клиентского кода для загрузки изображения в корзину по умолчанию. Я развернул функцию в облаке, потому что нет эмулятора хранилища, который я мог бы использовать для локальной разработки, но мое приложение React обслуживается локально.
В приведенном ниже коде отсутствует обычный шаблон.
Код функции Firebase:
const id = uuidv4()
const bucket = storage.bucket("project-id.appspot.com");
const file = bucket.file(id)
const expires_at = Date.now() + 300000;
const config = {
action: 'write',
version: 'v2',
expires: expires_at,
contentType: 'application/octet-stream'
};
file.getSignedUrl(config, (err, url) => {
if (err) {
console.error(err);
res.status(500).end();
return;
}
res.send(url);
});
Это возвращает URL-адрес клиенту в форме: https://storage.googleapis.com/project-id.appspot.com/db9a5cc5-6540-4f40-933f-cfdb287b15a9?GoogleAccessId=project-id%40appspot.gserviceaccount.com&Expires=1594719835&Signature=<signature here>
Код на стороне клиента :
Как только это получено на стороне клиента, я пытаюсь загрузить файл по этому URL-адресу, используя метод PUT:
// signed_url is the url returned from the first API call to the function above.
// image_file is the file data I get from using react-dropzone.
axios({
method: 'put',
url: signed_url,
data: image_file,
headers: {'Content-Type':'application/octet-stream'}
}).then(res => {
console.log("success");
console.log(res);
}).catch((error) => {
console.log(error);
});
Здесь я получаю ошибку CORS в форме: Access to XMLHttpRequest at 'https://storage.googleapis.com/project-id.appspot.com/db9a5cc5-6540-4f40-933f-cfdb287b15a9?GoogleAccessId=project-id%40appspot.gserviceaccount.com&Expires=1594719835&Signature=<signature here>' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Я использовал cURL, чтобы увидеть, устанавливаются ли заголовки CORS в ответе, а они нет. Затем я использовал gsutil cors set config.json gs://project-id.appspot.com
, чтобы установить разрешения CORS для корзины по умолчанию. Вот формат конфигурации:
[
{
"origin": ["*"],
"responseHeader": [
"Origin",
"Accept",
"x-goog-resumable",
"Content-Type",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Headers",
"Authorization",
"X-Requested-With"
],
"method": ["GET, POST, PUT, PATCH, POST, DELETE, OPTIONS"],
"maxAgeSeconds": 3600
}
]
Я проверил учетную запись службы, чтобы убедиться, что у них есть разрешение «Создатель токена учетной записи службы» и разрешения «Создатель объекта хранения», и они это сделали.
I выполнил шаги в https://cloud.google.com/functions/docs/writing/http#gcloud, и я пробовал каждую комбинацию заголовков типа содержимого и пробовал v2 и v4 версии getSignedURL, а также следовал любым другим предложениям, которые я мог найти в Интернете, но безрезультатно.