Skip to content

Instantly share code, notes, and snippets.

@alecthomas
Created May 22, 2014 19:37
Show Gist options
  • Save alecthomas/dde4346aeaf330862ca0 to your computer and use it in GitHub Desktop.
Save alecthomas/dde4346aeaf330862ca0 to your computer and use it in GitHub Desktop.
Convenient return handler for Martini JSON API calls
import (
"encoding/json"
"net/http"
"reflect"
"github.com/codegangsta/inject"
"github.com/go-martini/martini"
)
const (
contentType = "application/json; charset=UTF-8"
)
type APIResponse struct {
S int
E string `json:",omitempty"`
D interface{} `json:",omitempty"`
}
// Allows responses from request handles to be in the following form:
//
// (status, <json-encodable-object>)
// (status, error)
//
func MartiniReturnHandler() martini.ReturnHandler {
return func(ctx martini.Context, vals []reflect.Value) {
// No return value, we assume the function wrote out the response.
if len(vals) == 0 {
return
}
res := ctx.Get(inject.InterfaceOf((*http.ResponseWriter)(nil))).Interface().(http.ResponseWriter)
// req := ctx.Get(reflect.TypeOf(&http.Request{})).Interface().(*http.Request)
var responseVal reflect.Value
status := 200
if len(vals) > 1 && vals[0].Kind() == reflect.Int {
status = int(vals[0].Int())
responseVal = vals[1]
if res.Header().Get("Content-Type") == "" {
switch responseVal.Interface().(type) {
case []byte:
res.Header().Set("Content-Type", "application/octet-stream")
case string:
res.Header().Set("Content-Type", "text/html; charset=utf-8")
case error:
res.Header().Set("Content-Type", contentType)
default:
res.Header().Set("Content-Type", contentType)
}
}
res.WriteHeader(status)
} else if len(vals) > 0 {
responseVal = vals[0]
}
if canDeref(responseVal) {
responseVal = responseVal.Elem()
}
enc := json.NewEncoder(res)
switch v := responseVal.Interface().(type) {
case string:
res.Write([]byte(v))
case []byte:
res.Write(v)
case error:
enc.Encode(&APIResponse{
S: status,
E: v.Error(),
})
default:
enc.Encode(&APIResponse{
S: status,
D: v,
})
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment