render.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
  2. // Use of this source code is governed by a MIT style
  3. // license that can be found in the LICENSE file.
  4. package render
  5. import (
  6. "encoding/json"
  7. "encoding/xml"
  8. "fmt"
  9. "html/template"
  10. "net/http"
  11. )
  12. type (
  13. Render interface {
  14. Render(http.ResponseWriter, int, ...interface{}) error
  15. }
  16. jsonRender struct{}
  17. indentedJSON struct{}
  18. xmlRender struct{}
  19. plainTextRender struct{}
  20. htmlPlainRender struct{}
  21. redirectRender struct{}
  22. HTMLRender struct {
  23. Template *template.Template
  24. }
  25. )
  26. var (
  27. JSON = jsonRender{}
  28. IndentedJSON = indentedJSON{}
  29. XML = xmlRender{}
  30. HTMLPlain = htmlPlainRender{}
  31. Plain = plainTextRender{}
  32. Redirect = redirectRender{}
  33. )
  34. func (_ redirectRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  35. w.Header().Set("Location", data[0].(string))
  36. w.WriteHeader(code)
  37. return nil
  38. }
  39. func (_ jsonRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  40. WriteHeader(w, code, "application/json")
  41. return json.NewEncoder(w).Encode(data[0])
  42. }
  43. func (_ indentedJSON) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  44. WriteHeader(w, code, "application/json")
  45. jsonData, err := json.MarshalIndent(data, "", " ")
  46. if err != nil {
  47. return err
  48. }
  49. _, err = w.Write(jsonData)
  50. return err
  51. }
  52. func (_ xmlRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  53. WriteHeader(w, code, "application/xml")
  54. return xml.NewEncoder(w).Encode(data[0])
  55. }
  56. func (_ plainTextRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
  57. WriteHeader(w, code, "text/plain")
  58. format := data[0].(string)
  59. args := data[1].([]interface{})
  60. if len(args) > 0 {
  61. _, err = w.Write([]byte(fmt.Sprintf(format, args...)))
  62. } else {
  63. _, err = w.Write([]byte(format))
  64. }
  65. return
  66. }
  67. func (_ htmlPlainRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
  68. WriteHeader(w, code, "text/html")
  69. format := data[0].(string)
  70. args := data[1].([]interface{})
  71. if len(args) > 0 {
  72. _, err = w.Write([]byte(fmt.Sprintf(format, args...)))
  73. } else {
  74. _, err = w.Write([]byte(format))
  75. }
  76. return
  77. }
  78. func (html HTMLRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  79. WriteHeader(w, code, "text/html")
  80. file := data[0].(string)
  81. args := data[1]
  82. return html.Template.ExecuteTemplate(w, file, args)
  83. }
  84. func WriteHeader(w http.ResponseWriter, code int, contentType string) {
  85. contentType = joinStrings(contentType, "; charset=utf-8")
  86. w.Header().Set("Content-Type", contentType)
  87. w.WriteHeader(code)
  88. }
  89. func joinStrings(a ...string) string {
  90. if len(a) == 0 {
  91. return ""
  92. }
  93. if len(a) == 1 {
  94. return a[0]
  95. }
  96. n := 0
  97. for i := 0; i < len(a); i++ {
  98. n += len(a[i])
  99. }
  100. b := make([]byte, n)
  101. n = 0
  102. for _, s := range a {
  103. n += copy(b[n:], s)
  104. }
  105. return string(b)
  106. }