-
-
Save nguyenthenguyen/36a108cdf16786e9af5c to your computer and use it in GitHub Desktop.
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
package main | |
import ( | |
"database/sql" | |
"encoding/json" | |
"errors" | |
"fmt" | |
"log" | |
"net/http" | |
"time" | |
"github.com/gorilla/context" | |
"github.com/julienschmidt/httprouter" | |
"github.com/justinas/alice" | |
) | |
func recoverHandler(next http.Handler) http.Handler { | |
fn := func(w http.ResponseWriter, r *http.Request) { | |
defer func() { | |
if err := recover(); err != nil { | |
log.Printf("panic: %+v", err) | |
http.Error(w, http.StatusText(500), 500) | |
} | |
}() | |
next.ServeHTTP(w, r) | |
} | |
return http.HandlerFunc(fn) | |
} | |
func loggingHandler(next http.Handler) http.Handler { | |
fn := func(w http.ResponseWriter, r *http.Request) { | |
t1 := time.Now() | |
next.ServeHTTP(w, r) | |
t2 := time.Now() | |
log.Printf("[%s] %q %v\n", r.Method, r.URL.String(), t2.Sub(t1)) | |
} | |
return http.HandlerFunc(fn) | |
} | |
func aboutHandler(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprintf(w, "You are on the about page.") | |
} | |
func indexHandler(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprintf(w, "Welcome!") | |
} | |
type appContext struct { | |
db *sql.DB | |
} | |
func (c *appContext) authHandler(next http.Handler) http.Handler { | |
fn := func(w http.ResponseWriter, r *http.Request) { | |
authToken := r.Header.Get("Authorization") | |
user, err := map[string]interface{}{}, errors.New("test") | |
// user, err := getUser(c.db, authToken) | |
log.Println(authToken) | |
if err != nil { | |
http.Error(w, http.StatusText(401), 401) | |
return | |
} | |
context.Set(r, "user", user) | |
next.ServeHTTP(w, r) | |
} | |
return http.HandlerFunc(fn) | |
} | |
func (c *appContext) adminHandler(w http.ResponseWriter, r *http.Request) { | |
user := context.Get(r, "user") | |
// Maybe other operations on the database | |
json.NewEncoder(w).Encode(user) | |
} | |
func (c *appContext) teaHandler(w http.ResponseWriter, r *http.Request) { | |
params := context.Get(r, "params").(httprouter.Params) | |
log.Println(params.ByName("id")) | |
// tea := getTea(c.db, params.ByName("id")) | |
json.NewEncoder(w).Encode(nil) | |
} | |
// We could also put *httprouter.Router in a field to not get access to the original methods (GET, POST, etc. in uppercase) | |
type router struct { | |
*httprouter.Router | |
} | |
func (r *router) Get(path string, handler http.Handler) { | |
r.GET(path, wrapHandler(handler)) | |
} | |
func NewRouter() *router { | |
return &router{httprouter.New()} | |
} | |
func wrapHandler(h http.Handler) httprouter.Handle { | |
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | |
context.Set(r, "params", ps) | |
h.ServeHTTP(w, r) | |
} | |
} | |
func main() { | |
// db := sql.Open("postgres", "...") | |
appC := appContext{nil} | |
commonHandlers := alice.New(context.ClearHandler, loggingHandler, recoverHandler) | |
router := NewRouter() | |
router.Get("/admin", commonHandlers.Append(appC.authHandler).ThenFunc(appC.adminHandler)) | |
router.Get("/about", commonHandlers.ThenFunc(aboutHandler)) | |
router.Get("/", commonHandlers.ThenFunc(indexHandler)) | |
router.Get("/teas/:id", commonHandlers.ThenFunc(appC.teaHandler)) | |
http.ListenAndServe(":8080", router) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment