Skip to content

Commit de8ab92

Browse files
author
Amine Afia
authored
Switch from Chi to Gin web framework (#79)
### TL;DR Migrated the API from Chi to Gin framework and updated related components. ### What changed? - Replaced Chi router with Gin in `cmd/api.go` - Updated API handlers to use Gin context - Modified middleware to work with Gin - Adjusted `api.go` to use Gin-compatible error handlers - Updated `Meta` struct to use `uint64` for `ChainId` - Changed `GetChainId` function to return `*big.Int` - Removed `api.go` file from `internal/handlers` package ### How to test? 1. Run the API server 2. Test all existing endpoints to ensure they work with the new Gin implementation 3. Verify that authentication middleware still functions correctly 4. Check that error handling and responses are consistent with the previous implementation ### Why make this change? The migration to Gin framework offers several benefits: - Improved performance and efficiency - Better support for middleware and routing - Enhanced request handling and parameter parsing - Simplified error management and response formatting This change aims to streamline the API implementation and potentially improve overall application performance.
1 parent 3fc7b21 commit de8ab92

File tree

8 files changed

+175
-140
lines changed

8 files changed

+175
-140
lines changed

api/api.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ package api
22

33
import (
44
"encoding/json"
5+
"math/big"
56
"net/http"
67
"reflect"
78
"strconv"
89
"strings"
910

10-
"github.com/go-chi/chi/v5"
11+
"github.com/gin-gonic/gin"
1112
"github.com/gorilla/schema"
1213
"github.com/rs/zerolog/log"
1314
)
@@ -29,13 +30,13 @@ type QueryParams struct {
2930
}
3031

3132
type Meta struct {
32-
ChainId *uint64 `json:"chain_id"`
33-
ContractAddress string `json:"address"`
34-
Signature string `json:"signature"`
35-
Page int `json:"page"`
36-
Limit int `json:"limit"`
37-
TotalItems int `json:"total_items"`
38-
TotalPages int `json:"total_pages"`
33+
ChainId uint64 `json:"chain_id"`
34+
ContractAddress string `json:"address"`
35+
Signature string `json:"signature"`
36+
Page int `json:"page"`
37+
Limit int `json:"limit"`
38+
TotalItems int `json:"total_items"`
39+
TotalPages int `json:"total_pages"`
3940
}
4041

4142
type QueryResponse struct {
@@ -58,14 +59,14 @@ func writeError(w http.ResponseWriter, message string, code int) {
5859
}
5960

6061
var (
61-
BadRequestErrorHandler = func(w http.ResponseWriter, err error) {
62-
writeError(w, err.Error(), http.StatusBadRequest)
62+
BadRequestErrorHandler = func(c *gin.Context, err error) {
63+
writeError(c.Writer, err.Error(), http.StatusBadRequest)
6364
}
64-
InternalErrorHandler = func(w http.ResponseWriter) {
65-
writeError(w, "An unexpected error occurred.", http.StatusInternalServerError)
65+
InternalErrorHandler = func(c *gin.Context) {
66+
writeError(c.Writer, "An unexpected error occurred.", http.StatusInternalServerError)
6667
}
67-
UnauthorizedErrorHandler = func(w http.ResponseWriter, err error) {
68-
writeError(w, err.Error(), http.StatusUnauthorized)
68+
UnauthorizedErrorHandler = func(c *gin.Context, err error) {
69+
writeError(c.Writer, err.Error(), http.StatusUnauthorized)
6970
}
7071
)
7172

@@ -97,13 +98,13 @@ func ParseQueryParams(r *http.Request) (QueryParams, error) {
9798
return params, nil
9899
}
99100

100-
func GetChainId(r *http.Request) (*uint64, error) {
101+
func GetChainId(c *gin.Context) (*big.Int, error) {
101102
// TODO: check chainId agains the chain-service to ensure it's valid
102-
chainId := chi.URLParam(r, "chainId")
103+
chainId := c.Param("chainId")
103104
chainIdInt, err := strconv.ParseUint(chainId, 10, 64)
104105
if err != nil {
105106
log.Error().Err(err).Msg("Error parsing chainId")
106107
return nil, err
107108
}
108-
return &chainIdInt, nil
109+
return big.NewInt(int64(chainIdInt)), nil
109110
}

cmd/api.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ package cmd
33
import (
44
"net/http"
55

6-
"github.com/rs/zerolog/log"
6+
"github.com/gin-gonic/gin"
77
"github.com/spf13/cobra"
88

9-
"github.com/go-chi/chi/middleware"
10-
"github.com/go-chi/chi/v5"
119
"github.com/thirdweb-dev/indexer/internal/handlers"
10+
"github.com/thirdweb-dev/indexer/internal/middleware"
1211
)
1312

1413
var (
@@ -23,16 +22,30 @@ var (
2322
)
2423

2524
func RunApi(cmd *cobra.Command, args []string) {
26-
var r *chi.Mux = chi.NewRouter()
27-
r.Use(middleware.Logger)
28-
r.Use(middleware.Recoverer)
29-
r.Use(middleware.RequestID)
25+
r := gin.New()
26+
r.Use(gin.Logger())
27+
r.Use(gin.Recovery())
3028

31-
handlers.Handler(r)
29+
root := r.Group("/:chainId")
30+
{
31+
root.Use(middleware.Authorization)
32+
// wildcard queries
33+
root.GET("/transactions", handlers.GetTransactions)
34+
root.GET("/events", handlers.GetLogs)
3235

33-
log.Info().Msg("Starting Server on port 3000")
34-
err := http.ListenAndServe(":3000", r)
35-
if err != nil {
36-
log.Error().Err(err).Msg("Error starting server")
36+
// contract scoped queries
37+
root.GET("/transactions/:to", handlers.GetTransactionsByContract)
38+
root.GET("/events/:contract", handlers.GetLogsByContract)
39+
40+
// signature scoped queries
41+
root.GET("/transactions/:to/:signature", handlers.GetTransactionsByContractAndSignature)
42+
root.GET("/events/:contract/:signature", handlers.GetLogsByContractAndSignature)
3743
}
44+
45+
r.GET("/health", func(c *gin.Context) {
46+
// TODO: implement a simple query before going live
47+
c.String(http.StatusOK, "ok")
48+
})
49+
50+
r.Run(":3000")
3851
}

go.mod

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ go 1.23
55
require (
66
github.com/ClickHouse/clickhouse-go/v2 v2.28.3
77
github.com/ethereum/go-ethereum v1.14.8
8-
github.com/go-chi/chi v1.5.5
9-
github.com/go-chi/chi/v5 v5.1.0
8+
github.com/gin-gonic/gin v1.10.0
109
github.com/go-redis/redis/v8 v8.11.5
1110
github.com/gorilla/schema v1.4.1
1211
github.com/hashicorp/golang-lru/v2 v2.0.7
@@ -23,7 +22,11 @@ require (
2322
github.com/beorn7/perks v1.0.1 // indirect
2423
github.com/bits-and-blooms/bitset v1.10.0 // indirect
2524
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
25+
github.com/bytedance/sonic v1.12.3 // indirect
26+
github.com/bytedance/sonic/loader v0.2.0 // indirect
2627
github.com/cespare/xxhash/v2 v2.3.0 // indirect
28+
github.com/cloudwego/base64x v0.1.4 // indirect
29+
github.com/cloudwego/iasm v0.2.0 // indirect
2730
github.com/consensys/bavard v0.1.13 // indirect
2831
github.com/consensys/gnark-crypto v0.12.1 // indirect
2932
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
@@ -32,23 +35,34 @@ require (
3235
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
3336
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
3437
github.com/fsnotify/fsnotify v1.7.0 // indirect
38+
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
39+
github.com/gin-contrib/sse v0.1.0 // indirect
3540
github.com/go-faster/city v1.0.1 // indirect
3641
github.com/go-faster/errors v0.7.1 // indirect
3742
github.com/go-ole/go-ole v1.3.0 // indirect
43+
github.com/go-playground/locales v0.14.1 // indirect
44+
github.com/go-playground/universal-translator v0.18.1 // indirect
45+
github.com/go-playground/validator/v10 v10.22.1 // indirect
46+
github.com/goccy/go-json v0.10.3 // indirect
3847
github.com/google/uuid v1.6.0 // indirect
3948
github.com/gorilla/websocket v1.4.2 // indirect
4049
github.com/hashicorp/hcl v1.0.0 // indirect
4150
github.com/holiman/uint256 v1.3.1 // indirect
4251
github.com/inconshreveable/mousetrap v1.1.0 // indirect
52+
github.com/json-iterator/go v1.1.12 // indirect
4353
github.com/klauspost/compress v1.17.9 // indirect
54+
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
55+
github.com/leodido/go-urn v1.4.0 // indirect
4456
github.com/magiconair/properties v1.8.7 // indirect
4557
github.com/mattn/go-colorable v0.1.13 // indirect
4658
github.com/mattn/go-isatty v0.0.20 // indirect
4759
github.com/mitchellh/mapstructure v1.5.0 // indirect
4860
github.com/mmcloughlin/addchain v0.4.0 // indirect
61+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
62+
github.com/modern-go/reflect2 v1.0.2 // indirect
4963
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
5064
github.com/paulmach/orb v0.11.1 // indirect
51-
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
65+
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
5266
github.com/pierrec/lz4/v4 v4.1.21 // indirect
5367
github.com/pkg/errors v0.9.1 // indirect
5468
github.com/prometheus/client_model v0.6.1 // indirect
@@ -67,15 +81,19 @@ require (
6781
github.com/supranational/blst v0.3.11 // indirect
6882
github.com/tklauser/go-sysconf v0.3.12 // indirect
6983
github.com/tklauser/numcpus v0.6.1 // indirect
84+
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
85+
github.com/ugorji/go/codec v1.2.12 // indirect
7086
github.com/yusufpapurcu/wmi v1.2.3 // indirect
7187
go.opentelemetry.io/otel v1.26.0 // indirect
7288
go.opentelemetry.io/otel/trace v1.26.0 // indirect
7389
go.uber.org/multierr v1.11.0 // indirect
74-
golang.org/x/crypto v0.26.0 // indirect
90+
golang.org/x/arch v0.10.0 // indirect
91+
golang.org/x/crypto v0.27.0 // indirect
7592
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
93+
golang.org/x/net v0.29.0 // indirect
7694
golang.org/x/sync v0.8.0 // indirect
7795
golang.org/x/sys v0.25.0 // indirect
78-
golang.org/x/text v0.17.0 // indirect
96+
golang.org/x/text v0.18.0 // indirect
7997
google.golang.org/protobuf v1.34.2 // indirect
8098
gopkg.in/ini.v1 v1.67.0 // indirect
8199
gopkg.in/yaml.v3 v3.0.1 // indirect

0 commit comments

Comments
 (0)