Skip to content

Instantly share code, notes, and snippets.

@rogiervandenberg
Created October 5, 2020 13:13
Show Gist options
  • Save rogiervandenberg/97e24f0d12404ec0e2a63d500bde157e to your computer and use it in GitHub Desktop.
Save rogiervandenberg/97e24f0d12404ec0e2a63d500bde157e to your computer and use it in GitHub Desktop.
Basis Golang HTTP REST server - Best practices interpreted
/*
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