Back to Home

Go Middleware - Part 5

  • March 17, 2019 |
  • 3 min read

In this fifth and final part of the Go middleware tutorial series, we'll use what we've learned to create a more structured API example that includes basic request logging, authorization, and response formatting.

Middleware will help simplify our API code and promote the single responsibility principle.

Part 5 - API Middleware Example

The code for this tutorial can be found here: https://github.com/benjohns1/go-middleware-example/tree/master/apiexample

API Example Code

Rather than building up the code from scratch as in previous tutorials, we're going to start with the completed code and discuss each component. The project is structured as follows:

Business Logic

This is where the meat and potatoes of the application reside. All the logical rules that the business, client, or user expects from the system should be driven from here without depending on implementation details such as HTTP, DB technology, etc. It's a great idea to write your business logic as decoupled as possible from infrastructure concerns, as has been recommended time and time again with architectural patterns like The Clean Architecture, Hexagonal Architecture, and Onion Architecture.

businessdomain/businesslogic.go:

In this example, we're not actually doing anything except returning a static struct, but notice that this package does not depend on anything related to the API delivery mechanism or database; it could easily be reused for a terminal or GUI application, for example.

Middleware Chain

Now for the API infrastructure: this is where the recursive chain style of middleware is implemented as described in Part 2 of this series. This could be replaced by any of the variants we've discussed or by one of the many router/mux packages available.

middleware/chain.go:

The Factory type defines a valid function that can be chained as middleware.

Logging Middleware

Similar to what we've shown in previous examples, this file contains HTTP request logging middleware.

middleware/logger.go:

The Logger function is of type Factory so it can be used directly as a middleware function. We're also implementing a custom WriteHeader function to capture the status code as described in Part 4.

Authorization Middleware

This middleware provides two strategies for authorization:

  1. Random Auth - randomly reject or accept a request (example purposes only!)
  2. Public Auth - always authorized

middleware/auth.go:

The Auth function accepts an auth strategy function as a parameter to determine whether the user is authorized, and returns a Factory function that can be chained as middleware.

Putting It All Together

Each of the previous files contain a specific and unique responsibility, and our business logic has no dependency on the API delivery mechanism or infrastructure. Let's put it all together into one informative (but... probably useless) API!

main.go:

Our main function creates two routes, each using a different auth strategy:

  1. localhost:8080/api/v1/random/
  2. localhost:8080/api/v1/public/

The requestHandler function calls the business logic and transforms the return value into an appropriate HTTP response. Notice again that the business logic knows nothing about the transport mechanism; the final data format and transport type is handled here. This could be extended to allow additional data formats and more complex transformation steps using the middleware techniques we've just learned.

This concludes the Go Middleware series. Now go forth a conqueror and win great API victories!

Go Middleware - Part 4

Related Posts

The essential design concepts I use when developing an evolvable, distributed system.

Read More

How can we continuously integrate small changes while practicing acceptance test-driven development?

Read More

TDD and Testing Behavior

January 24, 2024

The importance of testing behavior when using test-driven development

Read More

When is it appropriate to use centralized orchestration versus event-driven choreography?

Read More

When defining a business problem and planning its solution, keep the two conversations separate...

Read More

Modern message brokers provide many important benefits to a distributed system...

Read More

Printable cheat sheets to help remember some of Uncle Bob's valuable contributions to the industry

Read More

Why Terraform?

December 25, 2019

Terraform leads the way in the infrastructure-as-code world...

Read More

I was looking for a quick and easy way to put together a personal static site and...

Read More

A few weeks ago, I decided to try Svelte's Sapper framework to handle the front-end of a simple app...

Read More

After years of consulting, I find myself continually coming back to three basic principles of system design...

Read More

Go Middleware - Part 4

February 24, 2019

In this fourth part of the Go middleware tutorial series, we'll discuss passing custom state along the request chain.

Read More

Go Middleware - Part 3

February 15, 2019

In this third part of the Go middleware tutorial series, we'll quickly look at a common variant on the recursive middleware implementation from part 2.

Read More

Go Middleware - Part 2

February 9, 2019

In this second part of the Go middleware tutorial series, we'll cover a recursive approach that provides a couple benefits beyond the simple loop chain example from part 1.

Read More

Go Middleware - Part 1

February 6, 2019

This is the first in a series of simple tutorials explaining the usage of HTTP middleware in Go.

Read More

How do we manage the architectural complexity that inevitably arises from using cloud services?

Read More

This Old Blog

January 20, 2019

I've decided to resurrect this old blog to publish some nuggets about software architecture and development, and perhaps...

Read More

Drupal 6 Theme Info Error

September 14, 2011

Recently one of my client sites had an issue where the custom theme info was corrupted...

Read More

Here's a slight modification to the handy Google Bookmarks Bookmarklet...

Read More

While building a Drupal site for one of my clients, I was having a heck of a time integrating...

Read More