Реализация базового S3-совместимого API с помощью akka-http - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь реализовать хранилище файлов ыукмшсу с базовым S3-совместимым API, используя akka-http.
Я использую s3 java sdk для тестирования моего сервисного API и получил проблему с методом putObject (...).Я не могу правильно использовать файл на моем сервере akka-http.Я написал простой маршрут для целей тестирования:

def putFile(bucket: String, file: String) = put{
      extractRequestEntity{ ent =>
      val finishedWriting = ent.dataBytes.runWith(FileIO.toPath(new File(s"/tmp/${file}").toPath))
      onComplete(finishedWriting) { ioResult =>
        complete("Finished writing data: " + ioResult)
      }
    }
  }

Сохраняет файл, но файл всегда поврежден.Заглянув внутрь файла, я нашел следующие строки:

"20000;chunk-signature=73c6b865ab5899b5b7596b8c11113a8df439489da42ddb5b8d0c861a0472f8a1".

Когда я пытаюсь PUT файл с любым другим клиентом отдыха, он работает нормально, как и ожидалось.Я знаю, что S3 использует заголовок «Expect: 100-continue» и может вызывать проблемы.Я действительно не могу понять, как справиться с этим.Любая помощь приветствуется.

1 Ответ

0 голосов
/ 09 октября 2018

Это не совсем повреждено.Ваша служба не учитывает один из четырех способов, которыми S3 поддерживает отправку по сети, используя Content-Encoding: aws-chunked и x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD.

Это нестандартный механизм для потоковой передачи объекта, ивключает в себя чанки, которые выглядят именно так:

string(IntHexBase(chunk-size)) + ";chunk-signature=" + signature + \r\n + chunk-data + \r\n

... где IntHexBase() - псевдокод для функции, которая форматирует целое число как шестнадцатеричное число в виде строки.

Этот алгоритм на основе чанков аналогичен Transfer-Encoding: chunked, но не совместим с ним, поскольку он встраивает контрольные суммы в поток.

Почему они составляютновая кодировка передачи HTTP?Это потенциально полезно на стороне клиента, поскольку устраняет необходимость либо «дважды прочитать вашу полезную нагрузку, либо поместить в буфер [всю полезную нагрузку объекта] в памяти [одновременно]» * - одна или другая из которых необходимы в противном случаеесли вы собираетесь вычислить хеш x-amz-content-sha256 до начала загрузки, как вы должны это сделать, так как это требуется для проверки целостности.

Я не слишком знаком с внутренними компонентами Java SDK, но этот тип загрузки может быть инициирован с помощью .withInputStream() или это может быть стандартное поведениедля файлов тоже или для файлов более определенного размера.

Ваш минимальный обходной путь - выброс HTTP-ошибки, если вы видите x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD в заголовках запроса, поскольку вы, похоже, не реализовали это в своем API,но это, скорее всего, будет служить только для предотвращения хранения объектов, загруженных этим методом.Тот факт, что это уже не то, что происходит автоматически, говорит о том, что вы вообще не реализовали обработку x-amz-content-sha256, поэтому вы не выполняете проверки целостности полезной нагрузки на стороне сервера, которые вам нужно делать.

Для полной совместимости вам необходимо реализовать алгоритм, поддерживаемый S3 и предполагаемый доступным для SDK, если только SDK специально не поддерживают механизм отключения этого алгоритма - что кажется маловероятным, поскольку он служит полезной цели, в частности (он появляется) для потоков, длина которых известна, но которые не доступны для поиска.


¹ один из четырех - остальные три являются стандартными PUT, веб-основанная на html форма POST и многокомпонентный API, рекомендуемый для больших файлов и обязательный для файлов размером более 5 ГБ.

...