package main
import (
"context""os""os/signal""time""github.com/labstack/echo/v4")
var PORT string = ":8080"funcmain() {
// create echo server
e := echo.New()
e.HideBanner = true// add middleware
err :=setupMiddleware(e)
if err !=nil {
panic(err)
}
// setup router
err = setupRouter(e)
if err !=nil {
panic(err)
}
//
// code to run server and enable graceful shutdown
//
// Start server with background goroutine
gofunc() {
if err := e.Start(PORT); err !=nil {
e.Logger.Info("shutting down the server")
}
}()
// Wait for interrupt signal to gracefully shutdown the server with
// a timeout of 10 seconds.
quit :=make(chan os.Signal)
signal.Notify(quit, os.Interrupt)
// wait on a quit signal
<-quit
// start the shutdown process
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defercancel()
if err := e.Shutdown(ctx); err !=nil {
e.Logger.Fatal(err)
}
}
templates/router.go
package main
import (
"net/http""github.com/labstack/echo/v4""github.com/prometheus/client_golang/prometheus/promhttp" {{ ifgt (len .SERVER.Routes ) 1 }}
"{{ .SERVER.GoModule }}/routes" {{ end }}
)
funcsetupRouter(e *echo.Echo) error {
// Internal routes
e.GET("/internal/alive", func(c echo.Context) error {
return c.NoContent(http.StatusOK)
})
{{ if .SERVER.Prometheus }}
h := promhttp.Handler()
e.GET("/internal/metrics", func(c echo.Context) error {
h.ServeHTTP(c.Response(), c.Request())
returnnil })
{{ end }}
// Application routes group
g := e.Group("")
// Register the routes
{{ range$ROUTE := .SERVER.Routes -}}
routes.{{ $ROUTE.Name }}Routes(g)
{{ end }}
returnnil}
templates/middleware.go
package main
import (
"github.com/labstack/echo/v4""github.com/labstack/echo/v4/middleware""github.com/labstack/echo-contrib/prometheus")
funcsetupMiddleware(e *echo.Echo) error {
// setup recovery middleware
e.Use(middleware.Recover())
// setup logging middleware
e.Use(middleware.Logger())
{{ if .SERVER.Prometheus }}
// Setup metrics middleware
p := prometheus.NewPrometheus("{{ .SERVER.Name }}", nil)
e.Use(p.HandlerFunc)
{{ end }}
returnnil}
Repeated and Partial Templates
We separate the handler into a template which uses the partial.
This is for demonstration purpose here and will be more useful
in the “full-example” section where the implementation is more complete.
templates/route.go
package routes
import (
"net/http""github.com/labstack/echo/v4")
// {{ .ROUTE.Name }}Routes sets up the routes in a router Group
func {{ .ROUTE.Name }}Routes(G *echo.Group) {
g := G.Group("{{ .ROUTE.Path }}{{ range $PATH := .ROUTE.Params }}/:{{$PATH}}{{ end }}")
g.{{.ROUTE.Method}}( "", {{.ROUTE.Name}}Handler)
// we'll handle sub-routes here in "full-example"
}
// Handler implementation is in a partial template
{{ template "handler.go" .ROUTE }}
partials/handler.go
{{ $ROUTE := . }}
func {{ $ROUTE.Name }}Handler(c echo.Context) (err error) {
// process any path and query params
{{ range$P :=$ROUTE.Params }}
{{ $P }} := c.Param("{{ $P }}")
{{ end }}
{{ range$Q :=$ROUTE.Query }}
{{ $Q }} := c.QueryParam("{{ $Q }}")
{{ end }}
{{ if$ROUTE.Body }}
// custom body
{{ $ROUTE.Body }}
{{ else }}
// default body
c.String(http.StatusNotImplemented, "Not Implemented")
{{ end }}
returnnil}
Rendered Output Files
Here we can see the result of code generation for a sample of the files.
We will actually generate these in the next section.
They are provided here so you can see the input / output pairs on a single page.
package main
import (
"net/http""github.com/labstack/echo/v4""github.com/prometheus/client_golang/prometheus/promhttp""hof.io/docs/example/routes")
funcsetupRouter(e *echo.Echo) error {
// Internal routes
e.GET("/internal/alive", func(c echo.Context) error {
return c.NoContent(http.StatusOK)
})
h := promhttp.Handler()
e.GET("/internal/metrics", func(c echo.Context) error {
h.ServeHTTP(c.Response(), c.Request())
returnnil })
// Application routes group
g := e.Group("")
// Register the routes
routes.EchoQRoutes(g)
routes.EchoPRoutes(g)
routes.HelloRoutes(g)
returnnil}
output/routes/Hello.go
package routes
import (
"net/http""github.com/labstack/echo/v4")
// HelloRoutes sets up the routes in a router Group
funcHelloRoutes(G *echo.Group) {
g := G.Group("/hello")
g.GET("", HelloHandler)
// we'll handle sub-routes here in "full-example"
}
// Handler implementation is in a partial template
funcHelloHandler(c echo.Context) (err error) {
// process any path and query params
msg := c.QueryParam("msg")
// custom body
if msg =="" {
msg = "hello world" }
c.String(http.StatusOK, msg)
returnnil}