Проблема с CORS для загрузки в хранилище Firebase с подписанным URL - PullRequest
1 голос
/ 14 июля 2020

Я создаю приложение для Интернета, размещенное на 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, а также следовал любым другим предложениям, которые я мог найти в Интернете, но безрезультатно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...