예제 #1
0
// RateLimitLB is very similar to RateLimit but it takes the X-Forwarded-For
// header in cosideration when trying to figure the IP address of the client.
// This is useful for when running a server behind a load balancer or proxy.
//
// However, this header can be spoofed by the client, so in some cases it could
// provide a way of getting around the rate limiter.
//
// When using this middleware, make sure the load balancer will strip any
// X-Forwarded-For headers set by the client, and that the server will not be
// publicly accessible by the public, just the load balancer.
func RateLimitLB(client *redis.Client, hasher speedbump.RateHasher, max int64) gin.HandlerFunc {
	limiter := speedbump.NewLimiter(client, hasher, max)

	return func(c *gin.Context) {
		// Attempt to perform the request
		ip := GetRequesterAddress(c.Request)
		ok, err := limiter.Attempt(ip)

		if err != nil {
			panic(err)
		}

		if !ok {
			nextTime := time.Now().Add(hasher.Duration())

			c.JSON(429, gin.H{
				"status":   "error",
				"messages": []string{"Rate limit exceeded. Try again in " + humanize.Time(nextTime)},
			})
			c.Abort()
		}

		c.Next()

		// After the request
		// log.Print(ip + " was limited because it exceeded the max rate")
	}
}
예제 #2
0
func RateLimit(client *redis.Client, hasher speedbump.RateHasher, max int64) negroni.HandlerFunc {
	limiter := speedbump.NewLimiter(client, hasher, max)
	rnd := render.New()

	return func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
		ip, _, _ := net.SplitHostPort(r.RemoteAddr)
		ok, err := limiter.Attempt(ip)
		if err != nil {
			panic(err)
		}

		if !ok {
			nextTime := time.Now().Add(hasher.Duration())
			rnd.JSON(rw, 429, map[string]string{"error": "Rate limit exceeded. Try again in " + humanize.Time(nextTime)})
		} else {
			next(rw, r)
		}
	}
}