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, чтобы отслеживать добавление этого в документы.