Philipp Mayer

March 28, 2021

http4k 101: HTTP Handlers

This post is part of a series about http4k.
Part 1 - Http4k - A Sneak Peak

A TL;DR can be found at the bottom of the article.

HttpHandlers are one of http4k's core features: Handling a request and returning a response.
Before we dive in, let me define a scenario that we will be used as an example for all the mechanics we will implement.


Scenario

Our company needs a new vacation planning tool. Over the next few articles, we will add more and more features, but today we're starting with two simple things:

  • We want to get information about how many of our colleagues are on vacation today.
  • We need an option to check the absence of a specific employee for the current day.


Our First HttpHandler

The "Hello World!" of http4k looks like that:
2.png

If we now look into what an HttpHandler is, we'll find out that it's just a lambda:
11.png
That's refreshing. Just a lambda with an object of type Request as input and a Response as output. Having that in mind, we can finally start playing around with it.


Feature 1: Overall Absence of Our Department

  • We want to get information about how many of our colleagues are on vacation

Let's write a test for our feature:
10.png
To start of easy, we always expect 15%. Here, I'm using Kotest assertions and its http4k extensions to validate the response. Since HttpHandler is only a lambda of type (Request) -> Response, we can simply pass in our request, and we'll get a response.

Why am I repeating that again?
Well, look closer. We have a test with no setup, just functions calling functions, but we're getting a valid Http response. All of it is running in-memory, blazing fast and easy to understand. Teaser: http4k offers a lot more when it comes to testing. We'll dive into it in another article.

Looking back at our handler, let's change some small things to fit our test:
1.png
We rename it and omit the request, since we're not using it anyways. Furthermore, we add the mentioned 15% to our body to make the test pass.

Oh, we're simply omitting the request. Overall, we have nothing that checks the http method.
Maybe we should test our handler with another Http method? Why not try them all? Let's go! Http4k provides all the necessary methods in an enum:
carbon.png
Junit5's Parameterized Tests come in handy here: We can just use the Method enum to iterate over its values
9.png
Running our test again, we find out that it indeed works with every method. Why shouldn't it, we didn't specify a http method type (we'll look into that later, don't worry).

Important: When performing it as an integration test (so to speak: crossing boundaries) with an http client, you will find out that the test will fail with an http method of type HEAD. You can read here why. An example for such a test can be found in the git repository.

We learned that, at least right now, the type of http message doesn't really matter. Let's inspect our request:
8.png
Hmmm, we also don't really have any kind of URI matcher in our handler.
Shall we test it? I know you would say "For sure.", great.
I told you about what to do, I told you about parameterized tests... Go on and try for yourself! You'll find a solution in the git repository.
Fast-forward: We can throw in any kind of string since the HttpHandler has yet no mechanism for it.
It might be a good idea to introduce one.
carbon(1).png
So far so good. But I bet there will not always be 15% of your colleagues on vacation. Let's move it to the parameter:
8.png
This snippet will not work, since HttpHandler expects (Request) -> Response.
Thus, we will convert it to a function (let IntelliJ IDEA do the work!).
6.png
I chose to move it to an interface that I can easily fake in a test, so we don't have to take care of the underlying implementation.
10.png
But there are also other possibilities. I strongly recommend reading Uberto Barbini's article about the invoke function. Summed up, it's possible to have a class inheriting from a function in Kotlin! Here's an example of Uberto's version:

Feature 2: Absence Of An Employee

To get the absence of a specific employee, we have to extract some kind of information from the request.
No worries, it's simple. Inside an HttpHandler, we can query the needed parameter from the request as follows:
carbon.png
That will do. But it looks kinda odd, no? A little hint: We will clean this up in the next article. To verify the provided id, we need some kind of repository.
Usually, you would want to define your own type UserId instead of using Int. Keep that in mind, we will come back to that.

Our final implementation of the handlers looks like that:
7.png
You can see that we declared employeeId as nullable. That might work, but we will learn about a better solution in the next article.
Having all handlers in a single file would quickly become unorganized. Having one point where all of them are grouped can be quite beneficial. Let's look into that.


Routing HttpHandlers

As already mentioned, I want to group all of our requests together at one place. Http4k provides use with the routes() function that takes HttpHandlers. Perfect match for our objective.
Nesting is of course also possible:
5.png

What's next?

And that's basically it! We've made quite some progression on our way to understanding http4k concepts. Next time, we will look into Lenses. A powerful feature that I wasn't aware of at all beforehand.

If you have any kind of feedback, I would love to hear it! Was it to detailed? Should I explain things more granular? Any feedback is welcome. You can find me on Twitter or message me via email.

Stay tuned and have a good day, Philipp


TL;DR

A simple HttpHandler:

A HttpHandler for a specific http method:
carbon(1).png
Extracting a parameter from the URI:
4.png

Routing:
5.png