Skip to content

Instantly share code, notes, and snippets.

@icholy
Last active August 29, 2015 14:14
Show Gist options
  • Save icholy/030b5e1ca191828974fa to your computer and use it in GitHub Desktop.
Save icholy/030b5e1ca191828974fa to your computer and use it in GitHub Desktop.
package main
import (
"net/http"
"strconv"
)
type ParamParser struct {
params map[string]string
err error
}
func NewParamParser(params map[string]string) *ParamParser {
return &ParamParser{params, nil}
}
func paramParser(params martini.Params, c martini.Context) {
c.Map(NewParamParser(params))
}
func (pp *ParamParser) String(key string) string {
if pp.err != nil {
return ""
}
return pp.params[key]
}
func (pp *ParamParser) Int64(key string) int64 {
if pp.err != nil {
return 0
}
v, err := strconv.ParseInt(pp.params[key], 10, 64)
if err != nil {
pp.err = err
return 0
}
return v
}
func (pp *ParamParser) Int32(key string) int32 {
if pp.err != nil {
return 0
}
v, err := strconv.ParseInt(pp.params[key], 10, 32)
if err != nil {
pp.err = err
return 0
}
return int32(v)
}
func (pp *ParamParser) Int16(key string) int16 {
if pp.err != nil {
return 0
}
v, err := strconv.ParseInt(pp.params[key], 10, 16)
if err != nil {
pp.err = err
return 0
}
return int16(v)
}
func (pp *ParamParser) Int8(key string) int8 {
if pp.err != nil {
return 0
}
v, err := strconv.ParseInt(pp.params[key], 10, 8)
if err != nil {
pp.err = err
return 0
}
return int8(v)
}
func (pp *ParamParser) Int(key string) int {
if pp.err != nil {
return 0
}
v, err := strconv.ParseInt(pp.params[key], 10, 0)
if err != nil {
pp.err = err
return 0
}
return int(v)
}
func (pp *ParamParser) Bool(key string) bool {
if pp.err != nil {
return false
}
v, err := strconv.ParseBool(pp.params[key])
if err != nil {
pp.err = err
return false
}
return v
}
func (pp *ParamParser) Float64(key string) float64 {
if pp.err != nil {
return 0
}
v, err := strconv.ParseFloat(pp.params[key], 64)
if err != nil {
pp.err = err
return 0
}
return v
}
func (pp *ParamParser) Float32(key string) float32 {
if pp.err != nil {
return 0
}
v, err := strconv.ParseFloat(pp.params[key], 32)
if err != nil {
pp.err = err
return 0
}
return float32(v)
}
func (pp *ParamParser) Err() error {
return pp.err
}
func (pp *ParamParser) WriteErrTo(w http.ResponseWriter) bool {
if pp.err != nil {
http.Error(w, pp.err.Error(), http.StatusBadRequest)
return true
}
return false
}

This middleware simplifies error handling for parsing route parameters. The approach was taken from Rob Pike's post

r.Get(`/user/:user_id/friends/:friend_id`, paramParser,
  func(w http.ResponseWriter, params *ParamParser) {
    var (
      userID   = params.Int64("user_id")
      friendID = params.Int64("friend_id")
    )
    if err := params.Err(); err != nil {
      http.Error(w, err.Error(), http.StatusBadRequest)
      return
    }
    // etc ...
  })

r.Get(`/user/:user_id/friends/:friend_id`, paramParser,
  func(w http.ResponseWriter, params *ParamParser) {
    var (
      userID   = params.Int64("user_id")
      friendID = params.Int64("friend_id")
    )
    if params.WriteErrTo(w) {
      return
    }
    // etc ...
  })

r.Get(`/user/:user_id/friends/:friend_id`,
  func(w http.ResponseWriter, params martini.Params) {
    var (
      pp       = NewParamParser(params)
      userID   = pp.Int64("user_id")
      friendID = pp.Int64("friend_id")
    )
    if pp.WriteErrTo(w) {
      return
    }
    // etc ...
  })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment