Creating custom middleware

Middleware functions are just functions that take in a next function and return a function. We are able to do this in Go because functions are first-class citizens, and they can be used as variables. By using this idea, we are able to use regular functions as parameters to middleware functions.

In order to create custom middleware for use within the Echo framework, all we need to do is create a function that conforms to the echo.MiddlewareFunc type, which is as follows:

type MiddlewareFunc func(HandlerFunc) HandlerFunc

The echo.MiddlewareFunc type which defines what a middleware should be is simply a function which takes a next parameter and returns a handler function. In the following example, we are creating a custom middleware which will assign a unique ID to every request that is made, and set our generated unique ID into the echo.Context for use in later stages of the request pipeline. The following code is found in the $GOPATH/src/github.com/PacktPublishing/Echo-Essentials/chapter4/middlewares/request_id.go directory within our project:

package middlewares

import (
        "github.com/labstack/echo"
        uuid "github.com/satori/go.uuid"
)

const (
        requestIDContextKey = "request_id_context_key"
)
func RequestIDMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
  return echo.HandlerFunc(func(c echo.Context) error {
    requestID := uuid.NewV4()
    c.Logger().Infof("RequestID: %s", requestID)
    c.Set(RequestIDContextKey, requestID)
    return next(c)
  })
}

A middleware that performs this functionality should be inserted early in the middleware call chain, in my opinion. I feel it needs to be inserted early because every single request that comes into the system should have a unique ID. For that reason, it makes sense that this middleware be a Pre-Middleware, which is processed before any routing occurs. In order to add this middleware as a Pre-Middleware so that every request before routing is performed gets a unique request ID, we add the following line to our $GOPATH/src/github.com/PacktPublishing/Echo-Essentials/chapter4/cmd/service/main.go main entrypoint:

 e.Pre(middlewares.RequestIDMiddleware) 

At this point, we are able to pull this newly generated unique request ID from the context inside any of our handlers. The power of echo.Context will be explored within Chapter 4, Developing Echo Projects, but for our sake, echo.Context is a place where state can be stored, and we can create the said state from within our middleware functions. The following is an example of how we can retrieve the RequestID that we created in the middlewares.RequestIDMiddleware from handlers.HealthCheck:

// HealthCheck - Health Check Handler
func HealthCheck(c echo.Context) error {
    if requestID, ok := c.Get(middlewares.RequestIDContextKey).(uuid.UUID); ok {
c.Logger().Infof("RequestID: %s", requestID)
}
resp := renderings.HealthCheckResponse{ Message: "Everything is good!", } return c.JSON(http.StatusOK, resp) }

As you can see, when we query the /health-check endpoint, we get a new debug entry which shows the RequestID that was generated by our middleware, completely accessible from our handler:

{"time":"2018-03-15T23:52:55.19648893-04:00","level":"INFO","prefix":"echo","file":"echo.go","line":"478","message":"RequestID: bc9b2366-22bc-4480-a8e4-d325f1516003"}

Now that we have this simple custom middleware, we can start looking at some of the contributed middleware functions that come with the Echo framework. As mentioned previously, Echo comes with many useful middleware solutions that provide much functionality to make our web application development easier.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.158.32