utils.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 gin
  5. import (
  6. "encoding/xml"
  7. "net/http"
  8. "os"
  9. "path"
  10. "reflect"
  11. "runtime"
  12. "strings"
  13. )
  14. // BindKey indicates a default bind key.
  15. const BindKey = "_gin-gonic/gin/bindkey"
  16. // Bind is a helper function for given interface object and returns a Gin middleware.
  17. func Bind(val interface{}) HandlerFunc {
  18. value := reflect.ValueOf(val)
  19. if value.Kind() == reflect.Ptr {
  20. panic(`Bind struct can not be a pointer. Example:
  21. Use: gin.Bind(Struct{}) instead of gin.Bind(&Struct{})
  22. `)
  23. }
  24. typ := value.Type()
  25. return func(c *Context) {
  26. obj := reflect.New(typ).Interface()
  27. if c.Bind(obj) == nil {
  28. c.Set(BindKey, obj)
  29. }
  30. }
  31. }
  32. // WrapF is a helper function for wrapping http.HandlerFunc and returns a Gin middleware.
  33. func WrapF(f http.HandlerFunc) HandlerFunc {
  34. return func(c *Context) {
  35. f(c.Writer, c.Request)
  36. }
  37. }
  38. // WrapH is a helper function for wrapping http.Handler and returns a Gin middleware.
  39. func WrapH(h http.Handler) HandlerFunc {
  40. return func(c *Context) {
  41. h.ServeHTTP(c.Writer, c.Request)
  42. }
  43. }
  44. // H is a shortcut for map[string]interface{}
  45. type H map[string]interface{}
  46. // MarshalXML allows type H to be used with xml.Marshal.
  47. func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
  48. start.Name = xml.Name{
  49. Space: "",
  50. Local: "map",
  51. }
  52. if err := e.EncodeToken(start); err != nil {
  53. return err
  54. }
  55. for key, value := range h {
  56. elem := xml.StartElement{
  57. Name: xml.Name{Space: "", Local: key},
  58. Attr: []xml.Attr{},
  59. }
  60. if err := e.EncodeElement(value, elem); err != nil {
  61. return err
  62. }
  63. }
  64. return e.EncodeToken(xml.EndElement{Name: start.Name})
  65. }
  66. func assert1(guard bool, text string) {
  67. if !guard {
  68. panic(text)
  69. }
  70. }
  71. func filterFlags(content string) string {
  72. for i, char := range content {
  73. if char == ' ' || char == ';' {
  74. return content[:i]
  75. }
  76. }
  77. return content
  78. }
  79. func chooseData(custom, wildcard interface{}) interface{} {
  80. if custom == nil {
  81. if wildcard == nil {
  82. panic("negotiation config is invalid")
  83. }
  84. return wildcard
  85. }
  86. return custom
  87. }
  88. func parseAccept(acceptHeader string) []string {
  89. parts := strings.Split(acceptHeader, ",")
  90. out := make([]string, 0, len(parts))
  91. for _, part := range parts {
  92. if part = strings.TrimSpace(strings.Split(part, ";")[0]); part != "" {
  93. out = append(out, part)
  94. }
  95. }
  96. return out
  97. }
  98. func lastChar(str string) uint8 {
  99. if str == "" {
  100. panic("The length of the string can't be 0")
  101. }
  102. return str[len(str)-1]
  103. }
  104. func nameOfFunction(f interface{}) string {
  105. return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
  106. }
  107. func joinPaths(absolutePath, relativePath string) string {
  108. if relativePath == "" {
  109. return absolutePath
  110. }
  111. finalPath := path.Join(absolutePath, relativePath)
  112. appendSlash := lastChar(relativePath) == '/' && lastChar(finalPath) != '/'
  113. if appendSlash {
  114. return finalPath + "/"
  115. }
  116. return finalPath
  117. }
  118. func resolveAddress(addr []string) string {
  119. switch len(addr) {
  120. case 0:
  121. if port := os.Getenv("PORT"); port != "" {
  122. debugPrint("Environment variable PORT=\"%s\"", port)
  123. return ":" + port
  124. }
  125. debugPrint("Environment variable PORT is undefined. Using port :8080 by default")
  126. return ":8080"
  127. case 1:
  128. return addr[0]
  129. default:
  130. panic("too many parameters")
  131. }
  132. }