| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
- // Use of this source code is governed by a MIT style
- // license that can be found in the LICENSE file.
- package gin
- import (
- "log"
- "net"
- "net/http"
- "strings"
- "github.com/gin-gonic/gin/binding"
- )
- const (
- MIMEJSON = binding.MIMEJSON
- MIMEHTML = binding.MIMEHTML
- MIMEXML = binding.MIMEXML
- MIMEXML2 = binding.MIMEXML2
- MIMEPlain = binding.MIMEPlain
- MIMEPOSTForm = binding.MIMEPOSTForm
- MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
- )
- // DEPRECATED, use Bind() instead.
- // Like ParseBody() but this method also writes a 400 error if the json is not valid.
- func (c *Context) EnsureBody(item interface{}) bool {
- return c.Bind(item)
- }
- // DEPRECATED use bindings directly
- // Parses the body content as a JSON input. It decodes the json payload into the struct specified as a pointer.
- func (c *Context) ParseBody(item interface{}) error {
- return binding.JSON.Bind(c.Request, item)
- }
- // DEPRECATED use gin.Static() instead
- // ServeFiles serves files from the given file system root.
- // The path must end with "/*filepath", files are then served from the local
- // path /defined/root/dir/*filepath.
- // For example if root is "/etc" and *filepath is "passwd", the local file
- // "/etc/passwd" would be served.
- // Internally a http.FileServer is used, therefore http.NotFound is used instead
- // of the Router's NotFound handler.
- // To use the operating system's file system implementation,
- // use http.Dir:
- // router.ServeFiles("/src/*filepath", http.Dir("/var/www"))
- func (engine *Engine) ServeFiles(path string, root http.FileSystem) {
- engine.router.ServeFiles(path, root)
- }
- // DEPRECATED use gin.LoadHTMLGlob() or gin.LoadHTMLFiles() instead
- func (engine *Engine) LoadHTMLTemplates(pattern string) {
- engine.LoadHTMLGlob(pattern)
- }
- // DEPRECATED. Use NoRoute() instead
- func (engine *Engine) NotFound404(handlers ...HandlerFunc) {
- engine.NoRoute(handlers...)
- }
- // the ForwardedFor middleware unwraps the X-Forwarded-For headers, be careful to only use this
- // middleware if you've got servers in front of this server. The list with (known) proxies and
- // local ips are being filtered out of the forwarded for list, giving the last not local ip being
- // the real client ip.
- func ForwardedFor(proxies ...interface{}) HandlerFunc {
- if len(proxies) == 0 {
- // default to local ips
- var reservedLocalIps = []string{"10.0.0.0/8", "127.0.0.1/32", "172.16.0.0/12", "192.168.0.0/16"}
- proxies = make([]interface{}, len(reservedLocalIps))
- for i, v := range reservedLocalIps {
- proxies[i] = v
- }
- }
- return func(c *Context) {
- // the X-Forwarded-For header contains an array with left most the client ip, then
- // comma separated, all proxies the request passed. The last proxy appears
- // as the remote address of the request. Returning the client
- // ip to comply with default RemoteAddr response.
- // check if remoteaddr is local ip or in list of defined proxies
- remoteIp := net.ParseIP(strings.Split(c.Request.RemoteAddr, ":")[0])
- if !ipInMasks(remoteIp, proxies) {
- return
- }
- if forwardedFor := c.Request.Header.Get("X-Forwarded-For"); forwardedFor != "" {
- parts := strings.Split(forwardedFor, ",")
- for i := len(parts) - 1; i >= 0; i-- {
- part := parts[i]
- ip := net.ParseIP(strings.TrimSpace(part))
- if ipInMasks(ip, proxies) {
- continue
- }
- // returning remote addr conform the original remote addr format
- c.Request.RemoteAddr = ip.String() + ":0"
- // remove forwarded for address
- c.Request.Header.Set("X-Forwarded-For", "")
- return
- }
- }
- }
- }
- func ipInMasks(ip net.IP, masks []interface{}) bool {
- for _, proxy := range masks {
- var mask *net.IPNet
- var err error
- switch t := proxy.(type) {
- case string:
- if _, mask, err = net.ParseCIDR(t); err != nil {
- log.Panic(err)
- }
- case net.IP:
- mask = &net.IPNet{IP: t, Mask: net.CIDRMask(len(t)*8, len(t)*8)}
- case net.IPNet:
- mask = &t
- }
- if mask.Contains(ip) {
- return true
- }
- }
- return false
- }
|