Речь идет об использовании ActiveStorage с GCS для случая использования клиента API.(Rails 5.2.1, 5.2.2)
Я пишу тест, чтобы изучить, как создать запрос, имитирующий прямую загрузку в GCS, подготовленный универсальным DirectUploadsController. Этот универсальный контроллер является частью ActiveStorage.Идея состоит в том, чтобы позже реплицировать код в мобильном приложении, используя тот же бэкэнд.
Конфигурация AS хорошо работает в среде разработки, используя как загрузку через контроллеры, так и прямую загрузку с использованием интеграции JS, которая поставляетсяс AS.Вот почему я предполагаю, что конфиг должен быть в порядке.(env 'test' и 'development' используют точно такую же настройку на этом этапе.)
Тестовый код находится в поле ниже.
В конечном итоге он вызывает 403 Запрещенный ответ отRestClient.put
call.
В ответном сообщении содержится жалоба на несоответствие подписи, подробности ниже.Сначала тестовый код:
require 'test_helper'
class UploadControllerTest < ActionDispatch::IntegrationTest
test "direct upload from controller prepared blob" do
pathname = file_fixture('cube.png')
data = pathname.binread
content_type = "image/png"
post rails_direct_uploads_path, params: {
blob: {
filename: pathname.basename,
byte_size: pathname.size,
checksum: Digest::MD5.base64digest(data),
content_type: content_type
}
}
assert_equal 27195, pathname.size
assert_response :success
json = response.parsed_body
direct_upload = json["direct_upload"]
signed_url = direct_upload["url"]
headers = direct_upload["headers"]
assert_equal({ "Content-MD5" => "tmBHZQCm+qBzGFEaDwmpnA==" }, headers)
assert_match /&Signature=/, signed_url
assert_match /&Expires=/, signed_url
assert_match %r{^https://storage.googleapis.com}, signed_url
response = RestClient.put(
signed_url,
data,
headers.merge("Content-Type" => content_type)
)
assert_response :success
rescue RestClient::Forbidden => e
pp e.response.body
fail "Failing with 403 Forbidden" # always ends up here
end
end
В результате тело ответа будет следующим: XML:
<?xml version='1.0' encoding='UTF-8'?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.
</Message>
<StringToSign>PUT\n" +
"tmBHZQCm+qBzGFEaDwmpnA==\n" +
"image/png\n" +
"1544517548\n" +
"/planprop-test-bucket/gVn9zVCumGJxiu2kU6mFWUVV</StringToSign>
</Error>
Код ошибки:
SignatureDoesNotMatch
и сопровождающее сообщение:
Рассчитанная нами подпись запроса не соответствует предоставленной вами подписи.Проверьте свой секретный ключ Google и метод подписи.
Перечисленными частями строки подписи являются контрольная сумма (как указано выше), срок действия (часть URL-адреса), тип контента (как указано выше) иобъект (имя и ключ группы, часть URL).Так что я не вижу места, где могло бы проскальзывать несоответствие.
Что не так?