#google-cloud-platform #google-cloud-storage
# #google-облачная платформа #google-облачное хранилище
Вопрос:
Ответ PUT
на запрос с подписанным URL — адресом не содержит заголовка Access-Control-Allow-Origin
.
import os
from datetime import timedelta
import requests
from google.cloud import storage
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = <path to google credentials>
client = storage.Client()
bucket = client.get_bucket('my_bucket')
policies = [
{
'origin': ['*'],
'method': ['PUT'],
}
]
bucket.cors = policies
bucket.update()
blob = bucket.blob('new_file')
url = blob.generate_signed_url(timedelta(days=30), method='PUT')
response = requests.put(url, data='some data')
for header in response.headers.keys():
print(header)
Выходной сигнал:
X-GUploader-UploadID
ETag
x-goog-generation
x-goog-metageneration
x-goog-hash
x-goog-stored-content-length
x-goog-stored-content-encoding
Vary
Content-Length
Date
Server
Content-Type
Alt-Svc
Как вы можете видеть, CORS-заголовков нет. Итак, могу ли я сделать вывод, что GCS не поддерживает CORS должным образом / полностью?
Ответ №1:
Совместное использование ресурсов из разных источников (CORS) позволяет взаимодействовать между ресурсами из разных источников. По умолчанию в облачном хранилище Google это запрещено / отключено для предотвращения вредоносного поведения.
Вы можете включить его с помощью облачных библиотек, Rest API или Cloud SDK, соблюдая следующие правила:
- Аутентификация с использованием учетной записи пользователя / службы с разрешениями для типа облачного хранилища :
FULL_CONTROL
. - Использование XML API для получения правильных заголовков CORS используйте один из двух URL-адресов:
- storage.googleapis.com/[BUCKET_NAME]
- [BUCKET_NAME].storage.googleapis.com
Origin storage.cloud.google.com/[BUCKET_NAME]
не будет отвечать заголовком CORS.
- Для запроса требуется правильный заголовок источника, соответствующий конфигурации источника политики корзины, как указано в пункте 3 документации по устранению неполадок CORS, в случае вашего кода:
headers = {
'ORIGIN': '*'
}
response = requests.put(url, data='some data', headers=headers)
for header in response.headers.keys():
print(header)
выдает следующий вывод:
X-GUploader-UploadID
ETag
x-goog-generation
x-goog-metageneration
x-goog-hash
x-goog-stored-content-length
x-goog-stored-content-encoding
Access-Control-Allow-Origin
Access-Control-Expose-Headers
Content-Length
Date
Server
Content-Type
Комментарии:
1. Это работает только для запросов GET. Но не работает для PUT. Посмотрите на предоставленный мной код. Я делаю то же самое, что вы предложили, за исключением метода PUT.
2. КСТАТИ, УДАЛЕНИЕ, которое вы использовали в политике корзины в вашем примере, также не работает.
3. В документации указано , что запрос предварительно отображается в любом другом методе, кроме: GET, HEAD или POST. Это включает в себя: ОПУБЛИКОВАТЬ и удалить. Вы пытались это проверить?
4. Да. Ответ на предполетный запрос не содержит заголовков CORS. В моем случае он УСТАНОВЛЕН (также установлен флажок УДАЛИТЬ).
5. Я воспроизвел вашу проблему и соответствующим образом обновил ответ. Это работает для меня.
Ответ №2:
У меня была эта проблема. Для меня проблема заключалась в том, что я использовал POST
вместо PUT
. Кроме того, мне пришлось настроить Content-Type
тип загрузки в соответствии с типом содержимого, используемым для создания формы. Тип содержимого по умолчанию в демо-версии — «application / octet-stream», поэтому мне пришлось изменить его на тот, который был типом содержимого при загрузке. При выполнении XMLHttpRequest мне просто нужно было отправить файл напрямую, а не использовать FormData.
Так я получил подписанный URL-адрес.
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("lsa-storage")
.file(upload.id)
.getSignedUrl(options as any);