Как программно вызвать Route в Akka Http - PullRequest
0 голосов
/ 10 мая 2018

В Akka Http можно определить систему маршрутов для управления инфраструктурой REST следующим образом: https://doc.akka.io/docs/akka-http/current/routing-dsl/overview.html

val route =
      get {
        pathSingleSlash {
          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,"<html><body>Hello world!</body></html>"))
        } ~
          path("ping") {
            complete("PONG!")
          } ~
          path("crash") {
            sys.error("BOOM!")
          }
      }

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

val response = (new Invoker(route = route, method = "GET", url = "/ping", body = null)).Invoke()

где Response будет таким же результатом удаленного HTTP-вызова службы?

Вышеупомянутый API предназначен только для того, чтобы дать представление о том, что я имею в виду, я ожидаю, что будет возможность устанавливать тип содержимого, заголовки и т. Д.

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

В конце концов мне удалось найти ответ на свой вопрос, немного покопавшись в документации Akka HTTP.

Как указано здесь: https://doc.akka.io/docs/akka-http/current/routing-dsl/routes.html, тип Route определяется следующим образом:

type Route = RequestContext => Future[RouteResult]

, где RequestContext - это оболочка для HttpRequest. Но верно также и то, что Route может быть преобразован, неявно или нет, в другие типы функций, например:

def asyncHandler(route: Route)(...): HttpRequest ⇒ Future[HttpResponse]

Следовательно, действительно возможно «вызвать» маршрут, преобразовав его в другой тип функции, а затем просто пропустив специальную сборку HttpRequest, получив Future, содержащий желаемый ответ. Преобразование потребовало немного больше времени, чем остальные операции, но это можно сделать при загрузке приложения.

Примечание : для преобразования требуется этот импорт, как указано здесь: https://doc.akka.io/docs/akka-http/current/introduction.html

implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher

Но этот импорт уже является обязательным для создания самой службы.

0 голосов
/ 10 мая 2018

Если это для модульных тестов, вы можете использовать akka-http's test kit .

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

Что касается причины, я хочу, чтобы мое приложение было обернуто как на веб-сервере (затем использовать маршрут «обычным» способом), так и на демона, который отвечает на входящее сообщение брокера сообщений.

У меня есть приложение, которое делает что-то подобное на самом деле.

Но я пришел к этому с другой стороны: я считаю сообщение посредника «основным» форматом. Он «маршрутизируется» внутри потребителя исключительно на основе свойств самого сообщения (содержимого тела, ключа сообщения, названия темы). Вдобавок к этому построен HTTP-шлюз: он имеет очень ограниченное количество конечных точек и маршрутов API (в основном для удобства вызывающего абонента, может также иметь только один) и создает сообщение, которое затем передается потребителю сообщения (в моем случае, фактически через посредника, так что шлюз HTTP даже не должен находиться на том же хосте, что и потребитель).

В результате мне не нужно «повторно» использовать HTTP-маршрут, потому что это ничего не делает. Вся логика совместной обработки происходит на более низком уровне (внутри службы, внутри потребителя).

...