Skip to content

Instantly share code, notes, and snippets.

@imjasonh
Created December 19, 2012 15:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save imjasonh/4337383 to your computer and use it in GitHub Desktop.
Save imjasonh/4337383 to your computer and use it in GitHub Desktop.
Recipe to require that a user log in before reaching an http Handler func, without specifying it in app.yaml (similar to Python App Engine's @login_required decorator)
package mustlogin
import (
"appengine"
"appengine/user"
"fmt"
"net/http"
)
func init() {
http.HandleFunc("/1", MustLogin(loggedIn))
http.Handle("/2", MustLoginHandler{loggedIn})
}
func loggedIn(w http.ResponseWriter, r *http.Request, u user.User) {
fmt.Fprintln(w, "<html><body>")
fmt.Fprintln(w, u.Email)
url, _ := user.LogoutURL(appengine.NewContext(r), r.URL.String())
fmt.Fprintln(w, "<br /><a href=\""+url+"\">Log out</a>")
fmt.Fprintln(w, "</body></html>")
}
// Option 1: Use a closure
func MustLogin(done func(http.ResponseWriter, *http.Request, user.User)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
if u := user.Current(c); u == nil {
url, _ := user.LoginURL(c, r.URL.String())
http.Redirect(w, r, url, http.StatusSeeOther)
} else {
done(w, r, *u)
}
}
}
// Option 2: Use a http.Handler
type MustLoginHandler struct {
inner func(http.ResponseWriter, *http.Request, user.User)
}
func (h MustLoginHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
if u := user.Current(c); u == nil {
url, _ := user.LoginURL(c, r.URL.String())
http.Redirect(w, r, url, http.StatusSeeOther)
} else {
h.inner(w, r, *u)
}
}
@groks
Copy link

groks commented Dec 26, 2012

A Handler doesn't need to be a struct: https://gist.github.com/4381796

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment