147 lines
2.8 KiB
Go
147 lines
2.8 KiB
Go
package tango
|
|
|
|
import (
|
|
"encoding/json"
|
|
"encoding/xml"
|
|
"net/http"
|
|
"reflect"
|
|
)
|
|
|
|
const (
|
|
AutoResponse = iota
|
|
JsonResponse
|
|
XmlResponse
|
|
)
|
|
|
|
type ResponseTyper interface {
|
|
ResponseType() int
|
|
}
|
|
|
|
type Json struct {}
|
|
func (Json) ResponseType() int {
|
|
return JsonResponse
|
|
}
|
|
|
|
type Xml struct {}
|
|
func (Xml) ResponseType() int {
|
|
return XmlResponse
|
|
}
|
|
|
|
func isNil(a interface{}) bool {
|
|
if a == nil {
|
|
return true
|
|
}
|
|
aa := reflect.ValueOf(a)
|
|
return !aa.IsValid() || (aa.Type().Kind() == reflect.Ptr && aa.IsNil())
|
|
}
|
|
|
|
type XmlError struct {
|
|
XMLName xml.Name `xml:"err"`
|
|
Content string `xml:"content"`
|
|
}
|
|
|
|
type XmlString struct {
|
|
XMLName xml.Name `xml:"string"`
|
|
Content string `xml:"content"`
|
|
}
|
|
|
|
func Return() HandlerFunc {
|
|
return func(ctx *Context) {
|
|
var rt int
|
|
action := ctx.Action()
|
|
if action != nil {
|
|
if i, ok := action.(ResponseTyper); ok {
|
|
rt = i.ResponseType()
|
|
}
|
|
}
|
|
|
|
ctx.Next()
|
|
|
|
// if no route match or has been write, then return
|
|
if action == nil || ctx.Written() {
|
|
return
|
|
}
|
|
|
|
// if there is no return value or return nil
|
|
if isNil(ctx.Result) {
|
|
// then we return blank page
|
|
ctx.Result = ""
|
|
}
|
|
|
|
if rt == JsonResponse {
|
|
encoder := json.NewEncoder(ctx)
|
|
ctx.Header().Set("Content-Type", "application/json")
|
|
switch res := ctx.Result.(type) {
|
|
case AbortError:
|
|
ctx.WriteHeader(res.Code())
|
|
encoder.Encode(map[string]string{
|
|
"err": res.Error(),
|
|
})
|
|
case error:
|
|
encoder.Encode(map[string]string{
|
|
"err": res.Error(),
|
|
})
|
|
case string:
|
|
encoder.Encode(map[string]string{
|
|
"content": res,
|
|
})
|
|
case []byte:
|
|
encoder.Encode(map[string]string{
|
|
"content": string(res),
|
|
})
|
|
default:
|
|
err := encoder.Encode(ctx.Result)
|
|
if err != nil {
|
|
ctx.Result = err
|
|
encoder.Encode(map[string]string{
|
|
"err": err.Error(),
|
|
})
|
|
}
|
|
}
|
|
|
|
return
|
|
} else if rt == XmlResponse {
|
|
encoder := xml.NewEncoder(ctx)
|
|
ctx.Header().Set("Content-Type", "application/xml")
|
|
switch res := ctx.Result.(type) {
|
|
case AbortError:
|
|
ctx.WriteHeader(res.Code())
|
|
encoder.Encode(XmlError{
|
|
Content: res.Error(),
|
|
})
|
|
case error:
|
|
encoder.Encode(XmlError{
|
|
Content: res.Error(),
|
|
})
|
|
case string:
|
|
encoder.Encode(XmlString{
|
|
Content: res,
|
|
})
|
|
case []byte:
|
|
encoder.Encode(XmlString{
|
|
Content: string(res),
|
|
})
|
|
default:
|
|
err := encoder.Encode(ctx.Result)
|
|
if err != nil {
|
|
ctx.Result = err
|
|
encoder.Encode(XmlError{
|
|
Content: err.Error(),
|
|
})
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
switch res := ctx.Result.(type) {
|
|
case AbortError, error:
|
|
ctx.HandleError()
|
|
case []byte:
|
|
ctx.WriteHeader(http.StatusOK)
|
|
ctx.Write(res)
|
|
case string:
|
|
ctx.WriteHeader(http.StatusOK)
|
|
ctx.Write([]byte(res))
|
|
}
|
|
}
|
|
} |