Skip to content

Commit

Permalink
Merge pull request #11 from kareemmahlees:fiber-to-chi
Browse files Browse the repository at this point in the history
Migrate from fiber to chi
  • Loading branch information
kareemmahlees authored Apr 24, 2024
2 parents a83c582 + c71bc22 commit 816a1de
Show file tree
Hide file tree
Showing 17 changed files with 530 additions and 699 deletions.
13 changes: 8 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.20
github.com/spf13/cobra v1.8.0
github.com/swaggo/swag v1.16.1
github.com/swaggo/swag v1.16.3
github.com/testcontainers/testcontainers-go v0.30.0
github.com/testcontainers/testcontainers-go/modules/mysql v0.27.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.30.0
Expand All @@ -37,6 +37,7 @@ require (
github.com/docker/go-units v0.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/go-chi/chi/v5 v5.0.12 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
Expand Down Expand Up @@ -66,6 +67,8 @@ require (
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/http-swagger v1.3.4 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/urfave/cli/v2 v2.25.5 // indirect
Expand All @@ -91,10 +94,10 @@ require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.8.0
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/spec v0.20.9 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.17.8 // indirect
Expand Down
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
Expand All @@ -71,18 +73,26 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
Expand Down Expand Up @@ -242,10 +252,16 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
github.com/swaggo/http-swagger v1.3.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww=
github.com/swaggo/http-swagger v1.3.4/go.mod h1:9dAh0unqMBAlbp1uE2Uc2mQTxNMU/ha4UbucIg1MFkQ=
github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg=
github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto=
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
github.com/testcontainers/testcontainers-go v0.30.0 h1:jmn/XS22q4YRrcMwWg0pAwlClzs/abopbsBzrepyc4E=
github.com/testcontainers/testcontainers-go v0.30.0/go.mod h1:K+kHNGiM5zjklKjgTtcrEetF3uhWbMUyqAQoyoh8Pf0=
github.com/testcontainers/testcontainers-go/modules/mysql v0.27.0 h1:6p/o/bAZPcFiBWTd71umQmj/i4L6ipVK3B2ZJBqn5HM=
Expand Down Expand Up @@ -321,6 +337,7 @@ golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
Expand Down
42 changes: 24 additions & 18 deletions internal/handlers/dbHandlers.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package handlers

import (
"github.com/gofiber/fiber/v2"
"net/http"

"github.com/go-chi/chi/v5"
"github.com/kareemmahlees/meta-x/internal/db"
"github.com/kareemmahlees/meta-x/lib"
"github.com/kareemmahlees/meta-x/models"
Expand All @@ -11,15 +13,15 @@ type DBHandler struct {
storage db.DatabaseExecuter
}

// TODO: change the interface
func NewDBHandler(storage db.DatabaseExecuter) *DBHandler {
return &DBHandler{storage}
}

func (dh *DBHandler) RegisterRoutes(app *fiber.App) {
dbGroup := app.Group("database")
dbGroup.Get("", dh.handleListDatabases)
dbGroup.Post("", dh.handleCreateDatabase)
func (dh *DBHandler) RegisterRoutes(r *chi.Mux) {
r.Route("/database", func(r chi.Router) {
r.Get("/", dh.handleListDatabases)
r.Post("/", dh.handleCreateDatabase)
})
}

// Lists databases
Expand All @@ -29,30 +31,34 @@ func (dh *DBHandler) RegisterRoutes(app *fiber.App) {
// @router /database [get]
// @produce json
// @success 200 {object} models.ListDatabasesResp
func (dh *DBHandler) handleListDatabases(c *fiber.Ctx) error {
func (dh *DBHandler) handleListDatabases(w http.ResponseWriter, r *http.Request) {
dbs, err := dh.storage.ListDBs()

if err != nil {
return lib.InternalServerErr(c, err.Error())
httpError(w, http.StatusInternalServerError, err.Error())
return
}
return c.JSON(models.ListDatabasesResp{Databases: dbs})
writeJson(w, models.ListDatabasesResp{Databases: dbs})
}

func (dh *DBHandler) handleCreateDatabase(c *fiber.Ctx) error {
func (dh *DBHandler) handleCreateDatabase(w http.ResponseWriter, r *http.Request) {
var payload models.CreatePgMySqlDBPayload

if err := c.BodyParser(&payload); err != nil {
return lib.UnprocessableEntityErr(c, err.Error())
if err := parseBody(r.Body, &payload); err != nil {
httpError(w, http.StatusUnprocessableEntity, err.Error())
return
}

if errs := lib.ValidateStruct(payload); len(errs) > 0 {
return lib.BadRequestErr(c, errs)
httpError(w, http.StatusBadRequest, errs)
return
}

err := dh.storage.CreateDB(payload.Name)

if err != nil {
return lib.InternalServerErr(c, err.Error())
if err := dh.storage.CreateDB(payload.Name); err != nil {
httpError(w, http.StatusInternalServerError, err.Error())
return
}
return c.Status(201).JSON(models.SuccessResp{Success: true})

w.WriteHeader(http.StatusCreated)
writeJson(w, models.SuccessResp{Success: true})
}
82 changes: 33 additions & 49 deletions internal/handlers/dbHandlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net/http/httptest"
"testing"

"github.com/gofiber/fiber/v2"
"github.com/go-chi/chi/v5"
"github.com/kareemmahlees/meta-x/models"
"github.com/kareemmahlees/meta-x/utils"
"github.com/stretchr/testify/suite"
Expand All @@ -27,49 +27,37 @@ func (md *MockDBExecutor) CreateDB(dbName string) error {

type DBHandlerTestSuite struct {
suite.Suite
app *fiber.App
r *chi.Mux
handler *DBHandler
}

func (suite *DBHandlerTestSuite) SetupSuite() {
app := fiber.New()
r := chi.NewRouter()
storage := NewMockDBExecutor()

handler := NewDBHandler(storage)
handler.RegisterRoutes(app)
handler.RegisterRoutes(r)

suite.app = app
suite.r = r
suite.handler = handler
}

func (suite *DBHandlerTestSuite) TestRegisterRoutes() {
assert := suite.Assert()

var routes []utils.FiberRoute
for _, route := range suite.app.GetRoutes() {
routes = append(routes, utils.FiberRoute{
Method: route.Method,
Path: route.Path,
})
var routes []string
for _, route := range suite.r.Routes() {
routes = append(routes, route.Pattern)
}

assert.Contains(routes, utils.FiberRoute{
Method: "GET",
Path: "/database",
})

assert.Contains(routes, "/database/*")
}

func (suite *DBHandlerTestSuite) TestHandleListDatabases() {
assert := suite.Assert()

req := httptest.NewRequest("GET", "http://localhost:5522/database", nil)

resp, _ := suite.app.Test(req)
defer resp.Body.Close()
payload := utils.DecodeBody[models.ListDatabasesResp](resp.Body)

assert.Equal(resp.StatusCode, fiber.StatusOK)
assert.NotEmpty(payload.Databases)

assert.HTTPSuccess(suite.handler.handleListDatabases, http.MethodGet, "/database", nil)
assert.HTTPBodyContains(suite.handler.handleListDatabases, http.MethodGet, "/database", nil, "test")
}

func (suite *DBHandlerTestSuite) TestHandleCreateDatabase() {
Expand All @@ -80,40 +68,36 @@ func (suite *DBHandlerTestSuite) TestHandleCreateDatabase() {
passingBody, _ := utils.EncodeBody(models.CreatePgMySqlDBPayload{
Name: "testing",
})
passing := utils.RequestTesting[models.SuccessResp]{
ReqMethod: http.MethodPost,
ReqUrl: "/database",
ReqBody: passingBody,
}

decodedRes, rawRes := passing.RunRequest(suite.app)
assert.Equal(rawRes.StatusCode, fiber.StatusCreated)
req, _ := http.NewRequest(http.MethodPost, "/database", passingBody)
rr := httptest.NewRecorder()

handler := http.HandlerFunc(suite.handler.handleCreateDatabase)
handler.ServeHTTP(rr, req)
assert.Equal(rr.Code, http.StatusCreated)

decodedRes := utils.DecodeBody[models.SuccessResp](rr.Result().Body)
assert.True(decodedRes.Success)

})

t.Run("should fail unproccessable entity", func(t *testing.T) {
failingUnprocessableEntity := utils.RequestTesting[models.ErrResp]{
ReqMethod: http.MethodPost,
ReqUrl: "/database",
}
decodedRes, rawRes := failingUnprocessableEntity.RunRequest(suite.app)
assert.Equal(http.StatusUnprocessableEntity, rawRes.StatusCode)
assert.Contains(decodedRes.Message, "Unprocessable Entity")
assert.HTTPError(suite.handler.handleCreateDatabase, http.MethodPost, "/database", nil)
})

t.Run("should fail bad request", func(t *testing.T) {
failingBadRequestBody, _ := utils.EncodeBody(models.CreatePgMySqlDBPayload{
Name: "",
})
failingBadRequest := utils.RequestTesting[models.ErrResp]{
ReqMethod: http.MethodPost,
ReqUrl: "/database",
ReqBody: failingBadRequestBody,
}
decodedRes, rawRes = failingBadRequest.RunRequest(suite.app)
assert.Equal(http.StatusBadRequest, rawRes.StatusCode)
assert.Len(decodedRes.Message, 1)
req, _ := http.NewRequest(http.MethodPost, "/database", failingBadRequestBody)
rr := httptest.NewRecorder()

})
handler := http.HandlerFunc(suite.handler.handleCreateDatabase)
handler.ServeHTTP(rr, req)
assert.Equal(rr.Code, http.StatusBadRequest)

decodedRes := utils.DecodeBody[models.ErrResp](rr.Result().Body)
assert.Len(decodedRes.Message, 1)
})
}

func TestDBHandlerTestSuite(t *testing.T) {
Expand Down
44 changes: 22 additions & 22 deletions internal/handlers/defaultHandler.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
package handlers

import (
"net/http"
"time"

"github.com/gofiber/fiber/v2"
"github.com/kareemmahlees/meta-x/internal/db"
"github.com/go-chi/chi/v5"
)

type DefaultHandler struct {
storage *db.Storage
}
type DefaultHandler struct{}

func NewDefaultHandler(storage *db.Storage) *DefaultHandler {
return &DefaultHandler{storage}
func NewDefaultHandler() *DefaultHandler {
return &DefaultHandler{}
}

func (h *DefaultHandler) RegisterRoutes(app *fiber.App) {
app.Get("/health", h.healthCheck)
app.Get("/", h.apiInfo)
func (h *DefaultHandler) RegisterRoutes(r *chi.Mux) {
r.Get("/health", h.healthCheck)
r.Get("/", h.apiInfo)
}

type HealthCheckResult struct {
Expand All @@ -31,15 +29,17 @@ type HealthCheckResult struct {
// @tags default
// @router /health [get]
// @success 200 {object} HealthCheckResult
func (h *DefaultHandler) healthCheck(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"date": time.Now()})
func (h *DefaultHandler) healthCheck(w http.ResponseWriter, r *http.Request) {
writeJson(w, map[string]time.Time{
"date": time.Now(),
})
}

type APIInfoResult struct {
Author string
Year int
Contact string
Repo string
Author string `json:"author"`
Year int `json:"yeaer"`
Contact string `json:"contact"`
Repo string `json:"repo"`
}

// Get info about the api
Expand All @@ -49,11 +49,11 @@ type APIInfoResult struct {
// @tags default
// @router / [get]
// @success 200 {object} APIInfoResult
func (h *DefaultHandler) apiInfo(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"author": "Kareem Ebrahim",
"year": 2023,
"contact": "[email protected]",
"repo": "https://github.com/kareemmahlees/meta-x",
func (h *DefaultHandler) apiInfo(w http.ResponseWriter, r *http.Request) {
writeJson(w, APIInfoResult{
Author: "Kareem Ebrahim",
Year: 2024,
Contact: "[email protected]",
Repo: "https://github.com/kareemmahlees/meta-x",
})
}
Loading

0 comments on commit 816a1de

Please sign in to comment.