Akka http потоковая заголовки ответа - PullRequest
0 голосов
/ 29 августа 2018

По определению ответ http делится на 3 части , status-code -> headers -> body, а при выполнении http-запросов akka client ответ http получается после того, как первые 2 части были полностью получил.

  val responseFuture: Future[HttpResponse]
  responseFuture.map {
    case HttpResponse(statusCode:StatusCode, headers:Seq[HttpHeader], entity:ResponseEntity, protocol:HttpProtocol)
  }

Это вполне нормально для большинства случаев использования, но в моем конкретном случае мне нужен доступ к заголовкам до получения всех заголовков (сторонний сервер возвращает прогресс, записывая пользовательские заголовки прогресса, пока ответ не будет готов). Есть ли способ получить доступ к заголовкам так же, как мы обращаемся к телу?

  val entity: ResponseEntity
  val entitySource:Source[ByteString, Any] = entity.dataBytes

В идеальном мире был бы способ получить доступ к заголовкам как к источнику

HttpResponse(statusCode:StatusCode, headers:Source[HttpHeader, NotUsed], entity:ResponseEntity, protocol:HttpProtocol)

1 Ответ

0 голосов
/ 29 августа 2018

невозможно с akka-http

Представление HttpResponse обрабатывает заголовки как Seq[HttpHeader] вместо Iterator или akka-stream Source. Следовательно, как объясняется в этом вопросе, невозможно создать экземпляр объекта HttpResponse, не имея вначале всех доступных значений заголовка.

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

Обработка нижнего уровня с akka-stream

протокол передачи гипертекста - это просто протокол прикладного уровня, обычно поверх TCP. И это довольно простой формат сообщения :

Ответное сообщение состоит из следующего:

  • Строка состояния, которая включает код состояния и сообщение о причине (например, HTTP / 1.1 200 OK, что указывает на успешное выполнение запроса клиента).
  • Поля заголовка ответа (например, Content-Type: text / html).
  • Пустая строка.
  • Необязательное тело сообщения.

Таким образом, вы можете использовать привязку Tcp, чтобы установить соединение и проанализировать сообщение ByteString Найдите источник, чтобы попасть в заголовки:

val maximumFrameLength = 1024 * 1024

val endOfMessageLine : () => Byte => Boolean = () => {
  var previousWasCarriage = false

  (byte) => 
    if(byte == '\r') {
      previousWasCarriage = true
      false
    }
    else if(byte == '\n' && previousWasCarriage) {
      previousWasCarriage = false
      true
    }
    else {
      previousWasCarriage = false
      false
    }
}

def subFlow = 
  Flow[ByteString].flatMapConcat(str => Source.fromIterable(str))
                  .splitAfter(endOfMessageLine())

К сожалению, для этого, вероятно, требуется, чтобы ваш запрос был отправлен как необработанная строка ByteString через привязку Tcp.

...