Created
October 5, 2020 13:13
-
-
Save rogiervandenberg/97e24f0d12404ec0e2a63d500bde157e to your computer and use it in GitHub Desktop.
Basis Golang HTTP REST server - Best practices interpreted
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Based on the video's and blogposts of Mat Ryer (@matryer).. | |
- https://pace.dev/blog/2018/05/09/how-I-write-http-services-after-eight-years.html | |
- https://www.youtube.com/watch?v=FkPqqakDeRY | |
- https://www.youtube.com/watch?v=rWBSMsLG8po | |
.. I derived the following starting point for a GO HTTP REST server. It can be used to add all explained (see above) concepts. | |
You could spread the code below in separate files as follows: | |
├── cmd | |
│ └── main.go | |
├── handle_index.go | |
├── handle_index_test.go | |
├── routes.go | |
└── server.go | |
*/ | |
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"net/http" | |
"github.com/gorilla/mux" | |
) | |
func main() { | |
NewServer() | |
} | |
// ------------------- server.go | |
type server struct { | |
router *mux.Router | |
} | |
// NewServer creates a server with router and does all things from here | |
func NewServer() { | |
s := &server{mux.NewRouter()} | |
s.routes() | |
log.Fatalln(http.ListenAndServe(":8080", s.router)) | |
} | |
// ------------------- routes.go | |
func (s *server) routes() { | |
s.router.HandleFunc("/", s.handleIndex()) | |
s.router.HandleFunc("/admin-ok", s.handleAdmin()) | |
s.router.HandleFunc("/admin-not-ok", s.adminOnly(s.handleAdmin())) | |
} | |
// ------------------- Handle functions below | |
func (s *server) handleIndex() http.HandlerFunc { | |
// Let's do some JSON output here | |
type response struct { | |
Greeting string `json:"greeting"` | |
} | |
return func(w http.ResponseWriter, r *http.Request) { | |
greet := response{"Hello world"} | |
js, err := json.Marshal(greet) | |
if err != nil { | |
http.Error(w, err.Error(), http.StatusInternalServerError) | |
return | |
} | |
w.Header().Set("Content-Type", "application/json") | |
w.Write(js) | |
} | |
} | |
func (s *server) handleAdmin() http.HandlerFunc { | |
// Here you can prepare a 'private thing' to use in the | |
return func(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprintf(w, "Hello Admin!") | |
} | |
} | |
func (s *server) adminOnly(h http.HandlerFunc) http.HandlerFunc { | |
return func(w http.ResponseWriter, r *http.Request) { | |
if true { // instead of "true" e.g. "!currentUser(r).IsAdmin" | |
http.NotFound(w, r) | |
return | |
} | |
h(w, r) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment