From f4b1bfeaf8676b3f77fbdfc0ff8db26e12034df4 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Mon, 12 Feb 2024 20:59:55 -0800 Subject: [PATCH] Refactored controller handlers - added API check --- src/controller/account.go | 27 ++++++++-------------- src/controller/api.go | 17 ++++++++++++++ src/repository/account.go | 33 +++++++++++++++++++++++++++ src/server/app.go | 48 +++++++++++++++++++++++++++++---------- src/utils/http.go | 12 ++++++++++ 5 files changed, 107 insertions(+), 30 deletions(-) create mode 100644 src/controller/api.go create mode 100644 src/repository/account.go create mode 100644 src/utils/http.go diff --git a/src/controller/account.go b/src/controller/account.go index 0cf7b25..cc897ce 100644 --- a/src/controller/account.go +++ b/src/controller/account.go @@ -1,40 +1,31 @@ package controller import ( - "context" "encoding/json" "net/http" - "time" "github.com/switcherapi/switcher-gitops/src/model" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "github.com/switcherapi/switcher-gitops/src/repository" + "github.com/switcherapi/switcher-gitops/src/utils" ) type AccountController struct { - Db mongo.Database - Ctx context.Context + AccountRepository repository.AccountRepository } func (controller *AccountController) CreateAccountHandler(w http.ResponseWriter, r *http.Request) { - var account model.Account - err := json.NewDecoder(r.Body).Decode(&account) + var accountRequest model.Account + err := json.NewDecoder(r.Body).Decode(&accountRequest) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + utils.ResponseJSON(w, err.Error(), http.StatusBadRequest) return } - collection := controller.Db.Collection(model.CollectionName) - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - result, _ := collection.InsertOne(ctx, account) - + accountCreated, err := controller.AccountRepository.Create(&accountRequest) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + utils.ResponseJSON(w, err.Error(), http.StatusInternalServerError) return } - w.Header().Set("Content-Type", "application/json") - account.ID = result.InsertedID.(primitive.ObjectID) - json.NewEncoder(w).Encode(account) + utils.ResponseJSON(w, accountCreated, http.StatusCreated) } diff --git a/src/controller/api.go b/src/controller/api.go new file mode 100644 index 0000000..de8e6bc --- /dev/null +++ b/src/controller/api.go @@ -0,0 +1,17 @@ +package controller + +import ( + "net/http" + + "github.com/switcherapi/switcher-gitops/src/utils" +) + +type ApiController struct{} + +type ApiCheckResponse struct { + Message string `json:"message"` +} + +func (controller *ApiController) CheckApiHandler(w http.ResponseWriter, r *http.Request) { + utils.ResponseJSON(w, ApiCheckResponse{Message: "API is working"}, http.StatusOK) +} diff --git a/src/repository/account.go b/src/repository/account.go new file mode 100644 index 0000000..4f4d826 --- /dev/null +++ b/src/repository/account.go @@ -0,0 +1,33 @@ +package repository + +import ( + "context" + "time" + + "github.com/switcherapi/switcher-gitops/src/model" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" +) + +type AccountRepository interface { + Create(account *model.Account) (*model.Account, error) +} + +type AccountRepositoryMongo struct { + Db *mongo.Database +} + +func (repo *AccountRepositoryMongo) Create(account *model.Account) (*model.Account, error) { + collection := repo.Db.Collection(model.CollectionName) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + result, err := collection.InsertOne(ctx, account) + + if err != nil { + return nil, err + } + + account.ID = result.InsertedID.(primitive.ObjectID) + return account, nil +} diff --git a/src/server/app.go b/src/server/app.go index 0583d0e..8286fbf 100644 --- a/src/server/app.go +++ b/src/server/app.go @@ -4,6 +4,8 @@ import ( "context" "log" "net/http" + "os" + "os/signal" "time" "github.com/gorilla/mux" @@ -12,6 +14,7 @@ import ( "github.com/switcherapi/switcher-gitops/src/config" "github.com/switcherapi/switcher-gitops/src/controller" + "github.com/switcherapi/switcher-gitops/src/repository" ) type App struct { @@ -20,46 +23,67 @@ type App struct { } func NewApp() *App { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - db := initDb(ctx) - routes := initRoutes(db, ctx) + db := initDb() + routes := initRoutes(db) return &App{ routerHandlers: routes, } } -func (app *App) Start() { +func (app *App) Start() error { port := config.GetEnv("PORT") app.httpServer = &http.Server{ Addr: ":" + port, Handler: app.routerHandlers, } + go func() { + if err := app.httpServer.ListenAndServe(); err != nil { + log.Fatalf("Failed to listen and serve: %+v", err) + } + }() + log.Println("Server started on port " + port) - app.httpServer.ListenAndServe() + + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt, os.Interrupt) + + <-quit + + ctx, shutdown := context.WithTimeout(context.Background(), 5*time.Second) + defer shutdown() + + return app.httpServer.Shutdown(ctx) } -func initDb(ctx context.Context) *mongo.Database { +func initDb() *mongo.Database { var err error + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + client, err := mongo.Connect(ctx, options.Client().ApplyURI(config.GetEnv("MONGO_URI"))) - db := client.Database(config.GetEnv("MONGO_DB")) if err != nil { panic(err) } + err = client.Ping(context.Background(), nil) + if err != nil { + log.Fatal(err) + } + log.Println("Connected to MongoDB!") - return db + return client.Database(config.GetEnv("MONGO_DB")) } -func initRoutes(db *mongo.Database, ctx context.Context) *mux.Router { - AccountController := controller.AccountController{Db: *db, Ctx: ctx} +func initRoutes(db *mongo.Database) *mux.Router { + ApiController := controller.ApiController{} + AccountController := controller.AccountController{AccountRepository: &repository.AccountRepositoryMongo{Db: db}} r := mux.NewRouter() + r.HandleFunc("/api/check", ApiController.CheckApiHandler).Methods("GET") r.HandleFunc("/accounts", AccountController.CreateAccountHandler).Methods("POST") return r diff --git a/src/utils/http.go b/src/utils/http.go new file mode 100644 index 0000000..826db4d --- /dev/null +++ b/src/utils/http.go @@ -0,0 +1,12 @@ +package utils + +import ( + "encoding/json" + "net/http" +) + +func ResponseJSON(w http.ResponseWriter, data interface{}, status int) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(status) + json.NewEncoder(w).Encode(data) +}