File: map.go

package info (click to toggle)
golang-github-getsentry-sentry-go 0.29.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,404 kB
  • sloc: makefile: 75; sh: 21
file content (64 lines) | stat: -rw-r--r-- 1,699 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package ratelimit

import (
	"net/http"
	"time"
)

// Map maps categories to rate limit deadlines.
//
// A rate limit is in effect for a given category if either the category's
// deadline or the deadline for the special CategoryAll has not yet expired.
//
// Use IsRateLimited to check whether a category is rate-limited.
type Map map[Category]Deadline

// IsRateLimited returns true if the category is currently rate limited.
func (m Map) IsRateLimited(c Category) bool {
	return m.isRateLimited(c, time.Now())
}

func (m Map) isRateLimited(c Category, now time.Time) bool {
	return m.Deadline(c).After(Deadline(now))
}

// Deadline returns the deadline when the rate limit for the given category or
// the special CategoryAll expire, whichever is furthest into the future.
func (m Map) Deadline(c Category) Deadline {
	categoryDeadline := m[c]
	allDeadline := m[CategoryAll]
	if categoryDeadline.After(allDeadline) {
		return categoryDeadline
	}
	return allDeadline
}

// Merge merges the other map into m.
//
// If a category appears in both maps, the deadline that is furthest into the
// future is preserved.
func (m Map) Merge(other Map) {
	for c, d := range other {
		if d.After(m[c]) {
			m[c] = d
		}
	}
}

// FromResponse returns a rate limit map from an HTTP response.
func FromResponse(r *http.Response) Map {
	return fromResponse(r, time.Now())
}

func fromResponse(r *http.Response, now time.Time) Map {
	s := r.Header.Get("X-Sentry-Rate-Limits")
	if s != "" {
		return parseXSentryRateLimits(s, now)
	}
	if r.StatusCode == http.StatusTooManyRequests {
		s := r.Header.Get("Retry-After")
		deadline, _ := parseRetryAfter(s, now)
		return Map{CategoryAll: deadline}
	}
	return Map{}
}