From ed9d44f8bfe28facb119a34e29b816c0e77d082a Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Thu, 17 Sep 2020 18:01:18 +0200 Subject: [PATCH 1/7] Added Gorilla/mux library --- articles.go | 2 ++ go.mod | 5 +++++ go.sum | 2 ++ main.go | 22 ++++++++++++++++++++-- server.go | 31 ++++++++++++++++++++++++++----- 5 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 go.mod create mode 100644 go.sum diff --git a/articles.go b/articles.go index edada5f..5e165ce 100644 --- a/articles.go +++ b/articles.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + "log" "net/http" ) @@ -22,6 +23,7 @@ func getAllArticles() http.Handler { } json.NewEncoder(w).Encode(articles) + log.Println("Served /articles") } return http.HandlerFunc(fn) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..417f06d --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module go-rest-api + +go 1.13 + +require github.com/gorilla/mux v1.8.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..5350288 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= diff --git a/main.go b/main.go index b789894..e6c1944 100644 --- a/main.go +++ b/main.go @@ -1,14 +1,32 @@ package main import ( + "context" "fmt" + "log" + "os" + "os/signal" + "time" ) func main() { fmt.Println("Hello world!") s := Server{ - port: ":3000", + port: ":9999", } - s.serve() + + go func() { + s.serve() + }() + + signCh := make(chan os.Signal) + signal.Notify(signCh, os.Interrupt) + signal.Notify(signCh, os.Kill) + + sig := <-signCh + log.Println("Received terminal, graceful shutdown", sig) + + tc, _ := context.WithTimeout(context.Background(), 30*time.Second) + s.shutdown(tc) } diff --git a/server.go b/server.go index 47cebaf..331209b 100644 --- a/server.go +++ b/server.go @@ -1,22 +1,39 @@ package main import ( + "context" "log" "net/http" + "time" + + "github.com/gorilla/mux" ) // Server base struct type Server struct { - port string + port string + server http.Server } func (s *Server) serve() { - mux := http.NewServeMux() - mux.Handle("/", s.handle()) - mux.Handle("/articles", getAllArticles()) + sm := mux.NewRouter() + sm.Handle("/", s.handle()) + sm.Handle("/articles", getAllArticles()) + serv := &http.Server{ + Addr: s.port, + Handler: sm, + IdleTimeout: 120 * time.Second, + ReadTimeout: 1 * time.Second, + WriteTimeout: 1 * time.Second, + } + s.server = *serv log.Print("Listening on", s.port) - log.Fatal(http.ListenAndServe(s.port, mux)) + + err := serv.ListenAndServe() + if err != nil { + log.Fatal(err) + } } func (s *Server) handle() http.Handler { @@ -26,3 +43,7 @@ func (s *Server) handle() http.Handler { return http.HandlerFunc(fn) } + +func (s *Server) shutdown(tc context.Context) { + s.server.Shutdown(tc) +} From 494b5a22bcbc85aa2e076b1a42213c2d93661086 Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Thu, 17 Sep 2020 19:16:46 +0200 Subject: [PATCH 2/7] Added mod dep config and modd base setup --- go.mod | 5 ++- go.sum | 64 ++++++++++++++++++++++++++++++ articles.go => handler_articles.go | 0 modd.conf | 4 ++ 4 files changed, 72 insertions(+), 1 deletion(-) rename articles.go => handler_articles.go (100%) create mode 100644 modd.conf diff --git a/go.mod b/go.mod index 417f06d..27f7d81 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module go-rest-api go 1.13 -require github.com/gorilla/mux v1.8.0 +require ( + github.com/cortesi/modd v0.0.0-20200630120222-8983974e5450 + github.com/gorilla/mux v1.8.0 +) diff --git a/go.sum b/go.sum index 5350288..257d840 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,66 @@ +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/bmatcuk/doublestar v1.3.0/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/bmatcuk/doublestar v1.3.1/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/cortesi/modd v0.0.0-20200630120222-8983974e5450/go.mod h1:nZYoHDEpIB+Hv0ns85UxQDkHQ1uuaUQIFJ99VPctjq8= +github.com/cortesi/moddwatch v0.0.0-20200427000745-d26468c93cf0/go.mod h1:QYGP4Q0SeEUNSC+dsNSKTmONSd1PpZVYUXIRAzxxpXo= +github.com/cortesi/termlog v0.0.0-20190809035425-7871d363854c/go.mod h1:gh6GQA3zOsGU4pz+X6ZHqW63KxI/V7KLmBCG9ODJ+l4= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rjeczalik/notify v0.0.0-20181126183243-629144ba06a1/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191202203127-2b6af5f9ace7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +mvdan.cc/sh v2.6.4+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8= diff --git a/articles.go b/handler_articles.go similarity index 100% rename from articles.go rename to handler_articles.go diff --git a/modd.conf b/modd.conf new file mode 100644 index 0000000..2d5bd4b --- /dev/null +++ b/modd.conf @@ -0,0 +1,4 @@ +**/*.go !**/*_test.go { + prep: go build -o build main.go server.go handler_*.go + daemon +sigterm: ./build +} \ No newline at end of file From 5aa9c4dfdbebe99449a0d47387b413a222a05f05 Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Thu, 17 Sep 2020 20:33:58 +0200 Subject: [PATCH 3/7] Refactor. Splitted code into subdirectories. Updated modd conf --- .gitignore | 2 ++ handler/articles.go | 43 ++++++++++++++++++++++++++++++++++ handler_articles.go | 30 ------------------------ main.go | 9 ++++---- modd.conf | 2 +- model/article.go | 11 +++++++++ server.go | 49 --------------------------------------- server/server.go | 56 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 117 insertions(+), 85 deletions(-) create mode 100644 handler/articles.go delete mode 100644 handler_articles.go create mode 100644 model/article.go delete mode 100644 server.go create mode 100644 server/server.go diff --git a/.gitignore b/.gitignore index 8f5fd87..6a09e2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .history + +build diff --git a/handler/articles.go b/handler/articles.go new file mode 100644 index 0000000..1564f1f --- /dev/null +++ b/handler/articles.go @@ -0,0 +1,43 @@ +package handler + +import ( + "encoding/json" + "go-rest-api/model" + "log" + "net/http" + + "github.com/gorilla/mux" +) + +func getAllArticles(w http.ResponseWriter, r *http.Request) { + articles := model.Articles{ + model.Article{Title: "Test Title", Description: "Test Description", Content: "Hello content!"}, + } + + json.NewEncoder(w).Encode(articles) + log.Println("Served /articles") +} + +func getOneArticle(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + log.Println(vars) + log.Println("Get single article") +} + +func createArticle(w http.ResponseWriter, r *http.Request) { + log.Println("Create article") +} + +func updateArticle(w http.ResponseWriter, r *http.Request) { + log.Println("Update article") +} + +// AttachArticleHandlersToRouter func +func AttachArticleHandlersToRouter(root *mux.Router) { + router := root.PathPrefix("/articles").Subrouter() + router.HandleFunc("", getAllArticles).Methods(http.MethodGet) + router.HandleFunc("/{id:[0-9]+}", getOneArticle).Methods(http.MethodGet) + router.HandleFunc("", createArticle).Methods(http.MethodPost) + router.HandleFunc("/{id:[0-9]+}", updateArticle).Methods(http.MethodPut) +} diff --git a/handler_articles.go b/handler_articles.go deleted file mode 100644 index 5e165ce..0000000 --- a/handler_articles.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "encoding/json" - "log" - "net/http" -) - -// Article type -type Article struct { - Title string `json:"title"` - Description string `json:"description"` - Content string `json:"content"` -} - -// Articles Collection -type Articles []Article - -func getAllArticles() http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - articles := Articles{ - Article{Title: "Test Title", Description: "Test Description", Content: "Hello content!"}, - } - - json.NewEncoder(w).Encode(articles) - log.Println("Served /articles") - } - - return http.HandlerFunc(fn) -} diff --git a/main.go b/main.go index e6c1944..bcd0a64 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "go-rest-api/server" "log" "os" "os/signal" @@ -12,12 +13,10 @@ import ( func main() { fmt.Println("Hello world!") - s := Server{ - port: ":9999", - } + s := server.NewServer(":9999") go func() { - s.serve() + s.Serve() }() signCh := make(chan os.Signal) @@ -28,5 +27,5 @@ func main() { log.Println("Received terminal, graceful shutdown", sig) tc, _ := context.WithTimeout(context.Background(), 30*time.Second) - s.shutdown(tc) + s.Shutdown(tc) } diff --git a/modd.conf b/modd.conf index 2d5bd4b..d76bc78 100644 --- a/modd.conf +++ b/modd.conf @@ -1,4 +1,4 @@ **/*.go !**/*_test.go { - prep: go build -o build main.go server.go handler_*.go + prep: go build -o build main.go daemon +sigterm: ./build } \ No newline at end of file diff --git a/model/article.go b/model/article.go new file mode 100644 index 0000000..17743b7 --- /dev/null +++ b/model/article.go @@ -0,0 +1,11 @@ +package model + +// Article type +type Article struct { + Title string `json:"title"` + Description string `json:"description"` + Content string `json:"content"` +} + +// Articles Collection +type Articles []Article diff --git a/server.go b/server.go deleted file mode 100644 index 331209b..0000000 --- a/server.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "context" - "log" - "net/http" - "time" - - "github.com/gorilla/mux" -) - -// Server base struct -type Server struct { - port string - server http.Server -} - -func (s *Server) serve() { - sm := mux.NewRouter() - sm.Handle("/", s.handle()) - sm.Handle("/articles", getAllArticles()) - - serv := &http.Server{ - Addr: s.port, - Handler: sm, - IdleTimeout: 120 * time.Second, - ReadTimeout: 1 * time.Second, - WriteTimeout: 1 * time.Second, - } - s.server = *serv - log.Print("Listening on", s.port) - - err := serv.ListenAndServe() - if err != nil { - log.Fatal(err) - } -} - -func (s *Server) handle() http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(string("Hello World"))) - } - - return http.HandlerFunc(fn) -} - -func (s *Server) shutdown(tc context.Context) { - s.server.Shutdown(tc) -} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..9427e31 --- /dev/null +++ b/server/server.go @@ -0,0 +1,56 @@ +package server + +import ( + "context" + "go-rest-api/handler" + "log" + "net/http" + "time" + + "github.com/gorilla/mux" +) + +// Server struct +type Server struct { + port string + server http.Server +} + +// NewServer func +func NewServer(port string) Server { + return Server{ + port: port, + } +} + +// Serve func +func (s *Server) Serve() { + r := mux.NewRouter() + + handler.AttachArticleHandlersToRouter(r) + + r.HandleFunc("/", s.handleDefault) + + s.server = http.Server{ + Addr: s.port, + Handler: r, + IdleTimeout: 120 * time.Second, + ReadTimeout: 1 * time.Second, + WriteTimeout: 1 * time.Second, + } + log.Print("Listening on", s.port) + + err := s.server.ListenAndServe() + if err != nil { + log.Fatal(err) + } +} + +// Shutdown func +func (s *Server) Shutdown(tc context.Context) { + s.server.Shutdown(tc) +} + +func (s *Server) handleDefault(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(string("REST API. Get the fuck out!"))) +} From 04684d0b4899fa0ab0578a5a2614fea58c96caef Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Thu, 17 Sep 2020 20:53:31 +0200 Subject: [PATCH 4/7] Added DroneCI config --- .drone.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..34d8c42 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,9 @@ +kind: pipeline +name: default + +steps: +- name: test + image: golang + commands: + - go test + - go build From eb5cfe61cbdad7f0c342499802f5a5383a686c4f Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Thu, 17 Sep 2020 20:55:56 +0200 Subject: [PATCH 5/7] Updated .drone.yml --- .drone.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.drone.yml b/.drone.yml index 34d8c42..c1e6dfc 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,3 +7,4 @@ steps: commands: - go test - go build + - ls \ No newline at end of file From e1019a5ecc1957a993032e68904393589f9ff135 Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Sat, 26 Sep 2020 22:38:38 +0200 Subject: [PATCH 6/7] Some refactor. Rewritted to Echo Framework --- .gitignore | 1 + database/mongodb.go | 58 +++++++++++++++++ docker-compose.yml | 14 +++++ go.mod | 5 ++ go.sum | 147 ++++++++++++++++++++++++++++++++++++++++++++ handler/articles.go | 128 ++++++++++++++++++++++++++++---------- handler/base.go | 83 +++++++++++++++++++++++++ main.go | 5 +- model/article.go | 20 +++++- public/favicon.ico | 0 server/server.go | 41 ++++++------ 11 files changed, 441 insertions(+), 61 deletions(-) create mode 100644 database/mongodb.go create mode 100644 docker-compose.yml create mode 100644 handler/base.go create mode 100644 public/favicon.ico diff --git a/.gitignore b/.gitignore index 6a09e2d..658c73b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .history +.env build diff --git a/database/mongodb.go b/database/mongodb.go new file mode 100644 index 0000000..4d77990 --- /dev/null +++ b/database/mongodb.go @@ -0,0 +1,58 @@ +package database + +import ( + "github.com/Kamva/mgm/v3" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" +) + +// MongoDb type +type MongoDb struct { + database string +} + +// NewMongoDb func +func NewMongoDb( /* dbName string */ ) *MongoDb { + dbName := "go-rest-api" // FIXME + + mgm.SetDefaultConfig(nil, dbName, options.Client().ApplyURI("mongodb://user:passwd@localhost:27017")) + + return &MongoDb{ + database: dbName, + } +} + +// FindByID func +func (m *MongoDb) FindByID(model mgm.Model, id string) error { + err := mgm.Coll(model).FindByID(id, model) + if err != nil { + return err + } + + return nil +} + +// FindAll func +func (m *MongoDb) FindAll(model mgm.Model, collection interface{}, filter bson.D) error { + err := mgm.Coll(model).SimpleFind(collection, filter) + if err != nil { + return err + } + + return nil +} + +// Create func +func (m *MongoDb) Create(model mgm.Model) error { + return mgm.Coll(model).Create(model) +} + +// Update func +func (m *MongoDb) Update(model mgm.Model) error { + return mgm.Coll(model).Update(model) +} + +// Remove func +func (m *MongoDb) Remove(model mgm.Model) error { + return mgm.Coll(model).Delete(model) +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..15e88ac --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: '3.7' + +services: + mongodb: + image: mongo:latest + env_file: .env + ports: + - 27017:27017 + networks: + - app-network + +networks: + app-network: + driver: bridge \ No newline at end of file diff --git a/go.mod b/go.mod index 27f7d81..2726015 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,11 @@ module go-rest-api go 1.13 require ( + github.com/Kamva/mgm/v3 v3.0.1 github.com/cortesi/modd v0.0.0-20200630120222-8983974e5450 + github.com/go-playground/validator/v10 v10.3.0 github.com/gorilla/mux v1.8.0 + github.com/labstack/echo v3.3.10+incompatible + github.com/labstack/echo/v4 v4.1.17 + go.mongodb.org/mongo-driver v1.4.1 ) diff --git a/go.sum b/go.sum index 257d840..5eeee75 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,12 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Kamva/mgm v1.2.3 h1:EokuP5HyjsURC/YyFrarQkMx4IecKq7yz3j2tC6oTcI= +github.com/Kamva/mgm v1.2.3/go.mod h1:si3Kyg7KypBXHibQh9+UfMouSuu+XhjPlTCfQCZrr6s= +github.com/Kamva/mgm/v3 v3.0.1 h1:jgWuqhdzUGLpGmbNfHtONY/6ikBs2g0aKlKqvEK/HzI= +github.com/Kamva/mgm/v3 v3.0.1/go.mod h1:3F9EhA1QeVB6kk8oWZSHVAye/+af8EQBTuZ0gAR/U88= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/aws/aws-sdk-go v1.29.15 h1:0ms/213murpsujhsnxnNKNeVouW60aJqSd992Ks3mxs= +github.com/aws/aws-sdk-go v1.29.15/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/bmatcuk/doublestar v1.3.0/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/bmatcuk/doublestar v1.3.1/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/cortesi/modd v0.0.0-20200630120222-8983974e5450/go.mod h1:nZYoHDEpIB+Hv0ns85UxQDkHQ1uuaUQIFJ99VPctjq8= @@ -7,60 +14,200 @@ github.com/cortesi/moddwatch v0.0.0-20200427000745-d26468c93cf0/go.mod h1:QYGP4Q github.com/cortesi/termlog v0.0.0-20190809035425-7871d363854c/go.mod h1:gh6GQA3zOsGU4pz+X6ZHqW63KxI/V7KLmBCG9ODJ+l4= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA= +github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o= +github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +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/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= +github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= +github.com/labstack/echo/v4 v4.1.17 h1:PQIBaRplyRy3OjwILGkPg89JRtH2x5bssi59G2EL3fo= +github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ= +github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rjeczalik/notify v0.0.0-20181126183243-629144ba06a1/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +go.mongodb.org/mongo-driver v1.1.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= +go.mongodb.org/mongo-driver v1.4.1 h1:38NSAyDPagwnFpUA/D5SFgbugUYR3NzYRNa4Qk9UxKs= +go.mongodb.org/mongo-driver v1.4.1/go.mod h1:llVBH2pkj9HywK0Dtdt6lDikOjFLbceHVu/Rc0iMKLs= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8= +golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191202203127-2b6af5f9ace7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= mvdan.cc/sh v2.6.4+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8= diff --git a/handler/articles.go b/handler/articles.go index 1564f1f..11bb112 100644 --- a/handler/articles.go +++ b/handler/articles.go @@ -1,43 +1,107 @@ package handler import ( - "encoding/json" + "go-rest-api/database" "go-rest-api/model" - "log" "net/http" - "github.com/gorilla/mux" + "github.com/go-playground/validator/v10" + "github.com/labstack/echo/v4" + "go.mongodb.org/mongo-driver/bson" ) -func getAllArticles(w http.ResponseWriter, r *http.Request) { - articles := model.Articles{ - model.Article{Title: "Test Title", Description: "Test Description", Content: "Hello content!"}, - } - - json.NewEncoder(w).Encode(articles) - log.Println("Served /articles") -} - -func getOneArticle(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - - log.Println(vars) - log.Println("Get single article") -} - -func createArticle(w http.ResponseWriter, r *http.Request) { - log.Println("Create article") -} - -func updateArticle(w http.ResponseWriter, r *http.Request) { - log.Println("Update article") -} +var ( + internalErr = "Unable to operate on Article." + articleNotFoundErr = "Article not found." + validationErr = "Validation Error." +) // AttachArticleHandlersToRouter func -func AttachArticleHandlersToRouter(root *mux.Router) { - router := root.PathPrefix("/articles").Subrouter() - router.HandleFunc("", getAllArticles).Methods(http.MethodGet) - router.HandleFunc("/{id:[0-9]+}", getOneArticle).Methods(http.MethodGet) - router.HandleFunc("", createArticle).Methods(http.MethodPost) - router.HandleFunc("/{id:[0-9]+}", updateArticle).Methods(http.MethodPut) +func AttachArticleHandlersToRouter(e *echo.Echo) { + db := database.NewMongoDb() + ah := NewArticlesHandler(db) + + g := e.Group("/articles") + g.GET("", ah.getAllArticles) + g.GET("/:id", ah.getOneArticle) + g.POST("", ah.createArticle) + g.PUT("/:id", ah.updateArticle) + g.DELETE("/:id", ah.removeArticle) +} + +// NewArticlesHandler return ArticlesHandler +func NewArticlesHandler(db *database.MongoDb) ArticlesHandler { + return ArticlesHandler{ + parent: BaseHandler{ + db: db, + validator: validator.New(), + }, + } +} + +// ArticlesHandler type +type ArticlesHandler struct { + parent BaseHandler +} + +func (ah *ArticlesHandler) getAllArticles(c echo.Context) error { + coll := &model.Articles{} + articles := ah.parent.GetAllObjects(&model.Article{}, coll, bson.D{}) + + return c.JSON(http.StatusOK, articles) +} + +func (ah *ArticlesHandler) getOneArticle(c echo.Context) error { + id := c.Param("id") + art := &model.Article{} + + if _, err := ah.parent.GetSingleObject(art, id); err != nil { + return err + } + + return c.JSON(http.StatusOK, art) +} + +func (ah *ArticlesHandler) createArticle(c echo.Context) error { + art := &model.Article{} + c.Bind(art) + + if _, err := ah.parent.CreateObject(art); err != nil { + return err + } + + return c.JSON(http.StatusOK, art) +} + +func (ah *ArticlesHandler) updateArticle(c echo.Context) error { + id := c.Param("id") + model := &model.Article{} + + art, err := ah.parent.GetSingleObject(model, id) + if err != nil { + return err + } + DeserializeFromRequest(c.Request(), art) + + if _, err := ah.parent.UpdateObject(art); err != nil { + return err + } + + return c.JSON(http.StatusOK, art) +} + +func (ah *ArticlesHandler) removeArticle(c echo.Context) error { + id := c.Param("id") + model := &model.Article{} + + art, err := ah.parent.GetSingleObject(model, id) + if err != nil { + return err + } + + if err := ah.parent.RemoveObject(art); err != nil { + return err + } + + return c.NoContent(http.StatusOK) } diff --git a/handler/base.go b/handler/base.go new file mode 100644 index 0000000..9f48558 --- /dev/null +++ b/handler/base.go @@ -0,0 +1,83 @@ +package handler + +import ( + "encoding/json" + "go-rest-api/database" + "io/ioutil" + "net/http" + + "github.com/Kamva/mgm/v3" + "github.com/go-playground/validator/v10" + "github.com/labstack/echo/v4" + "go.mongodb.org/mongo-driver/bson" +) + +// DeserializeFromRequest func +func DeserializeFromRequest(request *http.Request, output interface{}) { + defer request.Body.Close() + + body, _ := ioutil.ReadAll(request.Body) + _ = json.Unmarshal(body, output) +} + +// BaseHandler type +type BaseHandler struct { + db *database.MongoDb + validator *validator.Validate +} + +// GetAllObjects Retrieve all objects +func (h *BaseHandler) GetAllObjects(model mgm.Model, coll interface{}, filter bson.D) interface{} { + h.db.FindAll(model, coll, filter) + + return coll +} + +// GetSingleObject Retrieve single object +func (h *BaseHandler) GetSingleObject(model mgm.Model, id string) (mgm.Model, *echo.HTTPError) { + if err := h.db.FindByID(model, id); err != nil { + return nil, echo.NewHTTPError(http.StatusNotFound, articleNotFoundErr) + } + + return model, nil +} + +// CreateObject Try to create a new object +func (h *BaseHandler) CreateObject(model mgm.Model) (mgm.Model, *echo.HTTPError) { + if err := h.Validate(model); err != nil { + return nil, echo.NewHTTPError(http.StatusBadRequest, validationErr+" "+err.Error()) + } + + if err := h.db.Create(model); err != nil { + return nil, echo.NewHTTPError(http.StatusInternalServerError, internalErr) + } + + return model, nil +} + +// UpdateObject Try to update a new object +func (h *BaseHandler) UpdateObject(model mgm.Model) (mgm.Model, *echo.HTTPError) { + if err := h.Validate(model); err != nil { + return nil, echo.NewHTTPError(http.StatusBadRequest, validationErr+" "+err.Error()) + } + + if err := h.db.Update(model); err != nil { + return nil, echo.NewHTTPError(http.StatusInternalServerError, internalErr) + } + + return model, nil +} + +//RemoveObject Try to remove object +func (h *BaseHandler) RemoveObject(model mgm.Model) *echo.HTTPError { + if err := h.db.Remove(model); err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, internalErr) + } + + return nil +} + +// Validate Validate model object +func (h *BaseHandler) Validate(i interface{}) error { + return h.validator.Struct(i) +} diff --git a/main.go b/main.go index bcd0a64..4a6b2c9 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "fmt" "go-rest-api/server" "log" "os" @@ -11,9 +10,7 @@ import ( ) func main() { - fmt.Println("Hello world!") - - s := server.NewServer(":9999") + s := server.NewServer(":8000") go func() { s.Serve() diff --git a/model/article.go b/model/article.go index 17743b7..d22c4a9 100644 --- a/model/article.go +++ b/model/article.go @@ -1,11 +1,25 @@ package model +import ( + "github.com/Kamva/mgm/v3" +) + // Article type type Article struct { - Title string `json:"title"` - Description string `json:"description"` - Content string `json:"content"` + mgm.DefaultModel `bson:",inline"` + Title string `json:"title" bson:"title" validate:"required"` + Description string `json:"description" bson:"description" validate:"required"` + Content string `json:"content" bson:"content" validate:"required"` } // Articles Collection type Articles []Article + +// NewArticle func +func NewArticle(title string, desc string, content string) *Article { + return &Article{ + Title: title, + Description: desc, + Content: content, + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/server/server.go b/server/server.go index 9427e31..746cf02 100644 --- a/server/server.go +++ b/server/server.go @@ -3,47 +3,44 @@ package server import ( "context" "go-rest-api/handler" - "log" "net/http" - "time" - "github.com/gorilla/mux" + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" ) // Server struct type Server struct { port string - server http.Server + server *http.Server } // NewServer func func NewServer(port string) Server { return Server{ - port: port, + server: &http.Server{ + Addr: port, + }, } } // Serve func func (s *Server) Serve() { - r := mux.NewRouter() + e := echo.New() - handler.AttachArticleHandlersToRouter(r) + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOrigins: []string{"http://localhost:8000"}, + AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept}, + })) - r.HandleFunc("/", s.handleDefault) + handler.AttachArticleHandlersToRouter(e) - s.server = http.Server{ - Addr: s.port, - Handler: r, - IdleTimeout: 120 * time.Second, - ReadTimeout: 1 * time.Second, - WriteTimeout: 1 * time.Second, - } - log.Print("Listening on", s.port) + e.Static("/", "./public") + e.GET("/", s.defaultHandler) - err := s.server.ListenAndServe() - if err != nil { - log.Fatal(err) - } + e.Logger.Fatal(e.StartServer(s.server)) } // Shutdown func @@ -51,6 +48,6 @@ func (s *Server) Shutdown(tc context.Context) { s.server.Shutdown(tc) } -func (s *Server) handleDefault(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(string("REST API. Get the fuck out!"))) +func (s *Server) defaultHandler(c echo.Context) error { + return echo.NewHTTPError(http.StatusMethodNotAllowed, "Method not allowed.") } From f30344c658f21a845418b98b55ef52bc5dca5577 Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Sat, 26 Sep 2020 23:27:30 +0200 Subject: [PATCH 7/7] Removed useless Server struct --- main.go | 38 ++++++++++++++++++++++++++++------ server/server.go | 53 ------------------------------------------------ 2 files changed, 32 insertions(+), 59 deletions(-) delete mode 100644 server/server.go diff --git a/main.go b/main.go index 4a6b2c9..cb39d7c 100644 --- a/main.go +++ b/main.go @@ -2,18 +2,37 @@ package main import ( "context" - "go-rest-api/server" + "go-rest-api/handler" "log" + "net/http" "os" "os/signal" "time" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" ) +var port = ":8000" + func main() { - s := server.NewServer(":8000") + e := echo.New() + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOrigins: []string{"http://localhost:8000"}, + AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept}, + })) + + handler.AttachArticleHandlersToRouter(e) + + e.Static("/", "./public") + e.GET("/", defaultHandler) go func() { - s.Serve() + if err := e.Start(port); err != nil { + e.Logger.Info("Shutting down the server...") + } }() signCh := make(chan os.Signal) @@ -21,8 +40,15 @@ func main() { signal.Notify(signCh, os.Kill) sig := <-signCh - log.Println("Received terminal, graceful shutdown", sig) + log.Println("Received terminal, graceful shutdown.", sig) - tc, _ := context.WithTimeout(context.Background(), 30*time.Second) - s.Shutdown(tc) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + if err := e.Shutdown(ctx); err != nil { + e.Logger.Fatal(err) + } +} + +func defaultHandler(c echo.Context) error { + return echo.NewHTTPError(http.StatusMethodNotAllowed, "Method not allowed.") } diff --git a/server/server.go b/server/server.go deleted file mode 100644 index 746cf02..0000000 --- a/server/server.go +++ /dev/null @@ -1,53 +0,0 @@ -package server - -import ( - "context" - "go-rest-api/handler" - "net/http" - - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" -) - -// Server struct -type Server struct { - port string - server *http.Server -} - -// NewServer func -func NewServer(port string) Server { - return Server{ - server: &http.Server{ - Addr: port, - }, - } -} - -// Serve func -func (s *Server) Serve() { - e := echo.New() - - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - AllowOrigins: []string{"http://localhost:8000"}, - AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept}, - })) - - handler.AttachArticleHandlersToRouter(e) - - e.Static("/", "./public") - e.GET("/", s.defaultHandler) - - e.Logger.Fatal(e.StartServer(s.server)) -} - -// Shutdown func -func (s *Server) Shutdown(tc context.Context) { - s.server.Shutdown(tc) -} - -func (s *Server) defaultHandler(c echo.Context) error { - return echo.NewHTTPError(http.StatusMethodNotAllowed, "Method not allowed.") -}