From cdf42b7ff38cbc6be0e19a618d4eb6bf3b6a04d0 Mon Sep 17 00:00:00 2001 From: Bronku Date: Wed, 6 Aug 2025 21:03:38 +0200 Subject: [PATCH] chi --- config.default.toml | 1 + go.mod | 2 + go.sum | 4 ++ main.go | 98 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 99 insertions(+), 6 deletions(-) diff --git a/config.default.toml b/config.default.toml index 6216c16..788f23d 100644 --- a/config.default.toml +++ b/config.default.toml @@ -4,3 +4,4 @@ File = "foo.db" [Server] Addr = ":8080" ReadHeaderTimeout = "3s" +RequestTimeout = "10s" diff --git a/go.mod b/go.mod index c48b048..e742f59 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,8 @@ require ( ) require ( + github.com/go-chi/chi v1.5.5 + github.com/go-chi/chi/v5 v5.2.2 gorm.io/driver/sqlite v1.6.0 gorm.io/gorm v1.30.0 ) diff --git a/go.sum b/go.sum index 8e03882..5aa5402 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE= +github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw= +github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= +github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= diff --git a/main.go b/main.go index 2b6373c..2feca1c 100644 --- a/main.go +++ b/main.go @@ -1,14 +1,22 @@ package main import ( + "context" _ "embed" + "errors" + "fmt" "log" "net/http" + "strconv" "time" - "github.com/Bronku/iroon/server" + "github.com/Bronku/iroon/models" "github.com/Bronku/iroon/store" "github.com/BurntSushi/toml" + "github.com/go-chi/chi/middleware" + "github.com/go-chi/chi/v5" + "gorm.io/gorm" + "gorm.io/gorm/clause" ) type config struct { @@ -19,12 +27,18 @@ type config struct { Server struct { Addr string ReadHeaderTimeout time.Duration + RequestTimeout time.Duration } } //go:embed config.default.toml var defaultConfig string +type contextKey string + +const dbContextKey = contextKey("db") +const orderContextKey = contextKey("order") + func main() { // load config var conf config @@ -43,14 +57,32 @@ func main() { log.Panic(err) } - // load server - h := server.New(db) - var handler http.Handler = h - log.Println("starting server") + r := chi.NewRouter() + r.Use(middleware.RequestID) + r.Use(middleware.RealIP) + r.Use(middleware.Logger) + r.Use(middleware.Recoverer) + r.Use(middleware.Timeout(conf.Server.RequestTimeout)) + + r.Get("/", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("welcome")) + }) + + r.Route("/orders", func(r chi.Router) { + r.Use(middleware.WithValue(dbContextKey, db)) + r.Route("/{orderID}", func(r chi.Router) { + r.Use(OrderCtx) // Load the *Article on the request context + r.Get("/", getOrder) + // r.Get("/", GetArticle) // GET /articles/123 + // r.Put("/", UpdateArticle) // PUT /articles/123 + // r.Delete("/", DeleteArticle) // DELETE /articles/123 + }) + + }) // start server server := &http.Server{ - Handler: handler, + Handler: r, Addr: conf.Server.Addr, ReadHeaderTimeout: conf.Server.ReadHeaderTimeout, } @@ -59,3 +91,57 @@ func main() { log.Fatal(err) } } + +// can't get item from context, please include it before registering route +var errNoContextValue = errors.New("no value from context") + +func OrderCtx(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + db := r.Context().Value(dbContextKey).(*gorm.DB) + if db == nil { + panic(errNoContextValue) + } + var order *models.Order + var err error + + orderID, err := strconv.Atoi(chi.URLParam(r, "orderID")) + if err != nil { + w.Write([]byte("url not found")) + return + } + + err = db.Preload("OrderItems.Product").Preload(clause.Associations).Find(&order, orderID).Error + if err != nil { + w.Write([]byte("item not found")) + return + } + + ctx := context.WithValue(r.Context(), orderContextKey, order) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} + +func getOrder(w http.ResponseWriter, r *http.Request) { + var db *gorm.DB + var catalogue []models.Product + var order *models.Order + var err error + + db = r.Context().Value(dbContextKey).(*gorm.DB) + if db == nil { + panic(errNoContextValue) + } + + err = db.Find(&catalogue).Error + if err != nil { + w.Write([]byte("no catalogue")) + return + } + + order = r.Context().Value(orderContextKey).(*models.Order) + if order == nil { + panic(errNoContextValue) + } + + fmt.Fprint(w, "order: ", order, "\ncatalogue: ", catalogue) +}