I am looking at the example for JWT middleware in Go.
In my API backend as-is, I use the Echo framework (specifically, based off this example). This is no big issue itself, as Echo has a very useful echo.WrapMiddleware()
function for turning regular bare HTTP handler middlewares into Echo ones. I literally just add the following in jwt.go
:
func EchoEnsureValidToken() (echo.MiddlewareFunc, error) {
mw := echo.WrapMiddleware(EnsureValidToken())
return mw, nil
}
and then use it in my app as per normal. However, I’m running into an issue with my handler functions.
main.go:
package main
import (
"log"
"os"
database "tlmgateway/db"
_ "tlmgateway/docs"
"tlmgateway/handlers"
"tlmgateway/logger"
"tlmgateway/middlewares"
"tlmgateway/services"
"tlmgateway/stores"
"go.uber.org/zap"
)
var GO_ENV = os.Getenv("GO_ENV")
// @title Go clean echo API v1
// @version 1.0
// @description This is a sample server.
// @termsOfService http://swagger.io/terms/
// @host localhost:3000
// @BasePath /
// @schemes http
func main() {
err := logger.New()
if err != nil {
log.Fatal(err)
}
db, err := database.New(GO_ENV == "development")
if err != nil {
logger.Fatal("failed to connect to the database", zap.Error(err))
}
e := handlers.Echo()
s := stores.New(db)
ss := services.New(s)
h := handlers.New(ss)
jwtCheck, err := middlewares.EchoEnsureValidToken()
if err != nil {
logger.Fatal("failed to set JWT middleware", zap.Error(err))
}
handlers.SetDefault(e)
handlers.SetApi(e, h, jwtCheck)
PORT := os.Getenv("PORT")
if PORT == "" {
PORT = "3001"
}
logger.Fatal("failed to start server", zap.Error(e.Start(":"+PORT)))
}
But in Echo, the routing and handlers are done a bit differently:
package handlers
import (
"net/http"
"strings"
"repo/services"
"repo/utils"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
echoSwagger "github.com/swaggo/echo-swagger"
)
type Handlers struct {
RecordHandler
}
func New(s *services.Services) *Handlers {
return &Handlers{
RecordHandler: &recordHandler{s.Record},
}
}
func SetDefault(e *echo.Echo) {
utils.SetHTMLTemplateRenderer(e)
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "OK")
})
e.GET("/healthcheck", HealthCheckHandler)
e.GET("/swagger/*", echoSwagger.WrapHandler)
}
func SetApi(e *echo.Echo, h *Handlers, m echo.MiddlewareFunc) {
g := e.Group("/api/v1")
g.Use(m)
// Organizations
g.GET("/record", h.RecordHandler.GetRecords)
}
func Echo() *echo.Echo {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Pre(middleware.RemoveTrailingSlash())
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"*"},
}))
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
Skipper: func(c echo.Context) bool {
return strings.Contains(c.Request().URL.Path, "swagger")
},
}))
return e
}
My issue is, these handlers simply take the Context and go from there. They’re defined like this:
GetRecords(c echo.Context) error
The question then is, how do I add something like ValidatedClaims and CustomClaims from the middleware function in the example to the context so that it can be used where I need to use it? The above code is more for illustration purposes, since the only implementation issue I’m having is “add validation results to context”.