Skip to content

Instantly share code, notes, and snippets.

@nguyenthenguyen
Forked from nmerouze/main.go
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nguyenthenguyen/36a108cdf16786e9af5c to your computer and use it in GitHub Desktop.
Save nguyenthenguyen/36a108cdf16786e9af5c to your computer and use it in GitHub Desktop.
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