From d009fd4f7b3fef7af1036c5c5ed63834eddc9083 Mon Sep 17 00:00:00 2001 From: Blinov Evgeniy Date: Tue, 20 Feb 2024 18:32:01 +0300 Subject: [PATCH 1/2] Fix gorm, swagger. Add infra components --- .env | 26 -------------------------- .env.example | 27 ++++++++++++++++++++------- .gitignore | 4 +++- Makefile | 27 +++++++++++++++++++++++++++ README.md | 31 ++++++++++++++++++++++++++++++- app/container/dic/container.go | 6 +++--- config/base.go | 9 ++++++++- controllers/userController.go | 7 ++++--- docker-compose.yml | 22 ++++++++++++++++++++++ docs/docs.go | 13 ++++++++++--- docs/swagger.json | 13 ++++++++++--- docs/swagger.yaml | 11 ++++++++--- infra/db/postgres_init.sh | 25 +++++++++++++++++++++++++ repositories/userRepository.go | 2 +- routers/api.go | 8 +++++--- 15 files changed, 176 insertions(+), 55 deletions(-) delete mode 100644 .env create mode 100644 Makefile create mode 100644 docker-compose.yml create mode 100755 infra/db/postgres_init.sh diff --git a/.env b/.env deleted file mode 100644 index f2f2b3a..0000000 --- a/.env +++ /dev/null @@ -1,26 +0,0 @@ -BASE_URL=127.0.0.1 -API_PORT=443 - -PROJECT_NAME=gotham -PROJECT_URL=https://www.example.com -PROJECT_API_URL=https://api.example.com - -#DB -DB_CONNECTION=postgres -DB_USERNAME=root -DB_DATABASE=gotham -DB_HOST=localhost -DB_PORT=5432 -DB_PASSWORD=password - -#EMAIL -FROM=example@go-gotham.com -HOST=smtp.gmail.com -PORT=587 -PASSWORD=password - -#VERSION -VERSION=0.1 - -#JWT_SECRET_KEY -JWT_SECRET_KEY=jwt_secret_key diff --git a/.env.example b/.env.example index e34de6a..c11639c 100644 --- a/.env.example +++ b/.env.example @@ -1,20 +1,33 @@ BASE_URL=127.0.0.1 -API_PORT=443 +API_PORT=8000 PROJECT_NAME=gotham +PROJECT_HOST=localhost PROJECT_URL=https://www.example.com PROJECT_API_URL=https://api.example.com #DB -DB_CONNECTION=mysql -DB_DATABASE=example +DB_CONNECTION=postgres +DB_USERNAME=gotham +DB_DATABASE=gotham DB_HOST=localhost -DB_PORT=3306 -DB_USERNAME=admin -DB_PASSWORD=admin +DB_PORT=35432 +DB_PASSWORD=password + +PGUSER=admin +PGPASSWORD=password +PGDATABASE=gotham +PGHOST=localhost +PGPORT=35432 + +#EMAIL +FROM=example@example.com +HOST=smtp.gmail.com +PORT=587 +PASSWORD=password #VERSION VERSION=0.1 #JWT_SECRET_KEY -JWT_SECRET_KEY=7l6dds5z2egrfcw01s6e78arte48067 +JWT_SECRET_KEY=jwt_secret_key diff --git a/.gitignore b/.gitignore index 6b80030..7e84b77 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ # vendor/ -*.idea \ No newline at end of file +*.idea + +.env diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d5da813 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +# vim: set noet ci pi sts=0 sw=4 ts=4 : +# http://www.gnu.org/software/make/manual/make.html +# http://linuxlib.ru/prog/make_379_manual.html +SHELL := $(shell which bash) +#SHELL := $(shell which sh) +DEBUG ?= 0 + +######################################################################## +# Default variables +######################################################################## +-include .env +export +######################################################################## +GOBIN := $(or $(GOBIN), $(GOPATH)/bin) +SUDO := $(or $(SUDO),) +GO111MODULE := $(or $(GO111MODULE), on) +GOROOT := $(GOPATH/src) +TAGS := +LDFLAGS := -w -s +GOFLAGS := + +.PHONY: db-init +db-init: + set -o allexport; + source .env; + set +o allexport; + ./infra/db/$(DB_CONNECTION)_init.sh diff --git a/README.md b/README.md index 2ac3f31..bc13f58 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,21 @@ DB_PORT=3306 DB_PASSWORD=strong_password ``` +## Infra + +``` +cp .env.example .env + +docker-compose up -d +# wait for pg container is up +# login from pgadmin and check database status + +make db-init + +go install github.com/swaggo/swag/cmd/swag@v1.7.0 +swag init -g main.go +``` + ## Flags - prevents re-creating container methods from definitions @@ -115,6 +130,20 @@ go run gotham -seed ### ViewModels ViewModels folder hosts all the structs under viewmodels namespace, viewmodels are model to be use as a response return of REST API call + +## Test + +``` +set -o allexport; +source .env; +set +o allexport; +export ADMIN_EMAIL=$(echo "SELECT json_agg(users) FROM users WHERE id=1" |psql -AXqt | jq -r '.[].email') +export ADMIN_TOKEN=$(curl -s -X POST "http://${BASE_URL}:${API_PORT}/v1/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"email\": \"${ADMIN_EMAIL}\", \"password\": \"password\", \"platform\": \"web\"}" | jq -r .data.access_token) + +curl -X GET "http://${BASE_URL}:${API_PORT}/v1/r/users" -H "accept: application/json" -H "Authorization: Bearer ${ADMIN_TOKEN}" +curl -X GET "http://${BASE_URL}:${API_PORT}/v1/r/users/2" -H "accept: application/json" -H "Authorization: Bearer ${ADMIN_TOKEN}" +``` + ## Author @@ -139,4 +168,4 @@ Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/app/container/dic/container.go b/app/container/dic/container.go index 328d8d7..582fad5 100644 --- a/app/container/dic/container.go +++ b/app/container/dic/container.go @@ -23,9 +23,9 @@ import ( // The function panics if the Container can not be retrieved. // // The interface can be : -// - a *Container -// - an *http.Request containing a *Container in its context.Context -// for the dingo.ContainerKey("dingo") key. +// - a *Container +// - an *http.Request containing a *Container in its context.Context +// for the dingo.ContainerKey("dingo") key. // // The function can be changed to match the needs of your application. var C = func(i interface{}) *Container { diff --git a/config/base.go b/config/base.go index 50ab1e6..8c222e0 100644 --- a/config/base.go +++ b/config/base.go @@ -29,6 +29,7 @@ type Config struct { Brand struct { ProjectName string ProjectUrl string + ProjectHost string ProjectApiUrl string } } @@ -47,7 +48,13 @@ func Configurations() { Brand: struct { ProjectName string ProjectUrl string + ProjectHost string ProjectApiUrl string - }{ProjectName: os.Getenv("PROJECT_NAME"), ProjectUrl: os.Getenv("PROJECT_URL"), ProjectApiUrl: os.Getenv("PROJECT_API_URL")}, + }{ + ProjectName: os.Getenv("PROJECT_NAME"), + ProjectUrl: os.Getenv("PROJECT_URL"), + ProjectHost: os.Getenv("PROJECT_HOST"), + ProjectApiUrl: os.Getenv("PROJECT_API_URL"), + }, } } diff --git a/controllers/userController.go b/controllers/userController.go index a7d95ab..64a704e 100644 --- a/controllers/userController.go +++ b/controllers/userController.go @@ -26,7 +26,7 @@ type UserController struct { // @Accept multipart/form-data // @Accept application/x-www-form-urlencoded // @Produce json -// @Param token header string true "Bearer Token" +// @Param Authorization header string true "Bearer Token" // @Success 200 {object} viewModels.Paginator{data=[]models.User} // @Failure 400 {object} viewModels.Message{} // @Failure 401 {object} viewModels.Message{} @@ -70,14 +70,15 @@ func (u UserController) Index(c echo.Context) (err error) { // @Accept multipart/form-data // @Accept application/x-www-form-urlencoded // @Produce json -// @Param token header string true "Bearer Token" +// @Param user path string true "1" +// @Param Authorization header string true "Bearer Token" // @Success 200 {object} viewModels.HTTPSuccessResponse{data=models.User} // @Failure 404 {object} viewModels.Message{} // @Failure 401 {object} viewModels.Message{} // @Failure 400 {object} viewModels.Message{} // @Failure 403 {object} viewModels.Message{} // @Failure 500 {object} viewModels.Message{} -// @Router /v1/r/users/:user [get] +// @Router /v1/r/users/{user} [get] func (u UserController) Show(c echo.Context) (err error) { auth := models.ConvertUser(c.Get("auth")) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..91a5b0e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + pg: + image: postgres:13.3 + container_name: gotham_pg + restart: always + environment: + POSTGRES_PASSWORD: "password" + POSTGRES_USER: "admin" + ports: + - '35432:5432' + + + pgadmin: + image: dpage/pgadmin4:latest + container_name: gotham_pgadmin + environment: + PGADMIN_DEFAULT_EMAIL: "admin@example.com" + PGADMIN_DEFAULT_PASSWORD: "password" + ports: + - '32082:80' diff --git a/docs/docs.go b/docs/docs.go index 6813a34..7702463 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -164,7 +164,7 @@ var doc = `{ { "type": "string", "description": "Bearer Token", - "name": "token", + "name": "Authorization", "in": "header", "required": true } @@ -212,7 +212,7 @@ var doc = `{ } } }, - "/v1/r/users/:user": { + "/v1/r/users/{user}": { "get": { "consumes": [ "application/json", @@ -227,10 +227,17 @@ var doc = `{ ], "summary": "Get User", "parameters": [ + { + "type": "string", + "description": "1", + "name": "user", + "in": "path", + "required": true + }, { "type": "string", "description": "Bearer Token", - "name": "token", + "name": "Authorization", "in": "header", "required": true } diff --git a/docs/swagger.json b/docs/swagger.json index d0fdd6d..900dcbb 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -144,7 +144,7 @@ { "type": "string", "description": "Bearer Token", - "name": "token", + "name": "Authorization", "in": "header", "required": true } @@ -192,7 +192,7 @@ } } }, - "/v1/r/users/:user": { + "/v1/r/users/{user}": { "get": { "consumes": [ "application/json", @@ -207,10 +207,17 @@ ], "summary": "Get User", "parameters": [ + { + "type": "string", + "description": "1", + "name": "user", + "in": "path", + "required": true + }, { "type": "string", "description": "Bearer Token", - "name": "token", + "name": "Authorization", "in": "header", "required": true } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 5c9dc2c..1a04d87 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -143,7 +143,7 @@ paths: parameters: - description: Bearer Token in: header - name: token + name: Authorization required: true type: string produces: @@ -175,16 +175,21 @@ paths: summary: List of users tags: - User - /v1/r/users/:user: + /v1/r/users/{user}: get: consumes: - application/json - multipart/form-data - application/x-www-form-urlencoded parameters: + - description: "1" + in: path + name: user + required: true + type: string - description: Bearer Token in: header - name: token + name: Authorization required: true type: string produces: diff --git a/infra/db/postgres_init.sh b/infra/db/postgres_init.sh new file mode 100755 index 0000000..46aae37 --- /dev/null +++ b/infra/db/postgres_init.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env sh +set -e + +echo "[LOG] CREATE DATABASE IF NOT EXISTS $PGDATABASE" +env PGPASSWORD="$PGPASSWORD" PGHOST="$PGHOST" PGPORT="$PGPORT" psql -v ON_ERROR_STOP=1 --username "$PGUSER" --dbname "postgres" <<-EOSQL +SELECT 'CREATE DATABASE $PGDATABASE' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$PGDATABASE')\gexec +EOSQL + +echo "[LOG] CREATE USER $DB_USERNAME IF NOT EXISTS" +env PGPASSWORD="$PGPASSWORD" PGHOST="$PGHOST" PGPORT="$PGPORT" psql -v ON_ERROR_STOP=1 --username "$PGUSER" --dbname "postgres" <<-EOSQL +DO +\$do$ +BEGIN + IF EXISTS ( + SELECT FROM pg_catalog.pg_roles + WHERE rolname = '$DB_USERNAME') THEN + + RAISE NOTICE 'Role "$DB_USERNAME" already exists. Skipping.'; + ELSE + CREATE ROLE $DB_USERNAME LOGIN ENCRYPTED PASSWORD '$DB_PASSWORD'; + END IF; +END +\$do$; +GRANT ALL ON DATABASE $PGDATABASE TO $DB_USERNAME; +EOSQL diff --git a/repositories/userRepository.go b/repositories/userRepository.go index a119a19..74ccc13 100644 --- a/repositories/userRepository.go +++ b/repositories/userRepository.go @@ -69,7 +69,7 @@ func (repository *UserRepository) Migrate() (err error) { } func (repository *UserRepository) GetUsersWithPaginationAndOrder(pagination scopes.GormPager, order scopes.GormOrderer) (users []models.User, totalCount int64, err error) { - err = repository.DB().Scopes(order.ToOrder(models.User{}.TableName(), "id", "id", "created_at", "updated_at")).Count(&totalCount).Scopes(pagination.ToPaginate()).Find(&users).Error + err = repository.DB().Table(models.User{}.TableName()).Scopes(order.ToOrder(models.User{}.TableName(), "id", "id", "created_at", "updated_at")).Count(&totalCount).Scopes(pagination.ToPaginate()).Find(&users).Error return } diff --git a/routers/api.go b/routers/api.go index 7616033..bc6c7a6 100644 --- a/routers/api.go +++ b/routers/api.go @@ -2,6 +2,7 @@ package routers import ( "context" + "fmt" "os" "os/signal" "time" @@ -21,9 +22,9 @@ func Route(e *echo.Echo) { docs.SwaggerInfo.Title = "Gotham API" docs.SwaggerInfo.Description = "..." docs.SwaggerInfo.Version = "1.0" - docs.SwaggerInfo.Host = "''" + docs.SwaggerInfo.Host = fmt.Sprintf("%s:%s", config.Conf.Brand.ProjectHost, config.Conf.Port) docs.SwaggerInfo.BasePath = "/" - docs.SwaggerInfo.Schemes = []string{"v1"} + //docs.SwaggerInfo.Schemes = []string{"v1"} e.Use(middleware.Logger()) e.Use(middleware.Recover()) @@ -40,7 +41,8 @@ func Route(e *echo.Echo) { // login v1.POST("/login", app.Application.Container.GetAuthController().Login) - r := v1.Group("/restricted") + //r := v1.Group("/restricted") + r := v1.Group("/r") c := middleware.JWTConfig{ Claims: &config.JwtCustomClaims{}, From 8bd4f23bfc32e67041adee94bfe829e1cf103742 Mon Sep 17 00:00:00 2001 From: Blinov Evgeniy Date: Tue, 20 Feb 2024 21:04:09 +0300 Subject: [PATCH 2/2] Add echo server as flag --- README.md | 5 +++ app/container/dic/container.go | 59 ++++++++++++++++++++++++++++++ app/container/dic/defs.go | 21 +++++++++++ app/defs/servers.go | 18 +++++++++ app/flags/base.go | 4 ++ app/provider/appServiceProvider.go | 7 +++- main.go | 4 +- routers/api.go | 22 +---------- routers/base.go | 16 ++++++++ server/server.go | 42 +++++++++++++++++++++ 10 files changed, 174 insertions(+), 24 deletions(-) create mode 100644 app/defs/servers.go create mode 100644 routers/base.go create mode 100644 server/server.go diff --git a/README.md b/README.md index bc13f58..d3b4ebf 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,11 @@ go run gotham -migrate go run gotham -seed ``` +- run echo server +``` +go run gotham -server +``` + ## FOLDER STRUCTURE ``` diff --git a/app/container/dic/container.go b/app/container/dic/container.go index 582fad5..d701d5a 100644 --- a/app/container/dic/container.go +++ b/app/container/dic/container.go @@ -16,6 +16,7 @@ import ( middlewares "gotham/middlewares" policies "gotham/policies" repositories "gotham/repositories" + server "gotham/server" services "gotham/services" ) @@ -511,6 +512,64 @@ func DbPool(i interface{}) infrastructures.IGormDatabasePool { return C(i).GetDbPool() } +// SafeGetEchoServer works like SafeGet but only for EchoServer. +// It does not return an interface but a *server.EchoServer. +func (c *Container) SafeGetEchoServer() (*server.EchoServer, error) { + i, err := c.ctn.SafeGet("echo-server") + if err != nil { + var eo *server.EchoServer + return eo, err + } + o, ok := i.(*server.EchoServer) + if !ok { + return o, errors.New("could get 'echo-server' because the object could not be cast to *server.EchoServer") + } + return o, nil +} + +// GetEchoServer is similar to SafeGetEchoServer but it does not return the error. +// Instead it panics. +func (c *Container) GetEchoServer() *server.EchoServer { + o, err := c.SafeGetEchoServer() + if err != nil { + panic(err) + } + return o +} + +// UnscopedSafeGetEchoServer works like UnscopedSafeGet but only for EchoServer. +// It does not return an interface but a *server.EchoServer. +func (c *Container) UnscopedSafeGetEchoServer() (*server.EchoServer, error) { + i, err := c.ctn.UnscopedSafeGet("echo-server") + if err != nil { + var eo *server.EchoServer + return eo, err + } + o, ok := i.(*server.EchoServer) + if !ok { + return o, errors.New("could get 'echo-server' because the object could not be cast to *server.EchoServer") + } + return o, nil +} + +// UnscopedGetEchoServer is similar to UnscopedSafeGetEchoServer but it does not return the error. +// Instead it panics. +func (c *Container) UnscopedGetEchoServer() *server.EchoServer { + o, err := c.UnscopedSafeGetEchoServer() + if err != nil { + panic(err) + } + return o +} + +// EchoServer is similar to GetEchoServer. +// It tries to find the container with the C method and the given interface. +// If the container can be retrieved, it applies the GetEchoServer method. +// If the container can not be retrieved, it panics. +func EchoServer(i interface{}) *server.EchoServer { + return C(i).GetEchoServer() +} + // SafeGetEmail works like SafeGet but only for Email. // It does not return an interface but a infrastructures.IEmailService. func (c *Container) SafeGetEmail() (infrastructures.IEmailService, error) { diff --git a/app/container/dic/defs.go b/app/container/dic/defs.go index e43b295..9d740c0 100644 --- a/app/container/dic/defs.go +++ b/app/container/dic/defs.go @@ -12,6 +12,7 @@ import ( middlewares "gotham/middlewares" policies "gotham/policies" repositories "gotham/repositories" + server "gotham/server" services "gotham/services" ) @@ -169,6 +170,26 @@ func getDiDefs(provider dingo.Provider) []di.Def { return nil }, }, + { + Name: "echo-server", + Scope: "app", + Build: func(ctn di.Container) (interface{}, error) { + d, err := provider.Get("echo-server") + if err != nil { + var eo *server.EchoServer + return eo, err + } + b, ok := d.Build.(func() (*server.EchoServer, error)) + if !ok { + var eo *server.EchoServer + return eo, errors.New("could not cast build function to func() (*server.EchoServer, error)") + } + return b() + }, + Close: func(obj interface{}) error { + return nil + }, + }, { Name: "email", Scope: "app", diff --git a/app/defs/servers.go b/app/defs/servers.go new file mode 100644 index 0000000..7c03c2e --- /dev/null +++ b/app/defs/servers.go @@ -0,0 +1,18 @@ +package defs + +import ( + "gotham/server" + + "github.com/sarulabs/di/v2" + "github.com/sarulabs/dingo/v4" +) + +var ServersDefs = []dingo.Def{ + { + Name: "echo-server", + Scope: di.App, + Build: func() (ES *server.EchoServer, err error) { + return &server.EchoServer{}, nil + }, + }, +} diff --git a/app/flags/base.go b/app/flags/base.go index 7c1e94a..bd53fb4 100644 --- a/app/flags/base.go +++ b/app/flags/base.go @@ -6,13 +6,17 @@ import ( var ( Production *bool + Dingo *bool Migrate *bool Seed *bool + Server *bool ) func init() { Production = flag.Bool("production", false, "a bool") + Dingo = flag.Bool("dingo", false, "a bool") Migrate = flag.Bool("migrate", false, "a bool") Seed = flag.Bool("seed", false, "a bool") + Server = flag.Bool("server", false, "a bool") flag.Parse() } diff --git a/app/provider/appServiceProvider.go b/app/provider/appServiceProvider.go index 85a1f6c..99dcd0a 100644 --- a/app/provider/appServiceProvider.go +++ b/app/provider/appServiceProvider.go @@ -1,8 +1,9 @@ package provider import ( - "github.com/sarulabs/dingo/v4" "gotham/app/defs" + + "github.com/sarulabs/dingo/v4" ) type Provider struct { @@ -42,5 +43,9 @@ func (p *Provider) Load() error { return err } + if err := p.AddDefSlice(defs.ServersDefs); err != nil { + return err + } + return nil } diff --git a/main.go b/main.go index 8c04519..678ca62 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,6 @@ package main import ( - "github.com/labstack/echo/v4" - "gotham/app" "gotham/config" "gotham/database/migrations" @@ -16,5 +14,5 @@ func main() { defer app.Application.Container.Delete() migrations.Initialize() seeds.Initialize() - routers.Route(echo.New()) + routers.Initialize() } diff --git a/routers/api.go b/routers/api.go index bc6c7a6..1edf8c0 100644 --- a/routers/api.go +++ b/routers/api.go @@ -1,11 +1,7 @@ package routers import ( - "context" "fmt" - "os" - "os/signal" - "time" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" @@ -18,7 +14,7 @@ import ( GMiddleware "gotham/middlewares" ) -func Route(e *echo.Echo) { +func GetRoute(e *echo.Echo) *echo.Echo { docs.SwaggerInfo.Title = "Gotham API" docs.SwaggerInfo.Description = "..." docs.SwaggerInfo.Version = "1.0" @@ -56,19 +52,5 @@ func Route(e *echo.Echo) { r.GET("/users/:user", app.Application.Container.GetUserController().Show, GMiddleware.Or(app.Application.Container.GetIsAdminMiddleware(), app.Application.Container.GetIsVerifiedMiddleware())) r.GET("/users", app.Application.Container.GetUserController().Index) - // Start server - go func() { - if err := e.Start(":" + config.Conf.Port); err != nil { - e.Logger.Info("shutting down the server") - } - }() - - quit := make(chan os.Signal, 1) - signal.Notify(quit, os.Interrupt) - <-quit - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - if err := e.Shutdown(ctx); err != nil { - e.Logger.Fatal(err) - } + return e } diff --git a/routers/base.go b/routers/base.go new file mode 100644 index 0000000..7e11961 --- /dev/null +++ b/routers/base.go @@ -0,0 +1,16 @@ +package routers + +import ( + "gotham/app" + "gotham/app/flags" +) + +func Initialize() { + if *flags.Server { + echoServer := app.Application.Container.GetEchoServer() + echo := echoServer.New() + routes := GetRoute(echo) + echoServer.StartServer(routes) + return + } +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..85407c4 --- /dev/null +++ b/server/server.go @@ -0,0 +1,42 @@ +package server + +import ( + "context" + "gotham/config" + "os" + "os/signal" + "time" + + "github.com/labstack/echo/v4" +) + +type IEchoServer interface { + StartServer(e *echo.Echo) +} + +type EchoServer struct { + echo.Echo + IEchoServer +} + +func (ES *EchoServer) New() *echo.Echo { + return echo.New() +} + +func (ES *EchoServer) StartServer(e *echo.Echo) { + // Start server + go func() { + if err := e.Start(":" + config.Conf.Port); err != nil { + e.Logger.Info("shutting down the server") + } + }() + + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt) + <-quit + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + if err := e.Shutdown(ctx); err != nil { + e.Logger.Fatal(err) + } +}