// Returns vulcan library compatible middleware func (r *RateLimit) NewHandler(next http.Handler) (http.Handler, error) { defaultRates := ratelimit.NewRateSet() if err := defaultRates.Add(time.Duration(r.PeriodSeconds)*time.Second, r.Requests, r.Burst); err != nil { return nil, err } return ratelimit.New(next, r.extract, defaultRates, ratelimit.ExtractRates(r.extractRates), ratelimit.Clock(r.clock)) }
func makeRateExtractor(variable string) (ratelimit.RateExtractor, error) { if variable == "" { return nil, nil } if !strings.HasPrefix(variable, "request.header.") { return nil, fmt.Errorf("unsupported variable format: %v", variable) } header := strings.TrimPrefix(variable, "request.header.") if len(header) == 0 { return nil, fmt.Errorf("Wrong header: %s", header) } return ratelimit.RateExtractorFunc(func(r *http.Request) (*ratelimit.RateSet, error) { jsonString := r.Header.Get(header) if jsonString == "" { return nil, fmt.Errorf("empty rate header") } var specs []rateSpec if err := json.Unmarshal([]byte(jsonString), &specs); err != nil { return nil, err } rateSet := ratelimit.NewRateSet() for _, s := range specs { period := time.Duration(s.PeriodSeconds) * time.Second if s.Burst == 0 { s.Burst = s.Requests } if err := rateSet.Add(period, s.Requests, s.Burst); err != nil { return nil, err } } return rateSet, nil }), nil }