Full Mattermost server source with integrated Community Enterprise features. Includes vendor directory for offline/air-gapped builds. Structure: - enterprise-impl/: Enterprise feature implementations - enterprise-community/: Init files that register implementations - enterprise/: Bridge imports (community_imports.go) - vendor/: All dependencies for offline builds Build (online): go build ./cmd/mattermost Build (offline/air-gapped): go build -mod=vendor ./cmd/mattermost 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
41 lines
1.1 KiB
Go
41 lines
1.1 KiB
Go
package ratelimit
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
const defaultRetryAfter = 1 * time.Minute
|
|
|
|
var errInvalidRetryAfter = errors.New("invalid input")
|
|
|
|
// parseRetryAfter parses a string s as in the standard Retry-After HTTP header
|
|
// and returns a deadline until when requests are rate limited and therefore new
|
|
// requests should not be sent. The input may be either a date or a non-negative
|
|
// integer number of seconds.
|
|
//
|
|
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
|
|
//
|
|
// parseRetryAfter always returns a usable deadline, even in case of an error.
|
|
//
|
|
// This is the original rate limiting mechanism used by Sentry, superseeded by
|
|
// the X-Sentry-Rate-Limits response header.
|
|
func parseRetryAfter(s string, now time.Time) (Deadline, error) {
|
|
if s == "" {
|
|
goto invalid
|
|
}
|
|
if n, err := strconv.Atoi(s); err == nil {
|
|
if n < 0 {
|
|
goto invalid
|
|
}
|
|
d := time.Duration(n) * time.Second
|
|
return Deadline(now.Add(d)), nil
|
|
}
|
|
if date, err := time.Parse(time.RFC1123, s); err == nil {
|
|
return Deadline(date), nil
|
|
}
|
|
invalid:
|
|
return Deadline(now.Add(defaultRetryAfter)), errInvalidRetryAfter
|
|
}
|