python - 使用 Django 通过 Google Cloud 签名 URL 发送元标记
问题描述
我正在使用签名的 url 在我的谷歌存储上获取或发布/发布视频 fileq。我的模块引用了signed_url V4并且运行良好。我想在我的请求中添加一些元数据标签,以便更有效地管理与 GCS 相关的费用。但是由于我添加了这些标头,因此请求未能返回 cors 策略错误:(我缩短了上面块中的签名以使其更具可读性)
Access to XMLHttpRequest at 'https://test-dev-slotll.storage.googleapis.com/uploads/dave/FR/eaa678c9/2020/9/785f/f45d3d82-785f_full.mp4?X-
Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=dev-storage%40brilliant-tower-264412.iam.gserviceaccount.com%2F20200926%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20200926T093102Z&X-Goog-Expires=3600&X-Goog-SignedHeaders=host%3Bx-goog-meta-account&x-goog-signature=6fbb27e[...]bd0891d21' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
和详细信息:
<Error>
<Code>MalformedSecurityHeader</Code>
<Message>Your request has a malformed header.</Message>
<ParameterName>x-goog-meta-account</ParameterName>
<Details>Header was included in signedheaders, but not in the request.</Details>
</Error>
cors 被配置为允许我的桶上的几乎所有东西:
[{"maxAgeSeconds": 3600, "method": ["*"], "origin": ["*"], "responseHeader": ["*"]}]
这是 Python/Django 函数
def _get_signed_url(self, http_method="GET"):
"""' create a signed url with google storage
create a 'GET' request by default,
add method='w' or 'put' to create a 'PUT' request
get_signed_url('w')->PUT / get_signed_url()->GET
"""
if http_method.lower() in ["w", "put", "post"]:
http_method = "PUT"
else:
http_method = "GET"
signed_url = generate_signed_url(
settings.GS_BUCKET_NAME,
self.file.name,
subresource=None,
expiration=3600,
http_method=http_method,
query_parameters=None,
headers={'x-goog-meta-language':'french','x-goog-meta-account':'david',},
)
return signed_url
正如我在上面写的那样,
如果我替换
为or方法 get_signed_url() 是从signed_url V4复制的(就像以前一样,它工作正常headers = {'x-goog-meta-language':'french','x-goog-meta-account':'david',},
hearders = {}
headers = None
最后,当我单击签名 URL 给出的链接时,我收到一条错误消息:
签名的 url 以及 blob 上传或下载在没有标头的情况下可以正常工作几个月,但我不明白为什么服务器会响应标头元标记格式错误......我将不胜感激,谢谢!
解决方案
正如@Sideshowbarker 在他的评论中所暗示的那样,问题来自客户。签名的 url 用于通过 ajax 将文件发送到存储,但没有向 ajax 添加自定义标头。通过在 ajax 中指定标头,带有自定义元数据的签名 url 的 PUT 请求运行良好。
function ajaxSendToStorage(uuid, url) {
// Sending ONE file to storage
var file = getFileById(uuid);
$.ajax({
method: "PUT",
contentType: file.type,
processData: false,
dataType: "xml",
crossDomain: true,
data: file,
url: url,
headers: {"x-goog-meta-account":"david","x-goog-meta-language": "fr"},
success: function() {},
complete: function() {},
});
}
推荐阅读
- c++ - 三元运算符中的条件移动或复制赋值
- javascript - 在 React 中使用递归渲染嵌套列表 - 如何避免不必要的更新?
- python - 多环境coremltools安装
- talend - gpload 在 NULL_AS 为 "" 的 CSV 模式下失败
- arrays - Swift:使用 start with 过滤字符串
- c - 作业左侧的括号
- database - 处理在 mongodb 中完全相同的多个查询
- hadoop - 如何防止 hadoop 在每个运行的作业上上传相同的 jar 到暂存缓存
- javascript - 使用 document.write() 将 html 写入 iframe,但 jquery 在 IE9 中不起作用
- mysql - Laravel 5.0 将 redis 数据从前端的套接字发射上的节点获取,无需 ajaxcall 并在 mysql 中更新