首页 > 解决方案 > 使用 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 上传或下载在没有标头的情况下可以正常工作几个月,但我不明白为什么服务器会响应标头元标记格式错误......我将不胜感激,谢谢!

标签: pythondjangogoogle-cloud-platformgoogle-cloud-storage

解决方案


正如@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() {},
  });
}

推荐阅读