Akka http с помощью Java - получить строку из RequestEntity

Я пытаюсь получить тело запроса http, но кажется, что это не так просто, как может показаться, если, конечно, я что-то упустил.

У меня есть экземпляр HttpRequest (от akka.http.javadsl.model) и от этого я могу получить RequestEntity, но я не могу понять, как извлечь строку из сущности.
Я хочу сделать это синхронно, просто простая операция по извлечению строки.

Я пробовал два разных пути:

(1)

Source<ByteString, Object> source = RequestEntity.getDataBytes();

Я не уверен, что я должен делать с sourceУ него много методов, и неясно, как их использовать, и может ли какой-нибудь из них действительно помочь мне.

(2)

Unmarshaller<HttpEntity, String> unmarshaller = Unmarshaller.entityToString();
CompletionStage<String> result = unmarshaller.unmarshall(entity, ExecutionContext, Materializer);

призвание unmarshaller.unmarshall требует не только экземпляра RequestEntity но также ExecutionContext и Materializer что я не имею в части unmarshalling, а также возвращает CompletionStage<String> что совершенно избыточно, так как я хочу, чтобы это было сделано синхронизировано.

Документация и примеры для java не очень помогают, поскольку они очень короткие и краткие, если они вообще существуют, например, в разделе Marshalling & Unmarshalling:

Используйте предопределенные Unmarshaller.entityToString, Unmarshaller.entityToByteString, Unmarshaller.entityToByteArray, Unmarshaller.entityToCharArray для преобразования в эти основные типы

Как видите, это не очень информативно.

Есть идеи?

2 ответа

Вы можете использовать глобальный ExecutionContext и то же самое Materializer используется для бега akka-http, Вам нужно будет составить Future который делает HTTP-запрос с тем, который предоставляется Unmarshaller:

    import akka.actor.ActorSystem;
    import akka.dispatch.ExecutionContexts;
    import akka.http.javadsl.Http;
    import akka.http.javadsl.model.HttpRequest;
    import akka.http.javadsl.model.HttpResponse;
    import akka.http.javadsl.model.ResponseEntity;
    import akka.http.javadsl.unmarshalling.Unmarshaller;
    import akka.stream.ActorMaterializer;
    import akka.stream.Materializer;

    ActorSystem system = ActorSystem.create();
    Materializer materializer = ActorMaterializer.create(system);

    Http.get(system).
        singleRequest(HttpRequest.create("http://stackru.com/"), materializer).
        thenCompose(response -> Unmarshaller.entityToString().unmarshal(response.entity(), ExecutionContexts.global(), materializer)).
        thenAccept(System.out::println);

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

Чтобы ответить на ваш конкретный вопрос, используя entity Директива с одним из предопределенных маршаллеров будет выглядеть так:

path("example", () ->
  entity(Unmarshaller.entityToString(), (string) -> {
    System.out.println("request body: " + string);
    return complete("ok");
  })
)

Обратите внимание, что он прочитает все тело запроса в память JVM, что может потребовать некоторых мыслей. Существует ограничение по умолчанию в 8M для тел запросов, которое можно изменить конфигурацией или переопределить для определенного пути с помощью withSizeLimit а также withoutSizeLimit директивы.

Я открыл билет Akka 21001, чтобы отслеживать добавление этого в документы.

Другие вопросы по тегам