render.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. xmlRender struct{}
  18. plainTextRender struct{}
  19. htmlPlainRender struct{}
  20. redirectRender struct{}
  21. HTMLRender struct {
  22. Template *template.Template
  23. }
  24. )
  25. var (
  26. JSON = jsonRender{}
  27. XML = xmlRender{}
  28. HTMLPlain = htmlPlainRender{}
  29. Plain = plainTextRender{}
  30. Redirect = redirectRender{}
  31. )
  32. func (_ redirectRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  33. w.Header().Set("Location", data[0].(string))
  34. w.WriteHeader(code)
  35. return nil
  36. }
  37. func (_ jsonRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  38. WriteHeader(w, code, "application/json")
  39. return json.NewEncoder(w).Encode(data[0])
  40. }
  41. func (_ xmlRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  42. WriteHeader(w, code, "application/xml")
  43. return xml.NewEncoder(w).Encode(data[0])
  44. }
  45. func (_ plainTextRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
  46. WriteHeader(w, code, "text/plain")
  47. format := data[0].(string)
  48. args := data[1].([]interface{})
  49. if len(args) > 0 {
  50. _, err = w.Write([]byte(fmt.Sprintf(format, args...)))
  51. } else {
  52. _, err = w.Write([]byte(format))
  53. }
  54. return
  55. }
  56. func (_ htmlPlainRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
  57. WriteHeader(w, code, "text/html")
  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 (html HTMLRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
  68. WriteHeader(w, code, "text/html")
  69. file := data[0].(string)
  70. args := data[1]
  71. return html.Template.ExecuteTemplate(w, file, args)
  72. }
  73. func WriteHeader(w http.ResponseWriter, code int, contentType string) {
  74. contentType = joinStrings(contentType, "; charset=utf-8")
  75. w.Header().Set("Content-Type", contentType)
  76. w.WriteHeader(code)
  77. }
  78. func joinStrings(a ...string) string {
  79. if len(a) == 0 {
  80. return ""
  81. }
  82. if len(a) == 1 {
  83. return a[0]
  84. }
  85. n := 0
  86. for i := 0; i < len(a); i++ {
  87. n += len(a[i])
  88. }
  89. b := make([]byte, n)
  90. n = 0
  91. for _, s := range a {
  92. n += copy(b[n:], s)
  93. }
  94. return string(b)
  95. }