How to call http endpoint from actor?

How to call http endpoint from actor?

This topic is based on a conversation between an anonymous user of Akka and our “Ask AI about Akka” bot in the documentation.

To call an HTTP endpoint from an actor in Akka, you can use the Akka HTTP client API. Here is an example of how to do it in Scala:

import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import scala.concurrent.Future
import scala.util.{ Failure, Success }

object HttpClientSingleRequest {
  def main(args: Array[String]): Unit = {
    implicit val system = ActorSystem(Behaviors.empty, "SingleRequest")
    // needed for the future flatMap/onComplete in the end
    implicit val executionContext = system.executionContext

    val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://akka.io"))

    responseFuture
      .onComplete {
        case Success(res) => println(res)
        case Failure(_)   => sys.error("something wrong")
      }
  }
}

In this example, an HTTP request is made to the “http://akka.io” endpoint. The Http().singleRequest() method is used to send the request and returns a Future[HttpResponse]. The onComplete method is then used to handle the response or any failure that might occur.
You can find more information about this in the Akka HTTP documentation.

How to get http response as actor message?

To get an HTTP response as an actor message in Akka, you can use the pipeTo pattern. This pattern allows you to pipe the result of a Future to an actor as a message. Here is an example in Scala:

import akka.actor.{ Actor, ActorLogging, ActorSystem }
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.util.ByteString

class Myself extends Actor
  with ActorLogging {

  import akka.pattern.pipe
  import context.dispatcher

  implicit val system: ActorSystem = context.system
  val http = Http(system)

  override def preStart() = {
    http.singleRequest(HttpRequest(uri = "http://akka.io"))
      .pipeTo(self)
  }

  def receive = {
    case HttpResponse(StatusCodes.OK, headers, entity, _) =>
      entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body =>
        log.info("Got response, body: " + body.utf8String)
      }
    case resp @ HttpResponse(code, _, _, _) =>
      log.info("Request failed, response code: " + code)
      resp.discardEntityBytes()
  }
}

In this example, an HTTP request is made to the “http://akka.io” endpoint. The pipeTo method is used to send the response of the http.singleRequest method to the actor itself. The actor then handles the response in its receive method.

You can find more information about this in the Akka HTTP documentation.

Explain the pipe pattern.

The pipe pattern in Akka is a way to deal with Future results within an actor. It is used to send the result of a Future as a message to an actor. This pattern is useful because it allows you to avoid blocking the actor while waiting for the Future to complete.
Here is an example of how to use the pipe pattern in Scala:

import akka.pattern.pipe
import context.dispatcher

http.singleRequest(HttpRequest(uri = "http://akka.io"))
  .pipeTo(self)
In this example, an HTTP request is made and the response, which is a Future, is piped to the actor itself using the pipeTo method. The actor can then handle the response as a message in its receive method.
The pipe pattern is also used in combination with the ask pattern. The ask pattern involves sending a message to an actor and receiving a Future that will be completed with the actor's reply. The pipe pattern can be used to send this reply to another actor.
Here is an example of how to use the pipe pattern with the ask pattern in Scala:

import akka.pattern.{ ask, pipe }
import system.dispatcher
implicit val timeout: Timeout = 5.seconds

val f: Future[Result] =
  for {
    x <- ask(actorA, Request).mapTo[Int]
    s <- actorB.ask(Request).mapTo[String]
    d <- (actorC ? Request).mapTo[Double]
  } yield Result(x, s, d)

f.pipeTo(actorD)

In this example, the ask pattern is used to send a Request message to three different actors and receive a Future from each. The pipe pattern is then used to send the result of these futures to another actor.
You can find more information about the pipe pattern in the Akka documentation.