return.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package tango
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "net/http"
  6. "reflect"
  7. )
  8. const (
  9. AutoResponse = iota
  10. JsonResponse
  11. XmlResponse
  12. )
  13. type ResponseTyper interface {
  14. ResponseType() int
  15. }
  16. type Json struct {}
  17. func (Json) ResponseType() int {
  18. return JsonResponse
  19. }
  20. type Xml struct {}
  21. func (Xml) ResponseType() int {
  22. return XmlResponse
  23. }
  24. func isNil(a interface{}) bool {
  25. if a == nil {
  26. return true
  27. }
  28. aa := reflect.ValueOf(a)
  29. return !aa.IsValid() || (aa.Type().Kind() == reflect.Ptr && aa.IsNil())
  30. }
  31. type XmlError struct {
  32. XMLName xml.Name `xml:"err"`
  33. Content string `xml:"content"`
  34. }
  35. type XmlString struct {
  36. XMLName xml.Name `xml:"string"`
  37. Content string `xml:"content"`
  38. }
  39. func Return() HandlerFunc {
  40. return func(ctx *Context) {
  41. var rt int
  42. action := ctx.Action()
  43. if action != nil {
  44. if i, ok := action.(ResponseTyper); ok {
  45. rt = i.ResponseType()
  46. }
  47. }
  48. ctx.Next()
  49. // if no route match or has been write, then return
  50. if action == nil || ctx.Written() {
  51. return
  52. }
  53. // if there is no return value or return nil
  54. if isNil(ctx.Result) {
  55. // then we return blank page
  56. ctx.Result = ""
  57. }
  58. if rt == JsonResponse {
  59. encoder := json.NewEncoder(ctx)
  60. ctx.Header().Set("Content-Type", "application/json")
  61. switch res := ctx.Result.(type) {
  62. case AbortError:
  63. ctx.WriteHeader(res.Code())
  64. encoder.Encode(map[string]string{
  65. "err": res.Error(),
  66. })
  67. case error:
  68. encoder.Encode(map[string]string{
  69. "err": res.Error(),
  70. })
  71. case string:
  72. encoder.Encode(map[string]string{
  73. "content": res,
  74. })
  75. case []byte:
  76. encoder.Encode(map[string]string{
  77. "content": string(res),
  78. })
  79. default:
  80. err := encoder.Encode(ctx.Result)
  81. if err != nil {
  82. ctx.Result = err
  83. encoder.Encode(map[string]string{
  84. "err": err.Error(),
  85. })
  86. }
  87. }
  88. return
  89. } else if rt == XmlResponse {
  90. encoder := xml.NewEncoder(ctx)
  91. ctx.Header().Set("Content-Type", "application/xml")
  92. switch res := ctx.Result.(type) {
  93. case AbortError:
  94. ctx.WriteHeader(res.Code())
  95. encoder.Encode(XmlError{
  96. Content: res.Error(),
  97. })
  98. case error:
  99. encoder.Encode(XmlError{
  100. Content: res.Error(),
  101. })
  102. case string:
  103. encoder.Encode(XmlString{
  104. Content: res,
  105. })
  106. case []byte:
  107. encoder.Encode(XmlString{
  108. Content: string(res),
  109. })
  110. default:
  111. err := encoder.Encode(ctx.Result)
  112. if err != nil {
  113. ctx.Result = err
  114. encoder.Encode(XmlError{
  115. Content: err.Error(),
  116. })
  117. }
  118. }
  119. return
  120. }
  121. switch res := ctx.Result.(type) {
  122. case AbortError, error:
  123. ctx.HandleError()
  124. case []byte:
  125. ctx.WriteHeader(http.StatusOK)
  126. ctx.Write(res)
  127. case string:
  128. ctx.WriteHeader(http.StatusOK)
  129. ctx.Write([]byte(res))
  130. }
  131. }
  132. }