Sending HTTP Requests in 5 Minutes With Scala and Akka HTTP
Join the DZone community and get the full member experience.
Join For Free
This article is for the Scala programmer who wants to run one-off HTTP requests quickly. The thinking style assumed is, "I don't want to care too much. I'll give you a payload; you just give me a future containing your response". With minimal boilerplate, we'll do exactly that with Akka HTTP in 5 minutes.
You can find this article in video form on YouTube or embedded below.
The
Rock the JVM blog is built with me typing my posts in plain text with minimal Markdown formatting and then generating a uniform HTML out of it, with a simple Scala parser (I hate typing HTML). For syntax highlighting, I use an
online highlighter, which happens to have a REST endpoint.
Naturally, I don't want to do it by hand, so as my HTML is generated, the syntax is automatically retrieved via an Akka HTTP as client, with little code. My HMTL generator currently has less than 100 lines of code in total.
In this article, I'm going to get you started with the simplest Akka HTTP client API in 5 minutes.
The Tiny Setup
First, you need to add the Akka libraries. Create an SBT project in your dev environment (I recommend IntelliJ). Then, add this to the
build.sbt file. (If you've never used SBT before, the
build.sbt file describes all the libraries that the project needs, which the IDE will download automatically)
Scala
x
10
1
val akkaVersion = "2.5.26"
2
val akkaHttpVersion = "10.1.11"
3
4
libraryDependencies ++= Seq(
5
// akka streams
6
"com.typesafe.akka" %% "akka-stream" % akkaVersion,
7
// akka http
8
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
9
"com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
10
)
Then, in a Scala application, I'm going to write a piece of small boilerplate because Akka HTTP needs an actor system to run:
Scala
xxxxxxxxxx
1
1
implicit val system = ActorSystem()
2
implicit val materializer = ActorMaterializer()
3
import system.dispatcher
Sending HTTP Requests
Now, we'll need to start sending HTTP requests. I'll use the exact HTTP API I'm using for the blog:
http://markup.su/highlighter/api. The API says it needs GET or POST requests to /api/highlighter, with the parameters "language", "theme", and "source" in a request with content type
application/x-www-form-urlencoded
.
So, let me create a piece of Scala code:
Scala
xxxxxxxxxx
1
12
1
val source =
2
"""
3
|object SimpleApp {
4
| val aField = 2
5
|
6
| def aMethod(x: Int) = x + 1
7
|
8
| def main(args: Array[String]) = {
9
| println(aMethod(aField))
10
| }
11
|}
12
""".stripMargin
and then let me create an HTTP request for it:
Scala
xxxxxxxxxx
1
1
val request = HttpRequest(
2
method = HttpMethods.POST,
3
uri = "http://markup.su/api/highlighter",
4
entity = HttpEntity(
5
ContentTypes.`application/x-www-form-urlencoded`,
6
s"source=${URLEncoder.encode(source.trim, "UTF-8")}&language=Scala&theme=Sunburst"
7
)
8
)
where I've named the arguments in the call for easy reading. In the Akka HTTP, an
HttpRequest
contains the HTTP method (POST in our case). The URI and a payload in the form of an
HttpEntity
. We specify the content type per the description specified in the API — notice the backticks for the name of the field — and the actual string we want to send, as described by the API. In practice, you can send other strings, like JSON — I'll show you how to auto-convert your data types to JSON auto-magically in another article.
Then, we actually need to send our request:
Scala
xxxxxxxxxx
1
1
def simpleRequest() = {
2
val responseFuture = Http().singleRequest(request)
3
responseFuture.flatMap(_.entity.toStrict(2 seconds)).map(_.data.utf8String).foreach(println)
4
}
The Akka HTTP client call is simple: just call the
singleRequest
method. You obtain a Future containing an HTTP response, which we can then unpack. We use its entity (= its payload) and convert it to a strict entity, meaning that we take its whole content in memory. We then take its data, which is a sequence of bytes, and convert that to a string. And we're done.
Hide it All
We can create a very nice method which hides this all away:
Scala
xxxxxxxxxx
1
16
1
def highlightCode(myCode: String): Future[String] = {
2
val responseFuture = Http().singleRequest(
3
HttpRequest(
4
method = HttpMethods.POST,
5
uri = "http://markup.su/api/highlighter",
6
entity = HttpEntity(
7
ContentTypes.`application/x-www-form-urlencoded`,
8
s"source=${URLEncoder.encode(myCode.trim, "UTF-8")}&language=Scala&theme=Sunburst"
9
)
10
)
11
)
12
13
responseFuture
14
.flatMap(_.entity.toStrict(2 seconds))
15
.map(_.data.utf8String)
16
}
And then you can go on with your day: pass a string, expect a future containing an HTML highlighting. All done!
If you want to practice sending HTTP requests as an exercise, you can use
https://jsonplaceholder.typicode.com/ for dummy APIs, the same principle applies.
Scala (programming language)
Requests
Akka (toolkit)
Published at DZone with permission of Daniel Ciocirlan. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments