-
Notifications
You must be signed in to change notification settings - Fork 150
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
210 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package limiter_test | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/ulule/limiter" | ||
"github.com/ulule/limiter/drivers/store/memory" | ||
) | ||
|
||
func New(options ...limiter.Option) *limiter.Limiter { | ||
store := memory.NewStore() | ||
rate := limiter.Rate{ | ||
Period: 1 * time.Second, | ||
Limit: int64(10), | ||
} | ||
return limiter.New(store, rate, options...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package limiter | ||
|
||
import ( | ||
"net" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
var ( | ||
// DefaultIPv4Mask defines the default IPv4 mask used to obtain user IP. | ||
DefaultIPv4Mask = net.CIDRMask(32, 32) | ||
// DefaultIPv6Mask defines the default IPv6 mask used to obtain user IP. | ||
DefaultIPv6Mask = net.CIDRMask(128, 128) | ||
) | ||
|
||
// GetIP returns IP address from request. | ||
func (limiter *Limiter) GetIP(r *http.Request) net.IP { | ||
if limiter.Options.TrustForwardHeader { | ||
ip := r.Header.Get("X-Forwarded-For") | ||
if ip != "" { | ||
parts := strings.SplitN(ip, ",", 2) | ||
part := strings.TrimSpace(parts[0]) | ||
return net.ParseIP(part) | ||
} | ||
|
||
ip = strings.TrimSpace(r.Header.Get("X-Real-IP")) | ||
if ip != "" { | ||
return net.ParseIP(ip) | ||
} | ||
} | ||
|
||
remoteAddr := strings.TrimSpace(r.RemoteAddr) | ||
host, _, err := net.SplitHostPort(remoteAddr) | ||
if err != nil { | ||
return net.ParseIP(remoteAddr) | ||
} | ||
|
||
return net.ParseIP(host) | ||
} | ||
|
||
// GetIPWithMask returns IP address from request by applying a mask. | ||
func (limiter *Limiter) GetIPWithMask(r *http.Request) net.IP { | ||
ip := limiter.GetIP(r) | ||
if ip.To4() != nil { | ||
return ip.Mask(limiter.Options.IPv4Mask) | ||
} | ||
if ip.To16() != nil { | ||
return ip.Mask(limiter.Options.IPv6Mask) | ||
} | ||
return ip | ||
} | ||
|
||
// GetIPKey extracts IP from request and returns hashed IP to use as store key. | ||
func (limiter *Limiter) GetIPKey(r *http.Request) string { | ||
return limiter.GetIPWithMask(r).String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package limiter | ||
|
||
import ( | ||
"net" | ||
) | ||
|
||
// Option is a functional option. | ||
type Option func(*Options) | ||
|
||
// Options are limiter options. | ||
type Options struct { | ||
// IPv4Mask defines the mask used to obtain a IPv4 address. | ||
IPv4Mask net.IPMask | ||
// IPv6Mask defines the mask used to obtain a IPv6 address. | ||
IPv6Mask net.IPMask | ||
// TrustForwardHeader enable parsing of X-Real-IP and X-Forwarded-For headers to obtain user IP. | ||
TrustForwardHeader bool | ||
} | ||
|
||
// WithIPv4Mask will configure the limiter to use given mask for IPv4 address. | ||
func WithIPv4Mask(mask net.IPMask) Option { | ||
return func(o *Options) { | ||
o.IPv4Mask = mask | ||
} | ||
} | ||
|
||
// WithIPv6Mask will configure the limiter to use given mask for IPv6 address. | ||
func WithIPv6Mask(mask net.IPMask) Option { | ||
return func(o *Options) { | ||
o.IPv6Mask = mask | ||
} | ||
} | ||
|
||
// WithTrustForwardHeader will configure the limiter to trust X-Real-IP and X-Forwarded-For headers. | ||
func WithTrustForwardHeader(enable bool) Option { | ||
return func(o *Options) { | ||
o.TrustForwardHeader = enable | ||
} | ||
} |
Oops, something went wrong.