codegangsta/martini — pull request #158 by googollee (2014-01-22 00:36:04+00:00)
Title: Pass context to return handler

As return handler is a part of the http process, it's more suitable passing Context to it. With Context, midware like martini-contrib/encoder can get encoder from Context in return handler and do output directly, no need to pass string between functions, and reduce the memory usage.

It can make a more clean handler for apis, like below:

```
package main

import (
"encoding/json"
"fmt"
"github.com/googollee/martini"
"io"
"net/http"
"reflect"
)

func main() {
m := martini.Classic()
m.Map(APIEncoder)
m.Use(API)
m.Get("/", func() string {
return "Hello world!"
})
m.Run()
}

type Encoder interface {
Encode(v interface{}) error
}

var EncoderType = reflect.TypeOf((*Encoder)(nil)).Elem()

type TextEncoder struct {
w io.Writer
}

func NewTextEncoder(w io.Writer) *TextEncoder {
return &TextEncoder{
w: w,
}
}

func (e *TextEncoder) Encode(v interface{}) error {
_, err := fmt.Fprintf(e.w, "%v", v)
return err
}

func writeAPI(ctx martini.Context, vals []reflect.Value) {
v := ctx.Get(EncoderType)
encoder := v.Interface().(Encoder)
encoder.Encode(vals[0].Interface())
}

var APIEncoder martini.ReturnHandler = writeAPI

func API(ctx martini.Context, w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Content-Type") == "application/json" {
ctx.MapTo(json.NewEncoder(w), (*Encoder)(nil))
w.Header().Set("Context-Type", "application/json")
return
}
ctx.MapTo(NewTextEncoder(w), (*Encoder)(nil))
}
```