...

Source file src/github.com/gin-gonic/gin/utils.go

Documentation: github.com/gin-gonic/gin

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

View as plain text