Skip to content

Instantly share code, notes, and snippets.

@lmas
Created November 28, 2018 21:18
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 lmas/95f3e991d49f69bcdfa34b21777908ea to your computer and use it in GitHub Desktop.
Save lmas/95f3e991d49f69bcdfa34b21777908ea to your computer and use it in GitHub Desktop.
Some simple http utils (http handlers with errors, secure cookies)
import (
"net/http"
"time"
"github.com/gorilla/securecookie"
)
type WebError struct {
Code int
Err error
}
func (e WebError) Error() string {
return e.Err.Error()
}
func (e WebError) Status() int {
return e.Code
}
type H func(w http.ResponseWriter, r *http.Request) error
func Handler(h H) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8") // default
err := h(w, r)
if err != nil {
switch e := err.(type) {
case WebError:
http.Error(w, e.Error(), e.Status())
default:
log.Printf("server error: %s\n", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
}
}
})
}
func WebClientAddr(r *http.Request) string {
addr := r.Header.Get("x-forwarded-for") // Possible proxy addr
if addr == "" {
addr = r.RemoteAddr // fallback
}
return addr
}
////////////////////////////////////////////////////////////////////////////////
const (
cookieName = "session"
cookieExpire = 24 * time.Hour
)
var (
hashKey = securecookie.GenerateRandomKey(64)
blockKey = securecookie.GenerateRandomKey(32)
cookieEncoder = securecookie.New(hashKey, blockKey).MaxAge(int(cookieExpire.Seconds()))
)
func defaultCookie() *http.Cookie {
return &http.Cookie{
Name: cookieName,
Path: "/",
SameSite: http.SameSiteStrictMode, // Prevents CSRF
HttpOnly: true,
//Secure: true, // NOTE: only works when we run the site behind TLS
// NOTE: don't forget to set these values on the new cookie
//Value: token,
//Expires: time.Now().Add(expire),
//MaxAge: int(expire.Seconds()),
}
}
func SetCookie(w http.ResponseWriter, data string) {
cookie := defaultCookie()
if data != "" {
val, err := cookieEncoder.Encode(cookieName, data)
if err != nil {
// silently ignore errors, no cookies will be set. sue me
// this should never happen with a string?
return
}
cookie.Value = val
cookie.Expires = time.Now().Add(cookieExpire)
cookie.MaxAge = int(cookieExpire.Seconds())
}
http.SetCookie(w, cookie)
}
func GetCookie(r *http.Request) string {
cookie, err := r.Cookie(cookieName)
if err != nil {
return ""
}
var data string
err = cookieEncoder.Decode(cookieName, cookie.Value, &data)
if err != nil {
return ""
}
return data
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment