Skip to content

Commit

Permalink
feat: migrate from Gin to Echo framework
Browse files Browse the repository at this point in the history
- Migrated from Gin to Echo framework to improve performance and routing
  capabilities.
- Updated `go.mod` and `go.sum` to include Echo and its dependencies.
- Refactored route definitions and handlers to use Echo's API.
- Improved error handling and assertions in test cases using Testify.
- Introduced middleware for host-based routing with secure handling for
  unknown hosts.
  • Loading branch information
infuzu-yidisprei committed Sep 18, 2024
1 parent e2e9d50 commit b6f030f
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 29 deletions.
10 changes: 9 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@ module github.com/YidiDev/echo-host-route

go 1.23.0

require github.com/labstack/echo/v4 v4.12.0
require (
github.com/labstack/echo/v4 v4.12.0
github.com/stretchr/testify v1.8.4
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
Expand Down Expand Up @@ -27,5 +29,9 @@ golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
62 changes: 62 additions & 0 deletions hostroute.go
Original file line number Diff line number Diff line change
@@ -1 +1,63 @@
package hostroute

import (
"fmt"
"github.com/labstack/echo/v4"
"net/http"
)

type HostConfig struct {
Host string
Prefix string
RouterFactory func(e *echo.Group)
}

func createHostBasedRoutingMiddleware(hostConfigMap map[string]*HostConfig, genericHosts map[string]bool, secureAgainstUnknownHosts bool) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
host := c.Request().Host

if _, exists := hostConfigMap[host]; exists {
return next(c)
}

if _, exists := genericHosts[host]; exists {
return next(c)
}

if secureAgainstUnknownHosts {
return c.String(http.StatusNotFound, "Unknown host")
}

return next(c)
}
}
}

func SetupHostBasedRoutes(e *echo.Echo, hostConfigs []HostConfig, genericHosts []string, secureAgainstUnknownHosts bool) {
hostConfigMap := make(map[string]*HostConfig)
genericHostsMap := stringSliceToMap(genericHosts)

for i := range hostConfigs {
group := e.Host(hostConfigs[i].Host)
hostConfigs[i].RouterFactory(group)

if hostConfigs[i].Prefix != "" {
group = e.Group(fmt.Sprintf("/%s", hostConfigs[i].Prefix))
hostConfigs[i].RouterFactory(group)
}

hostConfigMap[hostConfigs[i].Host] = &hostConfigs[i]
}

e.Use(createHostBasedRoutingMiddleware(hostConfigMap, genericHostsMap, secureAgainstUnknownHosts))

}

func stringSliceToMap(slice []string) map[string]bool {
result := make(map[string]bool)
for _, s := range slice {
result[s] = true
}
return result
}
44 changes: 16 additions & 28 deletions hostroute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,22 @@ func defineHost1Routes(g *echo.Group) {
})
}

func defineHost2Routes(rg *gin.RouterGroup) {
rg.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello from host2")
func defineHost2Routes(rg *echo.Group) {
rg.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello from host2")
})
rg.GET("/hi", func(c *gin.Context) {
c.String(http.StatusOK, "Hi from host2")
rg.GET("/hi", func(c echo.Context) error {
return c.String(http.StatusOK, "Hi from host2")
})
}

func noRouteHandler(c *gin.Context) {
c.String(http.StatusNotFound, "No known route")
func noRouteHandler(c echo.Context) error {
return c.String(http.StatusNotFound, "No known route")
}

func TestHostBasedRouting(t *testing.T) {
gin.SetMode(gin.TestMode)

r := gin.Default()
r.NoRoute(noRouteHandler)
r := echo.New()
r.RouteNotFound("/*", noRouteHandler)

hostConfigs := []HostConfig{
{Host: "host1.com", Prefix: "1", RouterFactory: defineHost1Routes},
Expand Down Expand Up @@ -87,24 +85,18 @@ func TestHostBasedRouting(t *testing.T) {

body := make([]byte, resp.ContentLength)
_, err = resp.Body.Read(body)
if err != nil {
return
}
assert.NoError(t, err)

assert.Equal(t, tt.statusCode, resp.StatusCode)
assert.Equal(t, tt.expected, string(body))
err = resp.Body.Close()
if err != nil {
return
}
assert.NoError(t, err)
}
}

func TestHostBasedRoutingWithoutSecureAgainstUnknownHosts(t *testing.T) {
gin.SetMode(gin.TestMode)

r := gin.Default()
r.NoRoute(noRouteHandler)
r := echo.New()
r.RouteNotFound("/*", noRouteHandler)

hostConfigs := []HostConfig{
{Host: "host1.com", Prefix: "1", RouterFactory: defineHost1Routes},
Expand Down Expand Up @@ -159,16 +151,12 @@ func TestHostBasedRoutingWithoutSecureAgainstUnknownHosts(t *testing.T) {

body := make([]byte, resp.ContentLength)
_, err = resp.Body.Read(body)
if err != nil {
return
}
assert.NoError(t, err)

assert.Equal(t, tt.statusCode, resp.StatusCode)
assert.Equal(t, tt.expected, string(body))

err = resp.Body.Close()
if err != nil {
return
}
assert.NoError(t, err)

}
}

0 comments on commit b6f030f

Please sign in to comment.