A Basic HTTP Server
Now that the skeleton structure for our project is in place, let’s focus our attention on getting a HTTP server up and running.
To start with, we’ll configure our server to have just one endpoint:
/v1/healthcheck. This endpoint will return some basic information about our API, including its current version number and operating environment (development, staging, production, etc.).
|/v1/healthcheck||healthcheckHandler||Show application information|
If you’re following along, open up the
cmd/api/main.go file and replace the ‘hello world’ application with the following code:
Creating the healthcheck handler
The next thing we need to do is create the
healthcheckHandler method for responding to HTTP requests. For now, we’ll keep the logic in this handler really simple and have it return a plain-text response containing three pieces of information:
- A fixed
- The API version from the hard-coded
- The operating environment name from the
Go ahead and create a new
And then add the following code:
The important thing to point out here is that
healthcheckHandler is implemented as a method on our
This is an effective and idiomatic way to make dependencies available to our handlers without resorting to global variables or closures — any dependency that the
healthcheckHandler needs can simply be included as a field in the
application struct when we initialize it in
We can see this pattern already being used in the code above, where the operating environment name is retrieved from the
application struct by calling
OK, let’s try this out. Make sure that all your changes are saved, then use the
go run command again to execute the code in the
cmd/api package. You should see a log message confirming that the HTTP server is running, similar to this:
While the server is running, go ahead and try visiting
localhost:4000/v1/healthcheck in your web browser. You should get a response from the
healthcheckHandler which looks like this:
Or alternatively, you can use
curl to make the request from your terminal:
If you want, you can also verify that the command-line flags are working correctly by specifying alternative
env values when starting the application. When you do this, you should see the contents of the log message change accordingly. For example:
APIs which support real-world businesses and users often need to change their functionality and endpoints over time — sometimes in a backwards-incompatible way. So, to avoid problems and confusion for clients, it’s a good idea to always implement some form of API versioning.
There are two common approaches to doing this:
- By prefixing all URLs with your API version, like
- By using custom
Content-Typeheaders on requests and responses to convey the API version, like
From a HTTP semantics point of view, using headers to convey the API version is the ‘purer’ approach. But from a user-experience point of view, using a URL prefix is arguably better. It makes it possible for developers to see which version of the API is being used at a glance, and it also means that the API can still be explored using a regular web browser (which is harder if custom headers are required).
Throughout this book we’ll version our API by prefixing all the URL paths with
/v1/ — just like we did with the
/v1/healthcheck endpoint in this chapter.