MCPcopy Index your code
hub / github.com/supabase/auth / performRateLimitingWithHeader

Method performRateLimitingWithHeader

internal/api/middleware.go:72–121  ·  view source on GitHub ↗
(lmt *limiter.Limiter, req *http.Request)

Source from the content-addressed store, hash-verified

70var emailRateLimitCounter = observability.ObtainMetricCounter("gotrue_email_rate_limit_counter", "Number of times an email rate limit has been triggered")
71
72func (a *API) performRateLimitingWithHeader(lmt *limiter.Limiter, req *http.Request) error {
73 limitHeader := a.config.RateLimitHeader
74
75 // If no rate limit header was set, ignore rate limiting
76 if limitHeader == "" {
77 return nil
78 }
79
80 valuesStr := req.Header.Get(limitHeader)
81
82 // If a rate limit header was set, but has no value, ignore rate limiting but warn with an error
83 if valuesStr == "" {
84 log := observability.GetLogEntry(req).Entry
85 log.WithField("header", limitHeader).Warn("request does not have a value for the rate limiting header, rate limiting is not applied")
86
87 return nil
88 }
89
90 // According to RFC 7230 section 3.2.2, multiple headers with the same name are equivalent
91 // to a single header with that name where each value is separated by a comma and whitespace.
92 //
93 // Note that there is some ambiguity in RFC 7230 where section 3.2.4 states that
94 // header field values (which can contain commas) are processed independently of the header
95 // field name, and thus it is not always clear if a comma is a list delimiter or simply par
96 // of a single value.
97 //
98 // Given that this function is primarily for use with headers like X-Forwarded-For which
99 // vendors generally combine into comma-separated lists, we opt for the simpler approach
100 // here and split the header value by commas before taking the first value.
101 values := strings.SplitN(valuesStr, ",", 2)
102
103 // We will always get at least one value back, so this operation is safe
104 key := strings.TrimSpace(values[0])
105
106 // If the rate limit header has at least one value, but the first value is all whitespace, return a warning.
107 // This will happen if the header is something like "X-Foo-Bar: ,baz".
108 if key == "" {
109 log := observability.GetLogEntry(req).Entry
110 log.WithField("header", limitHeader).Warn("first rate limit header value is empty, rate limiting is not applied")
111
112 return nil
113 }
114
115 // Otherwise, apply rate limiting based on the first rate limit header value
116 if err := tollbooth.LimitByKeys(lmt, []string{key}); err != nil {
117 return apierrors.NewTooManyRequestsError(apierrors.ErrorCodeOverRequestRateLimit, "Request rate limit reached")
118 }
119
120 return nil
121}
122
123func (a *API) performRateLimiting(lmt *limiter.Limiter, req *http.Request) error {
124 if sbffAddr, ok := sbff.GetIPAddress(req); ok {

Callers 1

performRateLimitingMethod · 0.95

Calls 3

GetLogEntryFunction · 0.92
NewTooManyRequestsErrorFunction · 0.92
GetMethod · 0.45

Tested by

no test coverage detected