Example #1
0
// Limit the amount of requests one IP can do per second.
//
// fillrate = Amount of requests allowed in one second
// capacity = Amount of 'extra'(burst) requests a-top fillrate allowed
// delay = Duration before changing http status 429 to 503
//
// If the fillrate+capacity are overloaded a HTTP 429 is returned
// If the callee keeps firing requests the 429 is changed into a 503
// if delay is passed.
func Use(fillrate float64, capacity float64) middleware.HandlerFunc {
	cache = lru.New(CacheSize)

	// Some sanity checks on fillrate and capacity
	if fillrate > capacity {
		panic("ratelimit: fillrate must be equal to or lower than capacity")
	}

	if fillrate < 1.0 {
		panic("ratelimit: fillrate must be equal to or higher than 1")
	}

	// Everything is OK
	return func(w http.ResponseWriter, r *http.Request) bool {
		httpCode := check(r.RemoteAddr, fillrate, capacity)
		switch httpCode {
		case StatusRateLimit:
			// Ratelimit request
			log.Println("ratelimit: Dropped HTTP %s (IP=%s)", r.URL.String(), r.RemoteAddr)
			w.Header().Set("Retry-After", strconv.Itoa(Delay))
			w.WriteHeader(StatusRateLimit)
			if e := httpd.FlushJson(w, httpd.Reply(false, StatusRateLimitText)); e != nil {
				httpd.Error(w, e, "Flush failed")
			}
			return false
		case http.StatusServiceUnavailable:
			// Abusive client, responding less friendly
			log.Println("ratelimit: Banned abusive HTTP %s (IP=%s)", r.URL.String(), r.RemoteAddr)
			w.Header().Set("Retry-After", strconv.Itoa(Delay))
			w.WriteHeader(http.StatusServiceUnavailable)
			if e := httpd.FlushJson(w, httpd.Reply(false, http.StatusText(http.StatusServiceUnavailable))); e != nil {
				httpd.Error(w, e, "Flush failed")
			}
			return false
		default:
			return true
		}
	}
}
Example #2
0
func verbose(w http.ResponseWriter, r *http.Request) {
	msg := `{success: true, msg: "Set verbosity to `
	if config.Verbose {
		config.Verbose = false
		msg += "OFF"
	} else {
		config.Verbose = true
		msg += "ON"
	}
	msg += `"}`

	if _, e := w.Write([]byte(msg)); e != nil {
		httpd.Error(w, e, "Flush failed")
		return
	}
}