2016-07-18 3 views
4

Я пытаюсь получить тело HTTP-запроса, но кажется, что это не так просто, как может показаться, если, конечно, я чего-то не хватает.Akka http using java - get String from RequestEntity

У меня есть экземпляр 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, которые я не имею в части немаршалинг, также возвращает CompletionStage<String>, который полностью избыточным, поскольку я хочу, чтобы это было выполнено синхронизированным.

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

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

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

Любые идеи?

+0

Я интересно, если вы не везли с этой задачей? – fnt

+3

@fnt Нет, я решил не использовать 'Akka', поскольку документация и поддержка очень плохие (по крайней мере, для java), это было просто слишком неприятно. –

ответ

0

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

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

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

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

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

+2

Спасибо за информацию. Я не возражаю против ограничения размера, поскольку запросы, которые я планирую поддерживать, не приближаются к '8M', но я просто предпочитаю использовать« низкоуровневый сервер api », а не« high-level api », , Я знаю директиву 'entity', я просто не хочу использовать директивы вообще. Итак, вопрос в том, как я могу выполнить это из объекта запроса? –

+0

@ johanandren У вас есть пример того, как создать пользовательский unmarshaller? Глядя, хотя javadocs, документация и онлайн-ресурсы не много. – Quy

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://stackoverflow.com/"), materializer). 
     thenCompose(response -> Unmarshaller.entityToString().unmarshal(response.entity(), ExecutionContexts.global(), materializer)). 
     thenAccept(System.out::println);