render.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. req := data[0].(*http.Request)
  36. location := data[1].(string)
  37. http.Redirect(w, req, location, code)
  38. return nil
  39. }
  40. func (_ jsonRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  41. WriteHeader(w, code, "application/json")
  42. return json.NewEncoder(w).Encode(data[0])
  43. }
  44. func (_ indentedJSON) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  45. WriteHeader(w, code, "application/json")
  46. jsonData, err := json.MarshalIndent(data[0], "", " ")
  47. if err != nil {
  48. return err
  49. }
  50. _, err = w.Write(jsonData)
  51. return err
  52. }
  53. func (_ xmlRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  54. WriteHeader(w, code, "application/xml")
  55. return xml.NewEncoder(w).Encode(data[0])
  56. }
  57. func (_ plainTextRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
  58. WriteHeader(w, code, "text/plain")
  59. format := data[0].(string)
  60. args := data[1].([]interface{})
  61. if len(args) > 0 {
  62. _, err = fmt.Fprintf(w, format, args...)
  63. } else {
  64. _, err = w.Write([]byte(format))
  65. }
  66. return
  67. }
  68. func (_ htmlPlainRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
  69. WriteHeader(w, code, "text/html")
  70. format := data[0].(string)
  71. args := data[1].([]interface{})
  72. if len(args) > 0 {
  73. _, err = fmt.Fprintf(w, format, args...)
  74. } else {
  75. _, err = w.Write([]byte(format))
  76. }
  77. return
  78. }
  79. func (html HTMLRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  80. WriteHeader(w, code, "text/html")
  81. file := data[0].(string)
  82. args := data[1]
  83. return html.Template.ExecuteTemplate(w, file, args)
  84. }
  85. func WriteHeader(w http.ResponseWriter, code int, contentType string) {
  86. contentType = joinStrings(contentType, "; charset=utf-8")
  87. w.Header().Set("Content-Type", contentType)
  88. w.WriteHeader(code)
  89. }
  90. func joinStrings(a ...string) string {
  91. if len(a) == 0 {
  92. return ""
  93. }
  94. if len(a) == 1 {
  95. return a[0]
  96. }
  97. n := 0
  98. for i := 0; i < len(a); i++ {
  99. n += len(a[i])
  100. }
  101. b := make([]byte, n)
  102. n = 0
  103. for _, s := range a {
  104. n += copy(b[n:], s)
  105. }
  106. return string(b)
  107. }