Запрос PUT в облачное хранилище Google, подписанный URL-адрес, сгенерированный Shopify, выдает ошибку MalformedSecurityHeader

Я пытаюсь загрузить файл .glb на продукт в магазине Shopify через Shopify GraphQL Admin API. Для этого он сначала возвращает подписанный URL-адрес облачного хранилища Google, куда я должен загрузить свой файл через HTTP-запрос PUT. После загрузки я должен прикрепить тот же URL к продукту с другим вызовом API.

Этот вопрос касается загрузки этого файла на подписанный URL-адрес облачного хранилища. Я включил все эти детали, чтобы облегчить получение ответа на этот вопрос. Итак, читайте до конца.

  1. Какие данные Shopify предоставляет мне, упоминается ниже.
{
  "data": {
    "stagedUploadsCreate": {
      "stagedTargets": [
        {
          "parameters": [
            {
              "name": "GoogleAccessId",
              "value": "threed-model-service--6bgx7cbe@shopify-applications.iam.gserviceaccount.com"
            },
            {
              "name": "key",
              "value": "models/a6436c066064bac3/windmill.glb"
            },
            {
              "name": "policy",
              "value": "eyJleHBpcmF0aW9uIjoiMjAyMC0wNy0yMVQwOToxNjoxMFoiLCJjb25kaXRpb25zIjpbWyJlcSIsIiRidWNrZXQiLCJ0aHJlZWQtbW9kZWxzLXByb2R1Y3Rpb24iXSxbImVxIiwiJGtleSIsIm1vZGVscy9hNjQzNmMwNjYwNjRiYWMzL3dpbmRtaWxsLmdsYiJdLFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLDE5NzE3MiwxOTcxNzJdXX0="
            },
            {
              "name": "signature",
              "value": "vz+OdcEmD9Kbv2FbXdxWNUk59XO2GmXzhvtDswXbDQNcyZpUufI85z5x2PFGv/XZ+tSBsl/S393pmy0Bu9xG7oVgOZcMIWEbOIm9kXgQunbjKQY3Ff3BBpMocB0xazzlYmckZozdJ8ZZkyox/c/gEe1QaxqW4+419iufuFHy4Bp3LL/aUr+ATNChwn9Dn8+XnHMOckZxDlbiggcF3dx+yBuTFia8FneaVSiU0M5DIWmHqHb2YDCV0KtEP6jfTj/PQVUjS8pn8EGhrRaMx7Q2A5G8Pycgc9H35hqJnnUKCTa3AYeyI45RbhddYnIWw9YrAADXuQYlVCo6LYBHjxsCWA=="
            }
          ],
          "resourceUrl": "https://storage.googleapis.com/threed-models-production/models/a6436c066064bac3/windmill.glb?external_model3d_id=bW9kZWwzZC00MDg5Ng==",
          "url": "https://storage.googleapis.com/threed-models-production/models/a6436c066064bac3/windmill.glb?external_model3d_id=bW9kZWwzZC00MDg5Ng=="
        }
      ],
      "userErrors": []
    }
  }
}
  1. Используя эти параметры, я создаю подписанный URL-адрес следующим образом.
resourceUrl+"&signature="+signature+"&key="+key+"&policy="+policy+"&GoogleAccessId="+GoogleAccessId

Eg:

https://storage.googleapis.com/threed-models-production/models/a6436c066064bac3/windmill.glb?external_model3d_id=bW9kZWwzZC00MDg5Ng==&signature=vz+OdcEmD9Kbv2FbXdxWNUk59XO2GmXzhvtDswXbDQNcyZpUufI85z5x2PFGv/XZ+tSBsl/S393pmy0Bu9xG7oVgOZcMIWEbOIm9kXgQunbjKQY3Ff3BBpMocB0xazzlYmckZozdJ8ZZkyox/c/gEe1QaxqW4+419iufuFHy4Bp3LL/aUr+ATNChwn9Dn8+XnHMOckZxDlbiggcF3dx+yBuTFia8FneaVSiU0M5DIWmHqHb2YDCV0KtEP6jfTj/PQVUjS8pn8EGhrRaMx7Q2A5G8Pycgc9H35hqJnnUKCTa3AYeyI45RbhddYnIWw9YrAADXuQYlVCo6LYBHjxsCWA==&key=models/a6436c066064bac3/windmill.glb&policy=eyJleHBpcmF0aW9uIjoiMjAyMC0wNy0yMVQwOToxNjoxMFoiLCJjb25kaXRpb25zIjpbWyJlcSIsIiRidWNrZXQiLCJ0aHJlZWQtbW9kZWxzLXByb2R1Y3Rpb24iXSxbImVxIiwiJGtleSIsIm1vZGVscy9hNjQzNmMwNjYwNjRiYWMzL3dpbmRtaWxsLmdsYiJdLFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLDE5NzE3MiwxOTcxNzJdXX0=&GoogleAccessId=threed-model-service--6bgx7cbe@shopify-applications.iam.gserviceaccount.com

  1. Затем я пытаюсь сделать запрос PUT к этому URL-адресу с файлом .glb в POSTman, как показано на этом изображении - ›  введите описание изображения здесь

со следующими заголовками.

введите описание изображения здесь

  1. Но я не получаю ответа об успехе. Фактически, я получаю ошибку 400 со следующим сообщением.
<?xml version='1.0' encoding='UTF-8'?>
<Error>
    <Code>MalformedSecurityHeader</Code>
    <Message>Your request has a malformed header.</Message>
    <ParameterName>signature</ParameterName>
    <Details>Signature was not base64 encoded</Details>
</Error>

Может кто-нибудь указать мне, что я здесь делаю не так? Я сталкивался с этой ошибкой в ​​течение нескольких дней и читал много вопросов и статей, но не мог заставить это работать. Поэтому мы очень ценим любое полезное предложение.


person Pavindu    schedule 20.07.2020    source источник


Ответы (1)


Несколько советов, которые стоит попробовать:

  • При генерации начального запроса (в данном случае это сделал Shopify), GCS обычно включает HTTP-заголовки этого запроса и включает их в подпись запроса и ожидает, что запрос на загрузку (тот, который вы пытаетесь сделать) будет соответствовать тем же значениям HTTP-заголовка. . Это означает, что вам рекомендуется включать только те заголовки Shopify, указанные в их запросе, в ваш подписанный запрос на загрузку ключа и ничего лишнего. Поэтому сначала попробуйте удалить все заголовки HTTP, которые не задокументированы Shopify (например, добавленные POSTMAN), и убедитесь, что все значения заголовков соответствуют документации Shopify (например, Content-Type должен совпадать)
  • You need to ensure signature parameters are in the expected names and formats:
    1. signature value field is named: x-goog-signature and not signature (This is the likely reason for the error you're getting that GCS can't find the expected param)
    2. вам, вероятно, также придется предоставить ключ алгоритма подписи (x-goog-algorithm)
    3. вам могут понадобиться и другие ключи в зависимости от других факторов, таких как аутентификация, поэтому я бы сказал, что они должны быть задокументированы Shopify SDK и / или примерами

Одним из предложений по упрощению / ускорению работы для вас может быть использование Google Cloud Utils (инструмент командной строки gsutil) для создания подписанного запроса URL-адреса, а затем попытка воспроизвести такое же поведение в вашем коде. Для получения дополнительной информации см. Эти ссылки:

https://cloud.google.com/storage/docs/access-control/signed-urls https://cloud.google.com/storage/docs/access-control/signing-urls-with-helpers#gsutil

Затем, познакомившись с форматом подписанного URL-адреса, вы можете проверить это на примере кода о том, как это сделать в своем собственном коде:

https://cloud.google.com/storage/docs/access-control/signing-urls-manually

Для справки при чтении документов, тип подписанного URL-адреса, который вы пытаетесь создать, является невозобновляемой загрузкой (которая использует один запрос PUT), а не возобновляемой (которая использует начальный POST плюс серию PUT) Извините, я не знаю не работал с Shopify, но вышеизложенное основано на моем опыте работы с URL-адресами, подписанными GCS

person Mohammad    schedule 28.07.2020
comment
Да, как вы упомянули, я также пробовал использовать x-goog-signature вместо signature и так далее. Однако, если я так использовал, он требует значение для параметра x-goog-credential, но ни одно из значений параметров, которые дает Shopify, не соответствует этому значению параметра, т.е. приводит к ошибке. - person Pavindu; 28.07.2020
comment
Как вы упомянули в ответе, эти вещи должны быть явно упомянуты в документации Shopify API, но ничего не найдено. Я также отправил по электронной почте поддержку Shopify, и они пообещали добавить эту информацию в документацию в ближайшее время, но я не знаю, когда это произойдет, и я хочу решить эту проблему как можно скорее. - person Pavindu; 28.07.2020