PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.20
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.20
1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 All 164 releases
woocommerce-pos / vendor_prefixed / sentry / sentry / src / Transport / RateLimiter.php

RateLimiter.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.20, at vendor_prefixed/sentry/sentry/src/Transport/RateLimiter.php

118 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace WCPOS\Vendor\Sentry\Transport;
5
6 use WCPOS\Vendor\Psr\Log\LoggerInterface;
7 use WCPOS\Vendor\Psr\Log\NullLogger;
8 use WCPOS\Vendor\Sentry\EventType;
9 use WCPOS\Vendor\Sentry\HttpClient\Response;
10 final class RateLimiter
11 {
12 /**
13 * @var string
14 */
15 public const DATA_CATEGORY_PROFILE = 'profile';
16 /**
17 * @var string
18 */
19 private const DATA_CATEGORY_ERROR = 'error';
20 /**
21 * @var string
22 */
23 private const DATA_CATEGORY_LOG_ITEM = 'log_item';
24 /**
25 * @var string
26 */
27 private const DATA_CATEGORY_CHECK_IN = 'monitor';
28 /**
29 * The name of the header to look at to know the rate limits for the events
30 * categories supported by the server.
31 */
32 private const RATE_LIMITS_HEADER = 'X-Sentry-Rate-Limits';
33 /**
34 * The name of the header to look at to know after how many seconds the HTTP
35 * request should be retried.
36 */
37 private const RETRY_AFTER_HEADER = 'Retry-After';
38 /**
39 * The number of seconds after which an HTTP request can be retried.
40 */
41 private const DEFAULT_RETRY_AFTER_SECONDS = 60;
42 /**
43 * @var array<string, int> The map of time instants for each event category after
44 * which an HTTP request can be retried
45 */
46 private $rateLimits = [];
47 /**
48 * @var LoggerInterface A PSR-3 logger
49 */
50 private $logger;
51 public function __construct(?LoggerInterface $logger = null)
52 {
53 $this->logger = $logger ?? new NullLogger();
54 }
55 public function handleResponse(Response $response) : bool
56 {
57 $now = \time();
58 if ($response->hasHeader(self::RATE_LIMITS_HEADER)) {
59 foreach (\explode(',', $response->getHeaderLine(self::RATE_LIMITS_HEADER)) as $limit) {
60 /**
61 * $parameters[0] - retry_after
62 * $parameters[1] - categories
63 * $parameters[2] - scope (not used)
64 * $parameters[3] - reason_code (not used)
65 * $parameters[4] - namespaces (only returned if categories contains "metric_bucket").
66 */
67 $parameters = \explode(':', $limit, 5);
68 $retryAfter = $now + (\ctype_digit($parameters[0]) ? (int) $parameters[0] : self::DEFAULT_RETRY_AFTER_SECONDS);
69 foreach (\explode(';', $parameters[1]) as $category) {
70 $this->rateLimits[$category ?: 'all'] = $retryAfter;
71 $this->logger->warning(\sprintf('Rate limited exceeded for category "%s", backing off until "%s".', $category, \gmdate(\DATE_ATOM, $retryAfter)));
72 }
73 }
74 return $this->rateLimits !== [];
75 }
76 if ($response->hasHeader(self::RETRY_AFTER_HEADER)) {
77 $retryAfter = $now + $this->parseRetryAfterHeader($now, $response->getHeaderLine(self::RETRY_AFTER_HEADER));
78 $this->rateLimits['all'] = $retryAfter;
79 $this->logger->warning(\sprintf('Rate limited exceeded for all categories, backing off until "%s".', \gmdate(\DATE_ATOM, $retryAfter)));
80 return \true;
81 }
82 return \false;
83 }
84 /**
85 * @param string|EventType $eventType
86 */
87 public function isRateLimited($eventType) : bool
88 {
89 return $this->getDisabledUntil($eventType) > \time();
90 }
91 /**
92 * @param string|EventType $eventType
93 */
94 public function getDisabledUntil($eventType) : int
95 {
96 $eventType = $eventType instanceof EventType ? (string) $eventType : $eventType;
97 if ($eventType === 'event') {
98 $eventType = self::DATA_CATEGORY_ERROR;
99 } elseif ($eventType === 'log') {
100 $eventType = self::DATA_CATEGORY_LOG_ITEM;
101 } elseif ($eventType === 'check_in') {
102 $eventType = self::DATA_CATEGORY_CHECK_IN;
103 }
104 return \max($this->rateLimits['all'] ?? 0, $this->rateLimits[$eventType] ?? 0);
105 }
106 private function parseRetryAfterHeader(int $currentTime, string $header) : int
107 {
108 if (\preg_match('/^\\d+$/', $header) === 1) {
109 return (int) $header;
110 }
111 $headerDate = \DateTimeImmutable::createFromFormat(\DateTimeImmutable::RFC1123, $header);
112 if ($headerDate !== \false && $headerDate->getTimestamp() >= $currentTime) {
113 return $headerDate->getTimestamp() - $currentTime;
114 }
115 return self::DEFAULT_RETRY_AFTER_SECONDS;
116 }
117 }
118