@@ -10,32 +10,32 @@ |
||
10 | 10 | */ |
11 | 11 | class RejectionException extends \RuntimeException |
12 | 12 | { |
13 | - /** @var mixed Rejection reason. */ |
|
14 | - private $reason; |
|
15 | - /** |
|
16 | - * @param mixed $reason Rejection reason. |
|
17 | - * @param string|null $description Optional description. |
|
18 | - */ |
|
19 | - public function __construct($reason, ?string $description = null) |
|
20 | - { |
|
21 | - $this->reason = $reason; |
|
22 | - $message = 'The promise was rejected'; |
|
23 | - if ($description) { |
|
24 | - $message .= ' with reason: ' . $description; |
|
25 | - } elseif (\is_string($reason) || \is_object($reason) && \method_exists($reason, '__toString')) { |
|
26 | - $message .= ' with reason: ' . $this->reason; |
|
27 | - } elseif ($reason instanceof \JsonSerializable) { |
|
28 | - $message .= ' with reason: ' . \json_encode($this->reason, \JSON_PRETTY_PRINT); |
|
29 | - } |
|
30 | - parent::__construct($message); |
|
31 | - } |
|
32 | - /** |
|
33 | - * Returns the rejection reason. |
|
34 | - * |
|
35 | - * @return mixed |
|
36 | - */ |
|
37 | - public function getReason() |
|
38 | - { |
|
39 | - return $this->reason; |
|
40 | - } |
|
13 | + /** @var mixed Rejection reason. */ |
|
14 | + private $reason; |
|
15 | + /** |
|
16 | + * @param mixed $reason Rejection reason. |
|
17 | + * @param string|null $description Optional description. |
|
18 | + */ |
|
19 | + public function __construct($reason, ?string $description = null) |
|
20 | + { |
|
21 | + $this->reason = $reason; |
|
22 | + $message = 'The promise was rejected'; |
|
23 | + if ($description) { |
|
24 | + $message .= ' with reason: ' . $description; |
|
25 | + } elseif (\is_string($reason) || \is_object($reason) && \method_exists($reason, '__toString')) { |
|
26 | + $message .= ' with reason: ' . $this->reason; |
|
27 | + } elseif ($reason instanceof \JsonSerializable) { |
|
28 | + $message .= ' with reason: ' . \json_encode($this->reason, \JSON_PRETTY_PRINT); |
|
29 | + } |
|
30 | + parent::__construct($message); |
|
31 | + } |
|
32 | + /** |
|
33 | + * Returns the rejection reason. |
|
34 | + * |
|
35 | + * @return mixed |
|
36 | + */ |
|
37 | + public function getReason() |
|
38 | + { |
|
39 | + return $this->reason; |
|
40 | + } |
|
41 | 41 | } |
@@ -13,66 +13,66 @@ |
||
13 | 13 | */ |
14 | 14 | class RejectedPromise implements PromiseInterface |
15 | 15 | { |
16 | - private $reason; |
|
17 | - /** |
|
18 | - * @param mixed $reason |
|
19 | - */ |
|
20 | - public function __construct($reason) |
|
21 | - { |
|
22 | - if (\is_object($reason) && \method_exists($reason, 'then')) { |
|
23 | - throw new \InvalidArgumentException('You cannot create a RejectedPromise with a promise.'); |
|
24 | - } |
|
25 | - $this->reason = $reason; |
|
26 | - } |
|
27 | - public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
28 | - { |
|
29 | - // If there's no onRejected callback then just return self. |
|
30 | - if (!$onRejected) { |
|
31 | - return $this; |
|
32 | - } |
|
33 | - $queue = Utils::queue(); |
|
34 | - $reason = $this->reason; |
|
35 | - $p = new Promise([$queue, 'run']); |
|
36 | - $queue->add(static function () use($p, $reason, $onRejected) : void { |
|
37 | - if (Is::pending($p)) { |
|
38 | - try { |
|
39 | - // Return a resolved promise if onRejected does not throw. |
|
40 | - $p->resolve($onRejected($reason)); |
|
41 | - } catch (\Throwable $e) { |
|
42 | - // onRejected threw, so return a rejected promise. |
|
43 | - $p->reject($e); |
|
44 | - } |
|
45 | - } |
|
46 | - }); |
|
47 | - return $p; |
|
48 | - } |
|
49 | - public function otherwise(callable $onRejected) : PromiseInterface |
|
50 | - { |
|
51 | - return $this->then(null, $onRejected); |
|
52 | - } |
|
53 | - public function wait(bool $unwrap = \true) |
|
54 | - { |
|
55 | - if ($unwrap) { |
|
56 | - throw Create::exceptionFor($this->reason); |
|
57 | - } |
|
58 | - return null; |
|
59 | - } |
|
60 | - public function getState() : string |
|
61 | - { |
|
62 | - return self::REJECTED; |
|
63 | - } |
|
64 | - public function resolve($value) : void |
|
65 | - { |
|
66 | - throw new \LogicException('Cannot resolve a rejected promise'); |
|
67 | - } |
|
68 | - public function reject($reason) : void |
|
69 | - { |
|
70 | - if ($reason !== $this->reason) { |
|
71 | - throw new \LogicException('Cannot reject a rejected promise'); |
|
72 | - } |
|
73 | - } |
|
74 | - public function cancel() : void |
|
75 | - { |
|
76 | - // pass |
|
77 | - } |
|
16 | + private $reason; |
|
17 | + /** |
|
18 | + * @param mixed $reason |
|
19 | + */ |
|
20 | + public function __construct($reason) |
|
21 | + { |
|
22 | + if (\is_object($reason) && \method_exists($reason, 'then')) { |
|
23 | + throw new \InvalidArgumentException('You cannot create a RejectedPromise with a promise.'); |
|
24 | + } |
|
25 | + $this->reason = $reason; |
|
26 | + } |
|
27 | + public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
28 | + { |
|
29 | + // If there's no onRejected callback then just return self. |
|
30 | + if (!$onRejected) { |
|
31 | + return $this; |
|
32 | + } |
|
33 | + $queue = Utils::queue(); |
|
34 | + $reason = $this->reason; |
|
35 | + $p = new Promise([$queue, 'run']); |
|
36 | + $queue->add(static function () use($p, $reason, $onRejected) : void { |
|
37 | + if (Is::pending($p)) { |
|
38 | + try { |
|
39 | + // Return a resolved promise if onRejected does not throw. |
|
40 | + $p->resolve($onRejected($reason)); |
|
41 | + } catch (\Throwable $e) { |
|
42 | + // onRejected threw, so return a rejected promise. |
|
43 | + $p->reject($e); |
|
44 | + } |
|
45 | + } |
|
46 | + }); |
|
47 | + return $p; |
|
48 | + } |
|
49 | + public function otherwise(callable $onRejected) : PromiseInterface |
|
50 | + { |
|
51 | + return $this->then(null, $onRejected); |
|
52 | + } |
|
53 | + public function wait(bool $unwrap = \true) |
|
54 | + { |
|
55 | + if ($unwrap) { |
|
56 | + throw Create::exceptionFor($this->reason); |
|
57 | + } |
|
58 | + return null; |
|
59 | + } |
|
60 | + public function getState() : string |
|
61 | + { |
|
62 | + return self::REJECTED; |
|
63 | + } |
|
64 | + public function resolve($value) : void |
|
65 | + { |
|
66 | + throw new \LogicException('Cannot resolve a rejected promise'); |
|
67 | + } |
|
68 | + public function reject($reason) : void |
|
69 | + { |
|
70 | + if ($reason !== $this->reason) { |
|
71 | + throw new \LogicException('Cannot reject a rejected promise'); |
|
72 | + } |
|
73 | + } |
|
74 | + public function cancel() : void |
|
75 | + { |
|
76 | + // pass |
|
77 | + } |
|
78 | 78 | } |
@@ -13,61 +13,61 @@ |
||
13 | 13 | */ |
14 | 14 | class FulfilledPromise implements PromiseInterface |
15 | 15 | { |
16 | - private $value; |
|
17 | - /** |
|
18 | - * @param mixed $value |
|
19 | - */ |
|
20 | - public function __construct($value) |
|
21 | - { |
|
22 | - if (\is_object($value) && \method_exists($value, 'then')) { |
|
23 | - throw new \InvalidArgumentException('You cannot create a FulfilledPromise with a promise.'); |
|
24 | - } |
|
25 | - $this->value = $value; |
|
26 | - } |
|
27 | - public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
28 | - { |
|
29 | - // Return itself if there is no onFulfilled function. |
|
30 | - if (!$onFulfilled) { |
|
31 | - return $this; |
|
32 | - } |
|
33 | - $queue = Utils::queue(); |
|
34 | - $p = new Promise([$queue, 'run']); |
|
35 | - $value = $this->value; |
|
36 | - $queue->add(static function () use($p, $value, $onFulfilled) : void { |
|
37 | - if (Is::pending($p)) { |
|
38 | - try { |
|
39 | - $p->resolve($onFulfilled($value)); |
|
40 | - } catch (\Throwable $e) { |
|
41 | - $p->reject($e); |
|
42 | - } |
|
43 | - } |
|
44 | - }); |
|
45 | - return $p; |
|
46 | - } |
|
47 | - public function otherwise(callable $onRejected) : PromiseInterface |
|
48 | - { |
|
49 | - return $this->then(null, $onRejected); |
|
50 | - } |
|
51 | - public function wait(bool $unwrap = \true) |
|
52 | - { |
|
53 | - return $unwrap ? $this->value : null; |
|
54 | - } |
|
55 | - public function getState() : string |
|
56 | - { |
|
57 | - return self::FULFILLED; |
|
58 | - } |
|
59 | - public function resolve($value) : void |
|
60 | - { |
|
61 | - if ($value !== $this->value) { |
|
62 | - throw new \LogicException('Cannot resolve a fulfilled promise'); |
|
63 | - } |
|
64 | - } |
|
65 | - public function reject($reason) : void |
|
66 | - { |
|
67 | - throw new \LogicException('Cannot reject a fulfilled promise'); |
|
68 | - } |
|
69 | - public function cancel() : void |
|
70 | - { |
|
71 | - // pass |
|
72 | - } |
|
16 | + private $value; |
|
17 | + /** |
|
18 | + * @param mixed $value |
|
19 | + */ |
|
20 | + public function __construct($value) |
|
21 | + { |
|
22 | + if (\is_object($value) && \method_exists($value, 'then')) { |
|
23 | + throw new \InvalidArgumentException('You cannot create a FulfilledPromise with a promise.'); |
|
24 | + } |
|
25 | + $this->value = $value; |
|
26 | + } |
|
27 | + public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
28 | + { |
|
29 | + // Return itself if there is no onFulfilled function. |
|
30 | + if (!$onFulfilled) { |
|
31 | + return $this; |
|
32 | + } |
|
33 | + $queue = Utils::queue(); |
|
34 | + $p = new Promise([$queue, 'run']); |
|
35 | + $value = $this->value; |
|
36 | + $queue->add(static function () use($p, $value, $onFulfilled) : void { |
|
37 | + if (Is::pending($p)) { |
|
38 | + try { |
|
39 | + $p->resolve($onFulfilled($value)); |
|
40 | + } catch (\Throwable $e) { |
|
41 | + $p->reject($e); |
|
42 | + } |
|
43 | + } |
|
44 | + }); |
|
45 | + return $p; |
|
46 | + } |
|
47 | + public function otherwise(callable $onRejected) : PromiseInterface |
|
48 | + { |
|
49 | + return $this->then(null, $onRejected); |
|
50 | + } |
|
51 | + public function wait(bool $unwrap = \true) |
|
52 | + { |
|
53 | + return $unwrap ? $this->value : null; |
|
54 | + } |
|
55 | + public function getState() : string |
|
56 | + { |
|
57 | + return self::FULFILLED; |
|
58 | + } |
|
59 | + public function resolve($value) : void |
|
60 | + { |
|
61 | + if ($value !== $this->value) { |
|
62 | + throw new \LogicException('Cannot resolve a fulfilled promise'); |
|
63 | + } |
|
64 | + } |
|
65 | + public function reject($reason) : void |
|
66 | + { |
|
67 | + throw new \LogicException('Cannot reject a fulfilled promise'); |
|
68 | + } |
|
69 | + public function cancel() : void |
|
70 | + { |
|
71 | + // pass |
|
72 | + } |
|
73 | 73 | } |
@@ -5,52 +5,52 @@ |
||
5 | 5 | |
6 | 6 | final class Each |
7 | 7 | { |
8 | - /** |
|
9 | - * Given an iterator that yields promises or values, returns a promise that |
|
10 | - * is fulfilled with a null value when the iterator has been consumed or |
|
11 | - * the aggregate promise has been fulfilled or rejected. |
|
12 | - * |
|
13 | - * $onFulfilled is a function that accepts the fulfilled value, iterator |
|
14 | - * index, and the aggregate promise. The callback can invoke any necessary |
|
15 | - * side effects and choose to resolve or reject the aggregate if needed. |
|
16 | - * |
|
17 | - * $onRejected is a function that accepts the rejection reason, iterator |
|
18 | - * index, and the aggregate promise. The callback can invoke any necessary |
|
19 | - * side effects and choose to resolve or reject the aggregate if needed. |
|
20 | - * |
|
21 | - * @param mixed $iterable Iterator or array to iterate over. |
|
22 | - */ |
|
23 | - public static function of($iterable, ?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
24 | - { |
|
25 | - return (new EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected]))->promise(); |
|
26 | - } |
|
27 | - /** |
|
28 | - * Like of, but only allows a certain number of outstanding promises at any |
|
29 | - * given time. |
|
30 | - * |
|
31 | - * $concurrency may be an integer or a function that accepts the number of |
|
32 | - * pending promises and returns a numeric concurrency limit value to allow |
|
33 | - * for dynamic a concurrency size. |
|
34 | - * |
|
35 | - * @param mixed $iterable |
|
36 | - * @param int|callable $concurrency |
|
37 | - */ |
|
38 | - public static function ofLimit($iterable, $concurrency, ?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
39 | - { |
|
40 | - return (new EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected, 'concurrency' => $concurrency]))->promise(); |
|
41 | - } |
|
42 | - /** |
|
43 | - * Like limit, but ensures that no promise in the given $iterable argument |
|
44 | - * is rejected. If any promise is rejected, then the aggregate promise is |
|
45 | - * rejected with the encountered rejection. |
|
46 | - * |
|
47 | - * @param mixed $iterable |
|
48 | - * @param int|callable $concurrency |
|
49 | - */ |
|
50 | - public static function ofLimitAll($iterable, $concurrency, ?callable $onFulfilled = null) : PromiseInterface |
|
51 | - { |
|
52 | - return self::ofLimit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, PromiseInterface $aggregate) : void { |
|
53 | - $aggregate->reject($reason); |
|
54 | - }); |
|
55 | - } |
|
8 | + /** |
|
9 | + * Given an iterator that yields promises or values, returns a promise that |
|
10 | + * is fulfilled with a null value when the iterator has been consumed or |
|
11 | + * the aggregate promise has been fulfilled or rejected. |
|
12 | + * |
|
13 | + * $onFulfilled is a function that accepts the fulfilled value, iterator |
|
14 | + * index, and the aggregate promise. The callback can invoke any necessary |
|
15 | + * side effects and choose to resolve or reject the aggregate if needed. |
|
16 | + * |
|
17 | + * $onRejected is a function that accepts the rejection reason, iterator |
|
18 | + * index, and the aggregate promise. The callback can invoke any necessary |
|
19 | + * side effects and choose to resolve or reject the aggregate if needed. |
|
20 | + * |
|
21 | + * @param mixed $iterable Iterator or array to iterate over. |
|
22 | + */ |
|
23 | + public static function of($iterable, ?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
24 | + { |
|
25 | + return (new EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected]))->promise(); |
|
26 | + } |
|
27 | + /** |
|
28 | + * Like of, but only allows a certain number of outstanding promises at any |
|
29 | + * given time. |
|
30 | + * |
|
31 | + * $concurrency may be an integer or a function that accepts the number of |
|
32 | + * pending promises and returns a numeric concurrency limit value to allow |
|
33 | + * for dynamic a concurrency size. |
|
34 | + * |
|
35 | + * @param mixed $iterable |
|
36 | + * @param int|callable $concurrency |
|
37 | + */ |
|
38 | + public static function ofLimit($iterable, $concurrency, ?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface |
|
39 | + { |
|
40 | + return (new EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected, 'concurrency' => $concurrency]))->promise(); |
|
41 | + } |
|
42 | + /** |
|
43 | + * Like limit, but ensures that no promise in the given $iterable argument |
|
44 | + * is rejected. If any promise is rejected, then the aggregate promise is |
|
45 | + * rejected with the encountered rejection. |
|
46 | + * |
|
47 | + * @param mixed $iterable |
|
48 | + * @param int|callable $concurrency |
|
49 | + */ |
|
50 | + public static function ofLimitAll($iterable, $concurrency, ?callable $onFulfilled = null) : PromiseInterface |
|
51 | + { |
|
52 | + return self::ofLimit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, PromiseInterface $aggregate) : void { |
|
53 | + $aggregate->reject($reason); |
|
54 | + }); |
|
55 | + } |
|
56 | 56 | } |
@@ -1,6 +1,6 @@ discard block |
||
1 | 1 | <?php |
2 | 2 | |
3 | -declare (strict_types=1); |
|
3 | +declare(strict_types=1); |
|
4 | 4 | namespace OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise; |
5 | 5 | |
6 | 6 | final class Each |
@@ -49,7 +49,7 @@ discard block |
||
49 | 49 | */ |
50 | 50 | public static function ofLimitAll($iterable, $concurrency, ?callable $onFulfilled = null) : PromiseInterface |
51 | 51 | { |
52 | - return self::ofLimit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, PromiseInterface $aggregate) : void { |
|
52 | + return self::ofLimit($iterable, $concurrency, $onFulfilled, function($reason, $idx, PromiseInterface $aggregate) : void { |
|
53 | 53 | $aggregate->reject($reason); |
54 | 54 | }); |
55 | 55 | } |
@@ -9,236 +9,236 @@ |
||
9 | 9 | */ |
10 | 10 | final class RequestOptions |
11 | 11 | { |
12 | - /** |
|
13 | - * allow_redirects: (bool|array) Controls redirect behavior. Pass false |
|
14 | - * to disable redirects, pass true to enable redirects, pass an |
|
15 | - * associative to provide custom redirect settings. Defaults to "false". |
|
16 | - * This option only works if your handler has the RedirectMiddleware. When |
|
17 | - * passing an associative array, you can provide the following key value |
|
18 | - * pairs: |
|
19 | - * |
|
20 | - * - max: (int, default=5) maximum number of allowed redirects. |
|
21 | - * - strict: (bool, default=false) Set to true to use strict redirects |
|
22 | - * meaning redirect POST requests with POST requests vs. doing what most |
|
23 | - * browsers do which is redirect POST requests with GET requests |
|
24 | - * - referer: (bool, default=false) Set to true to enable the Referer |
|
25 | - * header. |
|
26 | - * - protocols: (array, default=['http', 'https']) Allowed redirect |
|
27 | - * protocols. |
|
28 | - * - on_redirect: (callable) PHP callable that is invoked when a redirect |
|
29 | - * is encountered. The callable is invoked with the request, the redirect |
|
30 | - * response that was received, and the effective URI. Any return value |
|
31 | - * from the on_redirect function is ignored. |
|
32 | - */ |
|
33 | - public const ALLOW_REDIRECTS = 'allow_redirects'; |
|
34 | - /** |
|
35 | - * auth: (array) Pass an array of HTTP authentication parameters to use |
|
36 | - * with the request. The array must contain the username in index [0], |
|
37 | - * the password in index [1], and you can optionally provide a built-in |
|
38 | - * authentication type in index [2]. Pass null to disable authentication |
|
39 | - * for a request. |
|
40 | - */ |
|
41 | - public const AUTH = 'auth'; |
|
42 | - /** |
|
43 | - * body: (resource|string|null|int|float|StreamInterface|callable|\Iterator) |
|
44 | - * Body to send in the request. |
|
45 | - */ |
|
46 | - public const BODY = 'body'; |
|
47 | - /** |
|
48 | - * cert: (string|array) Set to a string to specify the path to a file |
|
49 | - * containing a PEM formatted SSL client side certificate. If a password |
|
50 | - * is required, then set cert to an array containing the path to the PEM |
|
51 | - * file in the first array element followed by the certificate password |
|
52 | - * in the second array element. |
|
53 | - */ |
|
54 | - public const CERT = 'cert'; |
|
55 | - /** |
|
56 | - * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false) |
|
57 | - * Specifies whether or not cookies are used in a request or what cookie |
|
58 | - * jar to use or what cookies to send. This option only works if your |
|
59 | - * handler has the `cookie` middleware. Valid values are `false` and |
|
60 | - * an instance of {@see Cookie\CookieJarInterface}. |
|
61 | - */ |
|
62 | - public const COOKIES = 'cookies'; |
|
63 | - /** |
|
64 | - * connect_timeout: (float, default=0) Float describing the number of |
|
65 | - * seconds to wait while trying to connect to a server. Use 0 to wait |
|
66 | - * 300 seconds (the default behavior). |
|
67 | - */ |
|
68 | - public const CONNECT_TIMEOUT = 'connect_timeout'; |
|
69 | - /** |
|
70 | - * crypto_method: (int) A value describing the minimum TLS protocol |
|
71 | - * version to use. |
|
72 | - * |
|
73 | - * This setting must be set to one of the |
|
74 | - * ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is |
|
75 | - * required in order to use TLS 1.3, and cURL 7.34.0 or higher is required |
|
76 | - * in order to specify a crypto method, with cURL 7.52.0 or higher being |
|
77 | - * required to use TLS 1.3. |
|
78 | - */ |
|
79 | - public const CRYPTO_METHOD = 'crypto_method'; |
|
80 | - /** |
|
81 | - * debug: (bool|resource) Set to true or set to a PHP stream returned by |
|
82 | - * fopen() enable debug output with the HTTP handler used to send a |
|
83 | - * request. |
|
84 | - */ |
|
85 | - public const DEBUG = 'debug'; |
|
86 | - /** |
|
87 | - * decode_content: (bool, default=true) Specify whether or not |
|
88 | - * Content-Encoding responses (gzip, deflate, etc.) are automatically |
|
89 | - * decoded. |
|
90 | - */ |
|
91 | - public const DECODE_CONTENT = 'decode_content'; |
|
92 | - /** |
|
93 | - * delay: (int) The amount of time to delay before sending in milliseconds. |
|
94 | - */ |
|
95 | - public const DELAY = 'delay'; |
|
96 | - /** |
|
97 | - * expect: (bool|integer) Controls the behavior of the |
|
98 | - * "Expect: 100-Continue" header. |
|
99 | - * |
|
100 | - * Set to `true` to enable the "Expect: 100-Continue" header for all |
|
101 | - * requests that sends a body. Set to `false` to disable the |
|
102 | - * "Expect: 100-Continue" header for all requests. Set to a number so that |
|
103 | - * the size of the payload must be greater than the number in order to send |
|
104 | - * the Expect header. Setting to a number will send the Expect header for |
|
105 | - * all requests in which the size of the payload cannot be determined or |
|
106 | - * where the body is not rewindable. |
|
107 | - * |
|
108 | - * By default, Guzzle will add the "Expect: 100-Continue" header when the |
|
109 | - * size of the body of a request is greater than 1 MB and a request is |
|
110 | - * using HTTP/1.1. |
|
111 | - */ |
|
112 | - public const EXPECT = 'expect'; |
|
113 | - /** |
|
114 | - * form_params: (array) Associative array of form field names to values |
|
115 | - * where each value is a string or array of strings. Sets the Content-Type |
|
116 | - * header to application/x-www-form-urlencoded when no Content-Type header |
|
117 | - * is already present. |
|
118 | - */ |
|
119 | - public const FORM_PARAMS = 'form_params'; |
|
120 | - /** |
|
121 | - * headers: (array) Associative array of HTTP headers. Each value MUST be |
|
122 | - * a string or array of strings. |
|
123 | - */ |
|
124 | - public const HEADERS = 'headers'; |
|
125 | - /** |
|
126 | - * http_errors: (bool, default=true) Set to false to disable exceptions |
|
127 | - * when a non- successful HTTP response is received. By default, |
|
128 | - * exceptions will be thrown for 4xx and 5xx responses. This option only |
|
129 | - * works if your handler has the `httpErrors` middleware. |
|
130 | - */ |
|
131 | - public const HTTP_ERRORS = 'http_errors'; |
|
132 | - /** |
|
133 | - * idn: (bool|int, default=true) A combination of IDNA_* constants for |
|
134 | - * idn_to_ascii() PHP's function (see "options" parameter). Set to false to |
|
135 | - * disable IDN support completely, or to true to use the default |
|
136 | - * configuration (IDNA_DEFAULT constant). |
|
137 | - */ |
|
138 | - public const IDN_CONVERSION = 'idn_conversion'; |
|
139 | - /** |
|
140 | - * json: (mixed) Adds JSON data to a request. The provided value is JSON |
|
141 | - * encoded and a Content-Type header of application/json will be added to |
|
142 | - * the request if no Content-Type header is already present. |
|
143 | - */ |
|
144 | - public const JSON = 'json'; |
|
145 | - /** |
|
146 | - * multipart: (array) Array of associative arrays, each containing a |
|
147 | - * required "name" key mapping to the form field, name, a required |
|
148 | - * "contents" key mapping to a StreamInterface|resource|string, an |
|
149 | - * optional "headers" associative array of custom headers, and an |
|
150 | - * optional "filename" key mapping to a string to send as the filename in |
|
151 | - * the part. If no "filename" key is present, then no "filename" attribute |
|
152 | - * will be added to the part. |
|
153 | - */ |
|
154 | - public const MULTIPART = 'multipart'; |
|
155 | - /** |
|
156 | - * on_headers: (callable) A callable that is invoked when the HTTP headers |
|
157 | - * of the response have been received but the body has not yet begun to |
|
158 | - * download. |
|
159 | - */ |
|
160 | - public const ON_HEADERS = 'on_headers'; |
|
161 | - /** |
|
162 | - * on_stats: (callable) allows you to get access to transfer statistics of |
|
163 | - * a request and access the lower level transfer details of the handler |
|
164 | - * associated with your client. ``on_stats`` is a callable that is invoked |
|
165 | - * when a handler has finished sending a request. The callback is invoked |
|
166 | - * with transfer statistics about the request, the response received, or |
|
167 | - * the error encountered. Included in the data is the total amount of time |
|
168 | - * taken to send the request. |
|
169 | - */ |
|
170 | - public const ON_STATS = 'on_stats'; |
|
171 | - /** |
|
172 | - * progress: (callable) Defines a function to invoke when transfer |
|
173 | - * progress is made. The function accepts the following positional |
|
174 | - * arguments: the total number of bytes expected to be downloaded, the |
|
175 | - * number of bytes downloaded so far, the number of bytes expected to be |
|
176 | - * uploaded, the number of bytes uploaded so far. |
|
177 | - */ |
|
178 | - public const PROGRESS = 'progress'; |
|
179 | - /** |
|
180 | - * proxy: (string|array) Pass a string to specify an HTTP proxy, or an |
|
181 | - * array to specify different proxies for different protocols (where the |
|
182 | - * key is the protocol and the value is a proxy string). |
|
183 | - */ |
|
184 | - public const PROXY = 'proxy'; |
|
185 | - /** |
|
186 | - * query: (array|string) Associative array of query string values to add |
|
187 | - * to the request. This option uses PHP's http_build_query() to create |
|
188 | - * the string representation. Pass a string value if you need more |
|
189 | - * control than what this method provides |
|
190 | - */ |
|
191 | - public const QUERY = 'query'; |
|
192 | - /** |
|
193 | - * sink: (resource|string|StreamInterface) Where the data of the |
|
194 | - * response is written to. Defaults to a PHP temp stream. Providing a |
|
195 | - * string will write data to a file by the given name. |
|
196 | - */ |
|
197 | - public const SINK = 'sink'; |
|
198 | - /** |
|
199 | - * synchronous: (bool) Set to true to inform HTTP handlers that you intend |
|
200 | - * on waiting on the response. This can be useful for optimizations. Note |
|
201 | - * that a promise is still returned if you are using one of the async |
|
202 | - * client methods. |
|
203 | - */ |
|
204 | - public const SYNCHRONOUS = 'synchronous'; |
|
205 | - /** |
|
206 | - * ssl_key: (array|string) Specify the path to a file containing a private |
|
207 | - * SSL key in PEM format. If a password is required, then set to an array |
|
208 | - * containing the path to the SSL key in the first array element followed |
|
209 | - * by the password required for the certificate in the second element. |
|
210 | - */ |
|
211 | - public const SSL_KEY = 'ssl_key'; |
|
212 | - /** |
|
213 | - * stream: Set to true to attempt to stream a response rather than |
|
214 | - * download it all up-front. |
|
215 | - */ |
|
216 | - public const STREAM = 'stream'; |
|
217 | - /** |
|
218 | - * verify: (bool|string, default=true) Describes the SSL certificate |
|
219 | - * verification behavior of a request. Set to true to enable SSL |
|
220 | - * certificate verification using the system CA bundle when available |
|
221 | - * (the default). Set to false to disable certificate verification (this |
|
222 | - * is insecure!). Set to a string to provide the path to a CA bundle on |
|
223 | - * disk to enable verification using a custom certificate. |
|
224 | - */ |
|
225 | - public const VERIFY = 'verify'; |
|
226 | - /** |
|
227 | - * timeout: (float, default=0) Float describing the timeout of the |
|
228 | - * request in seconds. Use 0 to wait indefinitely (the default behavior). |
|
229 | - */ |
|
230 | - public const TIMEOUT = 'timeout'; |
|
231 | - /** |
|
232 | - * read_timeout: (float, default=default_socket_timeout ini setting) Float describing |
|
233 | - * the body read timeout, for stream requests. |
|
234 | - */ |
|
235 | - public const READ_TIMEOUT = 'read_timeout'; |
|
236 | - /** |
|
237 | - * version: (float) Specifies the HTTP protocol version to attempt to use. |
|
238 | - */ |
|
239 | - public const VERSION = 'version'; |
|
240 | - /** |
|
241 | - * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol |
|
242 | - */ |
|
243 | - public const FORCE_IP_RESOLVE = 'force_ip_resolve'; |
|
12 | + /** |
|
13 | + * allow_redirects: (bool|array) Controls redirect behavior. Pass false |
|
14 | + * to disable redirects, pass true to enable redirects, pass an |
|
15 | + * associative to provide custom redirect settings. Defaults to "false". |
|
16 | + * This option only works if your handler has the RedirectMiddleware. When |
|
17 | + * passing an associative array, you can provide the following key value |
|
18 | + * pairs: |
|
19 | + * |
|
20 | + * - max: (int, default=5) maximum number of allowed redirects. |
|
21 | + * - strict: (bool, default=false) Set to true to use strict redirects |
|
22 | + * meaning redirect POST requests with POST requests vs. doing what most |
|
23 | + * browsers do which is redirect POST requests with GET requests |
|
24 | + * - referer: (bool, default=false) Set to true to enable the Referer |
|
25 | + * header. |
|
26 | + * - protocols: (array, default=['http', 'https']) Allowed redirect |
|
27 | + * protocols. |
|
28 | + * - on_redirect: (callable) PHP callable that is invoked when a redirect |
|
29 | + * is encountered. The callable is invoked with the request, the redirect |
|
30 | + * response that was received, and the effective URI. Any return value |
|
31 | + * from the on_redirect function is ignored. |
|
32 | + */ |
|
33 | + public const ALLOW_REDIRECTS = 'allow_redirects'; |
|
34 | + /** |
|
35 | + * auth: (array) Pass an array of HTTP authentication parameters to use |
|
36 | + * with the request. The array must contain the username in index [0], |
|
37 | + * the password in index [1], and you can optionally provide a built-in |
|
38 | + * authentication type in index [2]. Pass null to disable authentication |
|
39 | + * for a request. |
|
40 | + */ |
|
41 | + public const AUTH = 'auth'; |
|
42 | + /** |
|
43 | + * body: (resource|string|null|int|float|StreamInterface|callable|\Iterator) |
|
44 | + * Body to send in the request. |
|
45 | + */ |
|
46 | + public const BODY = 'body'; |
|
47 | + /** |
|
48 | + * cert: (string|array) Set to a string to specify the path to a file |
|
49 | + * containing a PEM formatted SSL client side certificate. If a password |
|
50 | + * is required, then set cert to an array containing the path to the PEM |
|
51 | + * file in the first array element followed by the certificate password |
|
52 | + * in the second array element. |
|
53 | + */ |
|
54 | + public const CERT = 'cert'; |
|
55 | + /** |
|
56 | + * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false) |
|
57 | + * Specifies whether or not cookies are used in a request or what cookie |
|
58 | + * jar to use or what cookies to send. This option only works if your |
|
59 | + * handler has the `cookie` middleware. Valid values are `false` and |
|
60 | + * an instance of {@see Cookie\CookieJarInterface}. |
|
61 | + */ |
|
62 | + public const COOKIES = 'cookies'; |
|
63 | + /** |
|
64 | + * connect_timeout: (float, default=0) Float describing the number of |
|
65 | + * seconds to wait while trying to connect to a server. Use 0 to wait |
|
66 | + * 300 seconds (the default behavior). |
|
67 | + */ |
|
68 | + public const CONNECT_TIMEOUT = 'connect_timeout'; |
|
69 | + /** |
|
70 | + * crypto_method: (int) A value describing the minimum TLS protocol |
|
71 | + * version to use. |
|
72 | + * |
|
73 | + * This setting must be set to one of the |
|
74 | + * ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is |
|
75 | + * required in order to use TLS 1.3, and cURL 7.34.0 or higher is required |
|
76 | + * in order to specify a crypto method, with cURL 7.52.0 or higher being |
|
77 | + * required to use TLS 1.3. |
|
78 | + */ |
|
79 | + public const CRYPTO_METHOD = 'crypto_method'; |
|
80 | + /** |
|
81 | + * debug: (bool|resource) Set to true or set to a PHP stream returned by |
|
82 | + * fopen() enable debug output with the HTTP handler used to send a |
|
83 | + * request. |
|
84 | + */ |
|
85 | + public const DEBUG = 'debug'; |
|
86 | + /** |
|
87 | + * decode_content: (bool, default=true) Specify whether or not |
|
88 | + * Content-Encoding responses (gzip, deflate, etc.) are automatically |
|
89 | + * decoded. |
|
90 | + */ |
|
91 | + public const DECODE_CONTENT = 'decode_content'; |
|
92 | + /** |
|
93 | + * delay: (int) The amount of time to delay before sending in milliseconds. |
|
94 | + */ |
|
95 | + public const DELAY = 'delay'; |
|
96 | + /** |
|
97 | + * expect: (bool|integer) Controls the behavior of the |
|
98 | + * "Expect: 100-Continue" header. |
|
99 | + * |
|
100 | + * Set to `true` to enable the "Expect: 100-Continue" header for all |
|
101 | + * requests that sends a body. Set to `false` to disable the |
|
102 | + * "Expect: 100-Continue" header for all requests. Set to a number so that |
|
103 | + * the size of the payload must be greater than the number in order to send |
|
104 | + * the Expect header. Setting to a number will send the Expect header for |
|
105 | + * all requests in which the size of the payload cannot be determined or |
|
106 | + * where the body is not rewindable. |
|
107 | + * |
|
108 | + * By default, Guzzle will add the "Expect: 100-Continue" header when the |
|
109 | + * size of the body of a request is greater than 1 MB and a request is |
|
110 | + * using HTTP/1.1. |
|
111 | + */ |
|
112 | + public const EXPECT = 'expect'; |
|
113 | + /** |
|
114 | + * form_params: (array) Associative array of form field names to values |
|
115 | + * where each value is a string or array of strings. Sets the Content-Type |
|
116 | + * header to application/x-www-form-urlencoded when no Content-Type header |
|
117 | + * is already present. |
|
118 | + */ |
|
119 | + public const FORM_PARAMS = 'form_params'; |
|
120 | + /** |
|
121 | + * headers: (array) Associative array of HTTP headers. Each value MUST be |
|
122 | + * a string or array of strings. |
|
123 | + */ |
|
124 | + public const HEADERS = 'headers'; |
|
125 | + /** |
|
126 | + * http_errors: (bool, default=true) Set to false to disable exceptions |
|
127 | + * when a non- successful HTTP response is received. By default, |
|
128 | + * exceptions will be thrown for 4xx and 5xx responses. This option only |
|
129 | + * works if your handler has the `httpErrors` middleware. |
|
130 | + */ |
|
131 | + public const HTTP_ERRORS = 'http_errors'; |
|
132 | + /** |
|
133 | + * idn: (bool|int, default=true) A combination of IDNA_* constants for |
|
134 | + * idn_to_ascii() PHP's function (see "options" parameter). Set to false to |
|
135 | + * disable IDN support completely, or to true to use the default |
|
136 | + * configuration (IDNA_DEFAULT constant). |
|
137 | + */ |
|
138 | + public const IDN_CONVERSION = 'idn_conversion'; |
|
139 | + /** |
|
140 | + * json: (mixed) Adds JSON data to a request. The provided value is JSON |
|
141 | + * encoded and a Content-Type header of application/json will be added to |
|
142 | + * the request if no Content-Type header is already present. |
|
143 | + */ |
|
144 | + public const JSON = 'json'; |
|
145 | + /** |
|
146 | + * multipart: (array) Array of associative arrays, each containing a |
|
147 | + * required "name" key mapping to the form field, name, a required |
|
148 | + * "contents" key mapping to a StreamInterface|resource|string, an |
|
149 | + * optional "headers" associative array of custom headers, and an |
|
150 | + * optional "filename" key mapping to a string to send as the filename in |
|
151 | + * the part. If no "filename" key is present, then no "filename" attribute |
|
152 | + * will be added to the part. |
|
153 | + */ |
|
154 | + public const MULTIPART = 'multipart'; |
|
155 | + /** |
|
156 | + * on_headers: (callable) A callable that is invoked when the HTTP headers |
|
157 | + * of the response have been received but the body has not yet begun to |
|
158 | + * download. |
|
159 | + */ |
|
160 | + public const ON_HEADERS = 'on_headers'; |
|
161 | + /** |
|
162 | + * on_stats: (callable) allows you to get access to transfer statistics of |
|
163 | + * a request and access the lower level transfer details of the handler |
|
164 | + * associated with your client. ``on_stats`` is a callable that is invoked |
|
165 | + * when a handler has finished sending a request. The callback is invoked |
|
166 | + * with transfer statistics about the request, the response received, or |
|
167 | + * the error encountered. Included in the data is the total amount of time |
|
168 | + * taken to send the request. |
|
169 | + */ |
|
170 | + public const ON_STATS = 'on_stats'; |
|
171 | + /** |
|
172 | + * progress: (callable) Defines a function to invoke when transfer |
|
173 | + * progress is made. The function accepts the following positional |
|
174 | + * arguments: the total number of bytes expected to be downloaded, the |
|
175 | + * number of bytes downloaded so far, the number of bytes expected to be |
|
176 | + * uploaded, the number of bytes uploaded so far. |
|
177 | + */ |
|
178 | + public const PROGRESS = 'progress'; |
|
179 | + /** |
|
180 | + * proxy: (string|array) Pass a string to specify an HTTP proxy, or an |
|
181 | + * array to specify different proxies for different protocols (where the |
|
182 | + * key is the protocol and the value is a proxy string). |
|
183 | + */ |
|
184 | + public const PROXY = 'proxy'; |
|
185 | + /** |
|
186 | + * query: (array|string) Associative array of query string values to add |
|
187 | + * to the request. This option uses PHP's http_build_query() to create |
|
188 | + * the string representation. Pass a string value if you need more |
|
189 | + * control than what this method provides |
|
190 | + */ |
|
191 | + public const QUERY = 'query'; |
|
192 | + /** |
|
193 | + * sink: (resource|string|StreamInterface) Where the data of the |
|
194 | + * response is written to. Defaults to a PHP temp stream. Providing a |
|
195 | + * string will write data to a file by the given name. |
|
196 | + */ |
|
197 | + public const SINK = 'sink'; |
|
198 | + /** |
|
199 | + * synchronous: (bool) Set to true to inform HTTP handlers that you intend |
|
200 | + * on waiting on the response. This can be useful for optimizations. Note |
|
201 | + * that a promise is still returned if you are using one of the async |
|
202 | + * client methods. |
|
203 | + */ |
|
204 | + public const SYNCHRONOUS = 'synchronous'; |
|
205 | + /** |
|
206 | + * ssl_key: (array|string) Specify the path to a file containing a private |
|
207 | + * SSL key in PEM format. If a password is required, then set to an array |
|
208 | + * containing the path to the SSL key in the first array element followed |
|
209 | + * by the password required for the certificate in the second element. |
|
210 | + */ |
|
211 | + public const SSL_KEY = 'ssl_key'; |
|
212 | + /** |
|
213 | + * stream: Set to true to attempt to stream a response rather than |
|
214 | + * download it all up-front. |
|
215 | + */ |
|
216 | + public const STREAM = 'stream'; |
|
217 | + /** |
|
218 | + * verify: (bool|string, default=true) Describes the SSL certificate |
|
219 | + * verification behavior of a request. Set to true to enable SSL |
|
220 | + * certificate verification using the system CA bundle when available |
|
221 | + * (the default). Set to false to disable certificate verification (this |
|
222 | + * is insecure!). Set to a string to provide the path to a CA bundle on |
|
223 | + * disk to enable verification using a custom certificate. |
|
224 | + */ |
|
225 | + public const VERIFY = 'verify'; |
|
226 | + /** |
|
227 | + * timeout: (float, default=0) Float describing the timeout of the |
|
228 | + * request in seconds. Use 0 to wait indefinitely (the default behavior). |
|
229 | + */ |
|
230 | + public const TIMEOUT = 'timeout'; |
|
231 | + /** |
|
232 | + * read_timeout: (float, default=default_socket_timeout ini setting) Float describing |
|
233 | + * the body read timeout, for stream requests. |
|
234 | + */ |
|
235 | + public const READ_TIMEOUT = 'read_timeout'; |
|
236 | + /** |
|
237 | + * version: (float) Specifies the HTTP protocol version to attempt to use. |
|
238 | + */ |
|
239 | + public const VERSION = 'version'; |
|
240 | + /** |
|
241 | + * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol |
|
242 | + */ |
|
243 | + public const FORCE_IP_RESOLVE = 'force_ip_resolve'; |
|
244 | 244 | } |
@@ -5,19 +5,19 @@ |
||
5 | 5 | use OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\MessageInterface; |
6 | 6 | final class BodySummarizer implements BodySummarizerInterface |
7 | 7 | { |
8 | - /** |
|
9 | - * @var int|null |
|
10 | - */ |
|
11 | - private $truncateAt; |
|
12 | - public function __construct(?int $truncateAt = null) |
|
13 | - { |
|
14 | - $this->truncateAt = $truncateAt; |
|
15 | - } |
|
16 | - /** |
|
17 | - * Returns a summarized message body. |
|
18 | - */ |
|
19 | - public function summarize(MessageInterface $message) : ?string |
|
20 | - { |
|
21 | - return $this->truncateAt === null ? Psr7\Message::bodySummary($message) : Psr7\Message::bodySummary($message, $this->truncateAt); |
|
22 | - } |
|
8 | + /** |
|
9 | + * @var int|null |
|
10 | + */ |
|
11 | + private $truncateAt; |
|
12 | + public function __construct(?int $truncateAt = null) |
|
13 | + { |
|
14 | + $this->truncateAt = $truncateAt; |
|
15 | + } |
|
16 | + /** |
|
17 | + * Returns a summarized message body. |
|
18 | + */ |
|
19 | + public function summarize(MessageInterface $message) : ?string |
|
20 | + { |
|
21 | + return $this->truncateAt === null ? Psr7\Message::bodySummary($message) : Psr7\Message::bodySummary($message, $this->truncateAt); |
|
22 | + } |
|
23 | 23 | } |
@@ -49,384 +49,384 @@ |
||
49 | 49 | use function strtolower; |
50 | 50 | final class Transport implements ClientInterface, HttpAsyncClient |
51 | 51 | { |
52 | - const VERSION = "8.10.0"; |
|
53 | - private ClientInterface $client; |
|
54 | - private LoggerInterface $logger; |
|
55 | - private NodePoolInterface $nodePool; |
|
56 | - private array $headers = []; |
|
57 | - private string $user; |
|
58 | - private string $password; |
|
59 | - private RequestInterface $lastRequest; |
|
60 | - private ResponseInterface $lastResponse; |
|
61 | - private string $OSVersion; |
|
62 | - private int $retries = 0; |
|
63 | - private HttpAsyncClient $asyncClient; |
|
64 | - private OnSuccessInterface $onAsyncSuccess; |
|
65 | - private OnFailureInterface $onAsyncFailure; |
|
66 | - private TracerInterface $otelTracer; |
|
67 | - public function __construct(ClientInterface $client, NodePoolInterface $nodePool, LoggerInterface $logger) |
|
68 | - { |
|
69 | - $this->client = $client; |
|
70 | - $this->nodePool = $nodePool; |
|
71 | - $this->logger = $logger; |
|
72 | - } |
|
73 | - public function getClient() : ClientInterface |
|
74 | - { |
|
75 | - return $this->client; |
|
76 | - } |
|
77 | - public function getNodePool() : NodePoolInterface |
|
78 | - { |
|
79 | - return $this->nodePool; |
|
80 | - } |
|
81 | - public function getLogger() : LoggerInterface |
|
82 | - { |
|
83 | - return $this->logger; |
|
84 | - } |
|
85 | - public function getOTelTracer() : TracerInterface |
|
86 | - { |
|
87 | - if (empty($this->otelTracer)) { |
|
88 | - $this->otelTracer = OpenTelemetry::getTracer(Globals::tracerProvider()); |
|
89 | - } |
|
90 | - return $this->otelTracer; |
|
91 | - } |
|
92 | - public function setOTelTracer(TracerInterface $tracer) : self |
|
93 | - { |
|
94 | - $this->otelTracer = $tracer; |
|
95 | - return $this; |
|
96 | - } |
|
97 | - public function setHeader(string $name, string $value) : self |
|
98 | - { |
|
99 | - $this->headers[$name] = $value; |
|
100 | - return $this; |
|
101 | - } |
|
102 | - /** |
|
103 | - * @throws InvalidArgumentException |
|
104 | - */ |
|
105 | - public function setRetries(int $num) : self |
|
106 | - { |
|
107 | - if ($num < 0) { |
|
108 | - throw new InvalidArgumentException('The retries number must be a positive integer'); |
|
109 | - } |
|
110 | - $this->retries = $num; |
|
111 | - return $this; |
|
112 | - } |
|
113 | - public function getRetries() : int |
|
114 | - { |
|
115 | - return $this->retries; |
|
116 | - } |
|
117 | - public function getHeaders() : array |
|
118 | - { |
|
119 | - return $this->headers; |
|
120 | - } |
|
121 | - public function setUserInfo(string $user, string $password = '') : self |
|
122 | - { |
|
123 | - $this->user = $user; |
|
124 | - $this->password = $password; |
|
125 | - return $this; |
|
126 | - } |
|
127 | - public function setUserAgent(string $name, string $version) : self |
|
128 | - { |
|
129 | - $this->headers['User-Agent'] = sprintf("%s/%s (%s %s; PHP %s)", $name, $version, \PHP_OS, $this->getOSVersion(), phpversion()); |
|
130 | - return $this; |
|
131 | - } |
|
132 | - /** |
|
133 | - * Set the x-elastic-client-meta header |
|
134 | - * |
|
135 | - * The header format is specified by the following regex: |
|
136 | - * ^[a-z]{1,}=[a-z0-9\.\-]{1,}(?:,[a-z]{1,}=[a-z0-9\.\-]+)*$ |
|
137 | - */ |
|
138 | - public function setElasticMetaHeader(string $clientName, string $clientVersion, bool $async = \false) : self |
|
139 | - { |
|
140 | - $phpSemVersion = sprintf("%d.%d.%d", \PHP_MAJOR_VERSION, \PHP_MINOR_VERSION, \PHP_RELEASE_VERSION); |
|
141 | - $meta = sprintf("%s=%s,php=%s,t=%s,a=%d", $clientName, $this->purgePreReleaseTag($clientVersion), $phpSemVersion, $this->purgePreReleaseTag(self::VERSION), $async ? 1 : 0); |
|
142 | - $lib = $this->getClientLibraryInfo(); |
|
143 | - if (!empty($lib)) { |
|
144 | - $meta .= sprintf(",%s=%s", $lib[0], $lib[1]); |
|
145 | - } |
|
146 | - $this->headers['x-elastic-client-meta'] = $meta; |
|
147 | - return $this; |
|
148 | - } |
|
149 | - /** |
|
150 | - * Remove pre-release suffix with a single 'p' letter |
|
151 | - */ |
|
152 | - private function purgePreReleaseTag(string $version) : string |
|
153 | - { |
|
154 | - return str_replace(['alpha', 'beta', 'snapshot', 'rc', 'pre'], 'p', strtolower($version)); |
|
155 | - } |
|
156 | - public function getLastRequest() : RequestInterface |
|
157 | - { |
|
158 | - return $this->lastRequest; |
|
159 | - } |
|
160 | - public function getLastResponse() : ResponseInterface |
|
161 | - { |
|
162 | - return $this->lastResponse; |
|
163 | - } |
|
164 | - /** |
|
165 | - * Setup the headers, if not already present |
|
166 | - */ |
|
167 | - private function setupHeaders(RequestInterface $request) : RequestInterface |
|
168 | - { |
|
169 | - foreach ($this->headers as $name => $value) { |
|
170 | - if (!$request->hasHeader($name)) { |
|
171 | - $request = $request->withHeader($name, $value); |
|
172 | - } |
|
173 | - } |
|
174 | - return $request; |
|
175 | - } |
|
176 | - /** |
|
177 | - * Setup the user info, if not already present |
|
178 | - */ |
|
179 | - private function setupUserInfo(RequestInterface $request) : RequestInterface |
|
180 | - { |
|
181 | - $uri = $request->getUri(); |
|
182 | - if (empty($uri->getUserInfo())) { |
|
183 | - if (isset($this->user)) { |
|
184 | - $request = $request->withUri($uri->withUserInfo($this->user, $this->password)); |
|
185 | - } |
|
186 | - } |
|
187 | - return $request; |
|
188 | - } |
|
189 | - /** |
|
190 | - * Setup the connection Uri |
|
191 | - */ |
|
192 | - private function setupConnectionUri(Node $node, RequestInterface $request) : RequestInterface |
|
193 | - { |
|
194 | - $uri = $node->getUri(); |
|
195 | - $path = $request->getUri()->getPath(); |
|
196 | - $nodePath = $uri->getPath(); |
|
197 | - // If the node has a path we need to use it as prefix for the existing path |
|
198 | - // @see https://github.com/elastic/elastic-transport-php/pull/20 |
|
199 | - if (!empty($nodePath)) { |
|
200 | - $path = sprintf("%s/%s", \rtrim($nodePath, '/'), \ltrim($path, '/')); |
|
201 | - } |
|
202 | - // If the user information is not in the request, we check if it is present in the node uri |
|
203 | - // @see https://github.com/elastic/elastic-transport-php/issues/18 |
|
204 | - if (empty($request->getUri()->getUserInfo()) && !empty($uri->getUserInfo())) { |
|
205 | - $userInfo = \explode(':', $uri->getUserInfo()); |
|
206 | - $request = $request->withUri($request->getUri()->withUserInfo($userInfo[0], $userInfo[1] ?? null)); |
|
207 | - } |
|
208 | - return $request->withUri($request->getUri()->withHost($uri->getHost())->withPort($uri->getPort())->withScheme($uri->getScheme())->withPath($path)); |
|
209 | - } |
|
210 | - private function decorateRequest(RequestInterface $request) : RequestInterface |
|
211 | - { |
|
212 | - $request = $this->setupHeaders($request); |
|
213 | - return $this->setupUserInfo($request); |
|
214 | - } |
|
215 | - private function logHeaders(MessageInterface $message) : void |
|
216 | - { |
|
217 | - $this->logger->debug(sprintf("Headers: %s\nBody: %s", json_encode($message->getHeaders()), (string) $message->getBody())); |
|
218 | - } |
|
219 | - private function logRequest(string $title, RequestInterface $request) : void |
|
220 | - { |
|
221 | - $this->logger->info(sprintf("%s: %s %s", $title, $request->getMethod(), (string) $request->getUri()), ['request' => $request]); |
|
222 | - $this->logHeaders($request); |
|
223 | - } |
|
224 | - private function logResponse(string $title, ResponseInterface $response, int $retry) : void |
|
225 | - { |
|
226 | - $this->logger->info(sprintf("%s (retry %d): %d", $title, $retry, $response->getStatusCode()), ['response' => $response, 'retry' => $retry]); |
|
227 | - $this->logHeaders($response); |
|
228 | - } |
|
229 | - /** |
|
230 | - * @throws NoNodeAvailableException |
|
231 | - * @throws ClientExceptionInterface |
|
232 | - */ |
|
233 | - public function sendRequest(RequestInterface $request) : ResponseInterface |
|
234 | - { |
|
235 | - if (empty($request->getUri()->getHost())) { |
|
236 | - $node = $this->nodePool->nextNode(); |
|
237 | - $request = $this->setupConnectionUri($node, $request); |
|
238 | - } |
|
239 | - $request = $this->decorateRequest($request); |
|
240 | - $this->lastRequest = $request; |
|
241 | - $this->logRequest("Request", $request); |
|
242 | - // OpenTelemetry get tracer |
|
243 | - if (\getenv(OpenTelemetry::ENV_VARIABLE_ENABLED)) { |
|
244 | - $tracer = $this->getOTelTracer(); |
|
245 | - } |
|
246 | - $count = -1; |
|
247 | - while ($count < $this->getRetries()) { |
|
248 | - try { |
|
249 | - $count++; |
|
250 | - // OpenTelemetry span start |
|
251 | - if (!empty($tracer)) { |
|
252 | - if ($request instanceof ServerRequestInterface) { |
|
253 | - $opts = $request->getAttribute(OpenTelemetry::PSR7_OTEL_ATTRIBUTE_NAME, []); |
|
254 | - } |
|
255 | - $spanName = $opts['db.operation.name'] ?? $request->getUri()->getPath(); |
|
256 | - $span = $tracer->spanBuilder($spanName)->startSpan(); |
|
257 | - $span->setAttribute('http.request.method', $request->getMethod()); |
|
258 | - $span->setAttribute('url.full', $this->getFullUrl($request)); |
|
259 | - $span->setAttribute('server.address', $request->getUri()->getHost()); |
|
260 | - $span->setAttribute('server.port', $request->getUri()->getPort()); |
|
261 | - if (!empty($opts)) { |
|
262 | - $span->setAttributes($opts); |
|
263 | - } |
|
264 | - } |
|
265 | - $response = $this->client->sendRequest($request); |
|
266 | - $this->lastResponse = $response; |
|
267 | - $this->logResponse("Response", $response, $count); |
|
268 | - return $response; |
|
269 | - } catch (NetworkExceptionInterface $e) { |
|
270 | - $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
271 | - if (!empty($span)) { |
|
272 | - $span->setAttribute('error.type', $e->getMessage()); |
|
273 | - } |
|
274 | - if (isset($node)) { |
|
275 | - $node->markAlive(\false); |
|
276 | - $node = $this->nodePool->nextNode(); |
|
277 | - $request = $this->setupConnectionUri($node, $request); |
|
278 | - } |
|
279 | - } catch (ClientExceptionInterface $e) { |
|
280 | - $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
281 | - if (!empty($span)) { |
|
282 | - $span->setAttribute('error.type', $e->getMessage()); |
|
283 | - } |
|
284 | - throw $e; |
|
285 | - } finally { |
|
286 | - // OpenTelemetry span end |
|
287 | - if (!empty($span)) { |
|
288 | - $span->end(); |
|
289 | - } |
|
290 | - } |
|
291 | - } |
|
292 | - $exceededMsg = sprintf("Exceeded maximum number of retries (%d)", $this->getRetries()); |
|
293 | - $this->logger->error($exceededMsg); |
|
294 | - throw new NoNodeAvailableException($exceededMsg); |
|
295 | - } |
|
296 | - public function setAsyncClient(HttpAsyncClient $asyncClient) : self |
|
297 | - { |
|
298 | - $this->asyncClient = $asyncClient; |
|
299 | - return $this; |
|
300 | - } |
|
301 | - /** |
|
302 | - * @throws NoAsyncClientException |
|
303 | - */ |
|
304 | - public function getAsyncClient() : HttpAsyncClient |
|
305 | - { |
|
306 | - if (!empty($this->asyncClient)) { |
|
307 | - return $this->asyncClient; |
|
308 | - } |
|
309 | - if ($this->client instanceof HttpAsyncClient) { |
|
310 | - return $this->client; |
|
311 | - } |
|
312 | - try { |
|
313 | - $this->asyncClient = HttpAsyncClientDiscovery::find(); |
|
314 | - } catch (Exception $e) { |
|
315 | - throw new NoAsyncClientException(sprintf("I did not find any HTTP library with HttpAsyncClient interface. " . "Make sure to install a package providing \"php-http/async-client-implementation\". " . "You can also set a specific async library using %s::setAsyncClient()", self::class)); |
|
316 | - } |
|
317 | - return $this->asyncClient; |
|
318 | - } |
|
319 | - public function setAsyncOnSuccess(OnSuccessInterface $success) : self |
|
320 | - { |
|
321 | - $this->onAsyncSuccess = $success; |
|
322 | - return $this; |
|
323 | - } |
|
324 | - public function getAsyncOnSuccess() : OnSuccessInterface |
|
325 | - { |
|
326 | - if (empty($this->onAsyncSuccess)) { |
|
327 | - $this->onAsyncSuccess = new OnSuccessDefault(); |
|
328 | - } |
|
329 | - return $this->onAsyncSuccess; |
|
330 | - } |
|
331 | - public function setAsyncOnFailure(OnFailureInterface $failure) : self |
|
332 | - { |
|
333 | - $this->onAsyncFailure = $failure; |
|
334 | - return $this; |
|
335 | - } |
|
336 | - public function getAsyncOnFailure() : OnFailureInterface |
|
337 | - { |
|
338 | - if (empty($this->onAsyncFailure)) { |
|
339 | - $this->onAsyncFailure = new OnFailureDefault(); |
|
340 | - } |
|
341 | - return $this->onAsyncFailure; |
|
342 | - } |
|
343 | - /** |
|
344 | - * @throws Exception |
|
345 | - */ |
|
346 | - public function sendAsyncRequest(RequestInterface $request) : Promise |
|
347 | - { |
|
348 | - $client = $this->getAsyncClient(); |
|
349 | - $node = null; |
|
350 | - if (empty($request->getUri()->getHost())) { |
|
351 | - $node = $this->nodePool->nextNode(); |
|
352 | - $request = $this->setupConnectionUri($node, $request); |
|
353 | - } |
|
354 | - $request = $this->decorateRequest($request); |
|
355 | - $this->lastRequest = $request; |
|
356 | - $this->logRequest("Async Request", $request); |
|
357 | - $count = 0; |
|
358 | - $promise = $client->sendAsyncRequest($request); |
|
359 | - // onFulfilled callable |
|
360 | - $onFulfilled = function (ResponseInterface $response) use(&$count) { |
|
361 | - $this->lastResponse = $response; |
|
362 | - $this->logResponse("Async Response", $response, $count); |
|
363 | - return $this->getAsyncOnSuccess()->success($response, $count); |
|
364 | - }; |
|
365 | - // onRejected callable |
|
366 | - $onRejected = function (Exception $e) use($client, $request, &$count, $node) { |
|
367 | - $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
368 | - $this->getAsyncOnFailure()->failure($e, $request, $count, $node ?? null); |
|
369 | - if (isset($node)) { |
|
370 | - $node->markAlive(\false); |
|
371 | - $node = $this->nodePool->nextNode(); |
|
372 | - $request = $this->setupConnectionUri($node, $request); |
|
373 | - } |
|
374 | - $count++; |
|
375 | - return $client->sendAsyncRequest($request); |
|
376 | - }; |
|
377 | - // Add getRetries() callables using then() |
|
378 | - for ($i = 0; $i < $this->getRetries(); $i++) { |
|
379 | - $promise = $promise->then($onFulfilled, $onRejected); |
|
380 | - } |
|
381 | - // Add the last getRetries()+1 callable for managing the exceeded error |
|
382 | - $promise = $promise->then($onFulfilled, function (Exception $e) use(&$count) { |
|
383 | - $exceededMsg = sprintf("Exceeded maximum number of retries (%d)", $this->getRetries()); |
|
384 | - $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
385 | - $this->logger->error($exceededMsg); |
|
386 | - throw new NoNodeAvailableException(sprintf("%s: %s", $exceededMsg, $e->getMessage())); |
|
387 | - }); |
|
388 | - return $promise; |
|
389 | - } |
|
390 | - /** |
|
391 | - * Get the OS version using php_uname if available |
|
392 | - * otherwise it returns an empty string |
|
393 | - */ |
|
394 | - private function getOSVersion() : string |
|
395 | - { |
|
396 | - if (!isset($this->OSVersion)) { |
|
397 | - $disable_functions = (string) ini_get('disable_functions'); |
|
398 | - $this->OSVersion = strpos(strtolower($disable_functions), 'php_uname') !== \false ? '' : php_uname("r"); |
|
399 | - } |
|
400 | - return $this->OSVersion; |
|
401 | - } |
|
402 | - /** |
|
403 | - * Returns the name and the version of the Client HTTP library used |
|
404 | - * Here a list of supported libraries: |
|
405 | - * gu => guzzlehttp/guzzle |
|
406 | - * sy => symfony/http-client |
|
407 | - */ |
|
408 | - private function getClientLibraryInfo() : array |
|
409 | - { |
|
410 | - $clientClass = get_class($this->client); |
|
411 | - if (\false !== strpos($clientClass, 'OCA\\FullTextSearch_Elasticsearch\\Vendor\\GuzzleHttp\\Client')) { |
|
412 | - return ['gu', InstalledVersions::getPrettyVersion('guzzlehttp/guzzle')]; |
|
413 | - } |
|
414 | - if (\false !== strpos($clientClass, 'OCA\\FullTextSearch_Elasticsearch\\Vendor\\Symfony\\Component\\HttpClient')) { |
|
415 | - return ['sy', InstalledVersions::getPrettyVersion('symfony/http-client')]; |
|
416 | - } |
|
417 | - return []; |
|
418 | - } |
|
419 | - /** |
|
420 | - * Return the full URL in the format |
|
421 | - * scheme://host:port/path?query_string |
|
422 | - */ |
|
423 | - private function getFullUrl(RequestInterface $request) : string |
|
424 | - { |
|
425 | - $fullUrl = sprintf("%s://%s:%s%s", $request->getUri()->getScheme(), $request->getUri()->getHost(), $request->getUri()->getPort(), $request->getUri()->getPath()); |
|
426 | - $queryString = $request->getUri()->getQuery(); |
|
427 | - if (!empty($queryString)) { |
|
428 | - $fullUrl .= '?' . $queryString; |
|
429 | - } |
|
430 | - return $fullUrl; |
|
431 | - } |
|
52 | + const VERSION = "8.10.0"; |
|
53 | + private ClientInterface $client; |
|
54 | + private LoggerInterface $logger; |
|
55 | + private NodePoolInterface $nodePool; |
|
56 | + private array $headers = []; |
|
57 | + private string $user; |
|
58 | + private string $password; |
|
59 | + private RequestInterface $lastRequest; |
|
60 | + private ResponseInterface $lastResponse; |
|
61 | + private string $OSVersion; |
|
62 | + private int $retries = 0; |
|
63 | + private HttpAsyncClient $asyncClient; |
|
64 | + private OnSuccessInterface $onAsyncSuccess; |
|
65 | + private OnFailureInterface $onAsyncFailure; |
|
66 | + private TracerInterface $otelTracer; |
|
67 | + public function __construct(ClientInterface $client, NodePoolInterface $nodePool, LoggerInterface $logger) |
|
68 | + { |
|
69 | + $this->client = $client; |
|
70 | + $this->nodePool = $nodePool; |
|
71 | + $this->logger = $logger; |
|
72 | + } |
|
73 | + public function getClient() : ClientInterface |
|
74 | + { |
|
75 | + return $this->client; |
|
76 | + } |
|
77 | + public function getNodePool() : NodePoolInterface |
|
78 | + { |
|
79 | + return $this->nodePool; |
|
80 | + } |
|
81 | + public function getLogger() : LoggerInterface |
|
82 | + { |
|
83 | + return $this->logger; |
|
84 | + } |
|
85 | + public function getOTelTracer() : TracerInterface |
|
86 | + { |
|
87 | + if (empty($this->otelTracer)) { |
|
88 | + $this->otelTracer = OpenTelemetry::getTracer(Globals::tracerProvider()); |
|
89 | + } |
|
90 | + return $this->otelTracer; |
|
91 | + } |
|
92 | + public function setOTelTracer(TracerInterface $tracer) : self |
|
93 | + { |
|
94 | + $this->otelTracer = $tracer; |
|
95 | + return $this; |
|
96 | + } |
|
97 | + public function setHeader(string $name, string $value) : self |
|
98 | + { |
|
99 | + $this->headers[$name] = $value; |
|
100 | + return $this; |
|
101 | + } |
|
102 | + /** |
|
103 | + * @throws InvalidArgumentException |
|
104 | + */ |
|
105 | + public function setRetries(int $num) : self |
|
106 | + { |
|
107 | + if ($num < 0) { |
|
108 | + throw new InvalidArgumentException('The retries number must be a positive integer'); |
|
109 | + } |
|
110 | + $this->retries = $num; |
|
111 | + return $this; |
|
112 | + } |
|
113 | + public function getRetries() : int |
|
114 | + { |
|
115 | + return $this->retries; |
|
116 | + } |
|
117 | + public function getHeaders() : array |
|
118 | + { |
|
119 | + return $this->headers; |
|
120 | + } |
|
121 | + public function setUserInfo(string $user, string $password = '') : self |
|
122 | + { |
|
123 | + $this->user = $user; |
|
124 | + $this->password = $password; |
|
125 | + return $this; |
|
126 | + } |
|
127 | + public function setUserAgent(string $name, string $version) : self |
|
128 | + { |
|
129 | + $this->headers['User-Agent'] = sprintf("%s/%s (%s %s; PHP %s)", $name, $version, \PHP_OS, $this->getOSVersion(), phpversion()); |
|
130 | + return $this; |
|
131 | + } |
|
132 | + /** |
|
133 | + * Set the x-elastic-client-meta header |
|
134 | + * |
|
135 | + * The header format is specified by the following regex: |
|
136 | + * ^[a-z]{1,}=[a-z0-9\.\-]{1,}(?:,[a-z]{1,}=[a-z0-9\.\-]+)*$ |
|
137 | + */ |
|
138 | + public function setElasticMetaHeader(string $clientName, string $clientVersion, bool $async = \false) : self |
|
139 | + { |
|
140 | + $phpSemVersion = sprintf("%d.%d.%d", \PHP_MAJOR_VERSION, \PHP_MINOR_VERSION, \PHP_RELEASE_VERSION); |
|
141 | + $meta = sprintf("%s=%s,php=%s,t=%s,a=%d", $clientName, $this->purgePreReleaseTag($clientVersion), $phpSemVersion, $this->purgePreReleaseTag(self::VERSION), $async ? 1 : 0); |
|
142 | + $lib = $this->getClientLibraryInfo(); |
|
143 | + if (!empty($lib)) { |
|
144 | + $meta .= sprintf(",%s=%s", $lib[0], $lib[1]); |
|
145 | + } |
|
146 | + $this->headers['x-elastic-client-meta'] = $meta; |
|
147 | + return $this; |
|
148 | + } |
|
149 | + /** |
|
150 | + * Remove pre-release suffix with a single 'p' letter |
|
151 | + */ |
|
152 | + private function purgePreReleaseTag(string $version) : string |
|
153 | + { |
|
154 | + return str_replace(['alpha', 'beta', 'snapshot', 'rc', 'pre'], 'p', strtolower($version)); |
|
155 | + } |
|
156 | + public function getLastRequest() : RequestInterface |
|
157 | + { |
|
158 | + return $this->lastRequest; |
|
159 | + } |
|
160 | + public function getLastResponse() : ResponseInterface |
|
161 | + { |
|
162 | + return $this->lastResponse; |
|
163 | + } |
|
164 | + /** |
|
165 | + * Setup the headers, if not already present |
|
166 | + */ |
|
167 | + private function setupHeaders(RequestInterface $request) : RequestInterface |
|
168 | + { |
|
169 | + foreach ($this->headers as $name => $value) { |
|
170 | + if (!$request->hasHeader($name)) { |
|
171 | + $request = $request->withHeader($name, $value); |
|
172 | + } |
|
173 | + } |
|
174 | + return $request; |
|
175 | + } |
|
176 | + /** |
|
177 | + * Setup the user info, if not already present |
|
178 | + */ |
|
179 | + private function setupUserInfo(RequestInterface $request) : RequestInterface |
|
180 | + { |
|
181 | + $uri = $request->getUri(); |
|
182 | + if (empty($uri->getUserInfo())) { |
|
183 | + if (isset($this->user)) { |
|
184 | + $request = $request->withUri($uri->withUserInfo($this->user, $this->password)); |
|
185 | + } |
|
186 | + } |
|
187 | + return $request; |
|
188 | + } |
|
189 | + /** |
|
190 | + * Setup the connection Uri |
|
191 | + */ |
|
192 | + private function setupConnectionUri(Node $node, RequestInterface $request) : RequestInterface |
|
193 | + { |
|
194 | + $uri = $node->getUri(); |
|
195 | + $path = $request->getUri()->getPath(); |
|
196 | + $nodePath = $uri->getPath(); |
|
197 | + // If the node has a path we need to use it as prefix for the existing path |
|
198 | + // @see https://github.com/elastic/elastic-transport-php/pull/20 |
|
199 | + if (!empty($nodePath)) { |
|
200 | + $path = sprintf("%s/%s", \rtrim($nodePath, '/'), \ltrim($path, '/')); |
|
201 | + } |
|
202 | + // If the user information is not in the request, we check if it is present in the node uri |
|
203 | + // @see https://github.com/elastic/elastic-transport-php/issues/18 |
|
204 | + if (empty($request->getUri()->getUserInfo()) && !empty($uri->getUserInfo())) { |
|
205 | + $userInfo = \explode(':', $uri->getUserInfo()); |
|
206 | + $request = $request->withUri($request->getUri()->withUserInfo($userInfo[0], $userInfo[1] ?? null)); |
|
207 | + } |
|
208 | + return $request->withUri($request->getUri()->withHost($uri->getHost())->withPort($uri->getPort())->withScheme($uri->getScheme())->withPath($path)); |
|
209 | + } |
|
210 | + private function decorateRequest(RequestInterface $request) : RequestInterface |
|
211 | + { |
|
212 | + $request = $this->setupHeaders($request); |
|
213 | + return $this->setupUserInfo($request); |
|
214 | + } |
|
215 | + private function logHeaders(MessageInterface $message) : void |
|
216 | + { |
|
217 | + $this->logger->debug(sprintf("Headers: %s\nBody: %s", json_encode($message->getHeaders()), (string) $message->getBody())); |
|
218 | + } |
|
219 | + private function logRequest(string $title, RequestInterface $request) : void |
|
220 | + { |
|
221 | + $this->logger->info(sprintf("%s: %s %s", $title, $request->getMethod(), (string) $request->getUri()), ['request' => $request]); |
|
222 | + $this->logHeaders($request); |
|
223 | + } |
|
224 | + private function logResponse(string $title, ResponseInterface $response, int $retry) : void |
|
225 | + { |
|
226 | + $this->logger->info(sprintf("%s (retry %d): %d", $title, $retry, $response->getStatusCode()), ['response' => $response, 'retry' => $retry]); |
|
227 | + $this->logHeaders($response); |
|
228 | + } |
|
229 | + /** |
|
230 | + * @throws NoNodeAvailableException |
|
231 | + * @throws ClientExceptionInterface |
|
232 | + */ |
|
233 | + public function sendRequest(RequestInterface $request) : ResponseInterface |
|
234 | + { |
|
235 | + if (empty($request->getUri()->getHost())) { |
|
236 | + $node = $this->nodePool->nextNode(); |
|
237 | + $request = $this->setupConnectionUri($node, $request); |
|
238 | + } |
|
239 | + $request = $this->decorateRequest($request); |
|
240 | + $this->lastRequest = $request; |
|
241 | + $this->logRequest("Request", $request); |
|
242 | + // OpenTelemetry get tracer |
|
243 | + if (\getenv(OpenTelemetry::ENV_VARIABLE_ENABLED)) { |
|
244 | + $tracer = $this->getOTelTracer(); |
|
245 | + } |
|
246 | + $count = -1; |
|
247 | + while ($count < $this->getRetries()) { |
|
248 | + try { |
|
249 | + $count++; |
|
250 | + // OpenTelemetry span start |
|
251 | + if (!empty($tracer)) { |
|
252 | + if ($request instanceof ServerRequestInterface) { |
|
253 | + $opts = $request->getAttribute(OpenTelemetry::PSR7_OTEL_ATTRIBUTE_NAME, []); |
|
254 | + } |
|
255 | + $spanName = $opts['db.operation.name'] ?? $request->getUri()->getPath(); |
|
256 | + $span = $tracer->spanBuilder($spanName)->startSpan(); |
|
257 | + $span->setAttribute('http.request.method', $request->getMethod()); |
|
258 | + $span->setAttribute('url.full', $this->getFullUrl($request)); |
|
259 | + $span->setAttribute('server.address', $request->getUri()->getHost()); |
|
260 | + $span->setAttribute('server.port', $request->getUri()->getPort()); |
|
261 | + if (!empty($opts)) { |
|
262 | + $span->setAttributes($opts); |
|
263 | + } |
|
264 | + } |
|
265 | + $response = $this->client->sendRequest($request); |
|
266 | + $this->lastResponse = $response; |
|
267 | + $this->logResponse("Response", $response, $count); |
|
268 | + return $response; |
|
269 | + } catch (NetworkExceptionInterface $e) { |
|
270 | + $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
271 | + if (!empty($span)) { |
|
272 | + $span->setAttribute('error.type', $e->getMessage()); |
|
273 | + } |
|
274 | + if (isset($node)) { |
|
275 | + $node->markAlive(\false); |
|
276 | + $node = $this->nodePool->nextNode(); |
|
277 | + $request = $this->setupConnectionUri($node, $request); |
|
278 | + } |
|
279 | + } catch (ClientExceptionInterface $e) { |
|
280 | + $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
281 | + if (!empty($span)) { |
|
282 | + $span->setAttribute('error.type', $e->getMessage()); |
|
283 | + } |
|
284 | + throw $e; |
|
285 | + } finally { |
|
286 | + // OpenTelemetry span end |
|
287 | + if (!empty($span)) { |
|
288 | + $span->end(); |
|
289 | + } |
|
290 | + } |
|
291 | + } |
|
292 | + $exceededMsg = sprintf("Exceeded maximum number of retries (%d)", $this->getRetries()); |
|
293 | + $this->logger->error($exceededMsg); |
|
294 | + throw new NoNodeAvailableException($exceededMsg); |
|
295 | + } |
|
296 | + public function setAsyncClient(HttpAsyncClient $asyncClient) : self |
|
297 | + { |
|
298 | + $this->asyncClient = $asyncClient; |
|
299 | + return $this; |
|
300 | + } |
|
301 | + /** |
|
302 | + * @throws NoAsyncClientException |
|
303 | + */ |
|
304 | + public function getAsyncClient() : HttpAsyncClient |
|
305 | + { |
|
306 | + if (!empty($this->asyncClient)) { |
|
307 | + return $this->asyncClient; |
|
308 | + } |
|
309 | + if ($this->client instanceof HttpAsyncClient) { |
|
310 | + return $this->client; |
|
311 | + } |
|
312 | + try { |
|
313 | + $this->asyncClient = HttpAsyncClientDiscovery::find(); |
|
314 | + } catch (Exception $e) { |
|
315 | + throw new NoAsyncClientException(sprintf("I did not find any HTTP library with HttpAsyncClient interface. " . "Make sure to install a package providing \"php-http/async-client-implementation\". " . "You can also set a specific async library using %s::setAsyncClient()", self::class)); |
|
316 | + } |
|
317 | + return $this->asyncClient; |
|
318 | + } |
|
319 | + public function setAsyncOnSuccess(OnSuccessInterface $success) : self |
|
320 | + { |
|
321 | + $this->onAsyncSuccess = $success; |
|
322 | + return $this; |
|
323 | + } |
|
324 | + public function getAsyncOnSuccess() : OnSuccessInterface |
|
325 | + { |
|
326 | + if (empty($this->onAsyncSuccess)) { |
|
327 | + $this->onAsyncSuccess = new OnSuccessDefault(); |
|
328 | + } |
|
329 | + return $this->onAsyncSuccess; |
|
330 | + } |
|
331 | + public function setAsyncOnFailure(OnFailureInterface $failure) : self |
|
332 | + { |
|
333 | + $this->onAsyncFailure = $failure; |
|
334 | + return $this; |
|
335 | + } |
|
336 | + public function getAsyncOnFailure() : OnFailureInterface |
|
337 | + { |
|
338 | + if (empty($this->onAsyncFailure)) { |
|
339 | + $this->onAsyncFailure = new OnFailureDefault(); |
|
340 | + } |
|
341 | + return $this->onAsyncFailure; |
|
342 | + } |
|
343 | + /** |
|
344 | + * @throws Exception |
|
345 | + */ |
|
346 | + public function sendAsyncRequest(RequestInterface $request) : Promise |
|
347 | + { |
|
348 | + $client = $this->getAsyncClient(); |
|
349 | + $node = null; |
|
350 | + if (empty($request->getUri()->getHost())) { |
|
351 | + $node = $this->nodePool->nextNode(); |
|
352 | + $request = $this->setupConnectionUri($node, $request); |
|
353 | + } |
|
354 | + $request = $this->decorateRequest($request); |
|
355 | + $this->lastRequest = $request; |
|
356 | + $this->logRequest("Async Request", $request); |
|
357 | + $count = 0; |
|
358 | + $promise = $client->sendAsyncRequest($request); |
|
359 | + // onFulfilled callable |
|
360 | + $onFulfilled = function (ResponseInterface $response) use(&$count) { |
|
361 | + $this->lastResponse = $response; |
|
362 | + $this->logResponse("Async Response", $response, $count); |
|
363 | + return $this->getAsyncOnSuccess()->success($response, $count); |
|
364 | + }; |
|
365 | + // onRejected callable |
|
366 | + $onRejected = function (Exception $e) use($client, $request, &$count, $node) { |
|
367 | + $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
368 | + $this->getAsyncOnFailure()->failure($e, $request, $count, $node ?? null); |
|
369 | + if (isset($node)) { |
|
370 | + $node->markAlive(\false); |
|
371 | + $node = $this->nodePool->nextNode(); |
|
372 | + $request = $this->setupConnectionUri($node, $request); |
|
373 | + } |
|
374 | + $count++; |
|
375 | + return $client->sendAsyncRequest($request); |
|
376 | + }; |
|
377 | + // Add getRetries() callables using then() |
|
378 | + for ($i = 0; $i < $this->getRetries(); $i++) { |
|
379 | + $promise = $promise->then($onFulfilled, $onRejected); |
|
380 | + } |
|
381 | + // Add the last getRetries()+1 callable for managing the exceeded error |
|
382 | + $promise = $promise->then($onFulfilled, function (Exception $e) use(&$count) { |
|
383 | + $exceededMsg = sprintf("Exceeded maximum number of retries (%d)", $this->getRetries()); |
|
384 | + $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
|
385 | + $this->logger->error($exceededMsg); |
|
386 | + throw new NoNodeAvailableException(sprintf("%s: %s", $exceededMsg, $e->getMessage())); |
|
387 | + }); |
|
388 | + return $promise; |
|
389 | + } |
|
390 | + /** |
|
391 | + * Get the OS version using php_uname if available |
|
392 | + * otherwise it returns an empty string |
|
393 | + */ |
|
394 | + private function getOSVersion() : string |
|
395 | + { |
|
396 | + if (!isset($this->OSVersion)) { |
|
397 | + $disable_functions = (string) ini_get('disable_functions'); |
|
398 | + $this->OSVersion = strpos(strtolower($disable_functions), 'php_uname') !== \false ? '' : php_uname("r"); |
|
399 | + } |
|
400 | + return $this->OSVersion; |
|
401 | + } |
|
402 | + /** |
|
403 | + * Returns the name and the version of the Client HTTP library used |
|
404 | + * Here a list of supported libraries: |
|
405 | + * gu => guzzlehttp/guzzle |
|
406 | + * sy => symfony/http-client |
|
407 | + */ |
|
408 | + private function getClientLibraryInfo() : array |
|
409 | + { |
|
410 | + $clientClass = get_class($this->client); |
|
411 | + if (\false !== strpos($clientClass, 'OCA\\FullTextSearch_Elasticsearch\\Vendor\\GuzzleHttp\\Client')) { |
|
412 | + return ['gu', InstalledVersions::getPrettyVersion('guzzlehttp/guzzle')]; |
|
413 | + } |
|
414 | + if (\false !== strpos($clientClass, 'OCA\\FullTextSearch_Elasticsearch\\Vendor\\Symfony\\Component\\HttpClient')) { |
|
415 | + return ['sy', InstalledVersions::getPrettyVersion('symfony/http-client')]; |
|
416 | + } |
|
417 | + return []; |
|
418 | + } |
|
419 | + /** |
|
420 | + * Return the full URL in the format |
|
421 | + * scheme://host:port/path?query_string |
|
422 | + */ |
|
423 | + private function getFullUrl(RequestInterface $request) : string |
|
424 | + { |
|
425 | + $fullUrl = sprintf("%s://%s:%s%s", $request->getUri()->getScheme(), $request->getUri()->getHost(), $request->getUri()->getPort(), $request->getUri()->getPath()); |
|
426 | + $queryString = $request->getUri()->getQuery(); |
|
427 | + if (!empty($queryString)) { |
|
428 | + $fullUrl .= '?' . $queryString; |
|
429 | + } |
|
430 | + return $fullUrl; |
|
431 | + } |
|
432 | 432 | } |
@@ -11,7 +11,7 @@ discard block |
||
11 | 11 | * Elasticsearch B.V licenses this file to you under the MIT License. |
12 | 12 | * See the LICENSE file in the project root for more information. |
13 | 13 | */ |
14 | -declare (strict_types=1); |
|
14 | +declare(strict_types=1); |
|
15 | 15 | namespace OCA\FullTextSearch_Elasticsearch\Vendor\Elastic\Transport; |
16 | 16 | |
17 | 17 | use Composer\InstalledVersions; |
@@ -214,11 +214,11 @@ discard block |
||
214 | 214 | } |
215 | 215 | private function logHeaders(MessageInterface $message) : void |
216 | 216 | { |
217 | - $this->logger->debug(sprintf("Headers: %s\nBody: %s", json_encode($message->getHeaders()), (string) $message->getBody())); |
|
217 | + $this->logger->debug(sprintf("Headers: %s\nBody: %s", json_encode($message->getHeaders()), (string)$message->getBody())); |
|
218 | 218 | } |
219 | 219 | private function logRequest(string $title, RequestInterface $request) : void |
220 | 220 | { |
221 | - $this->logger->info(sprintf("%s: %s %s", $title, $request->getMethod(), (string) $request->getUri()), ['request' => $request]); |
|
221 | + $this->logger->info(sprintf("%s: %s %s", $title, $request->getMethod(), (string)$request->getUri()), ['request' => $request]); |
|
222 | 222 | $this->logHeaders($request); |
223 | 223 | } |
224 | 224 | private function logResponse(string $title, ResponseInterface $response, int $retry) : void |
@@ -312,7 +312,7 @@ discard block |
||
312 | 312 | try { |
313 | 313 | $this->asyncClient = HttpAsyncClientDiscovery::find(); |
314 | 314 | } catch (Exception $e) { |
315 | - throw new NoAsyncClientException(sprintf("I did not find any HTTP library with HttpAsyncClient interface. " . "Make sure to install a package providing \"php-http/async-client-implementation\". " . "You can also set a specific async library using %s::setAsyncClient()", self::class)); |
|
315 | + throw new NoAsyncClientException(sprintf("I did not find any HTTP library with HttpAsyncClient interface. "."Make sure to install a package providing \"php-http/async-client-implementation\". "."You can also set a specific async library using %s::setAsyncClient()", self::class)); |
|
316 | 316 | } |
317 | 317 | return $this->asyncClient; |
318 | 318 | } |
@@ -357,13 +357,13 @@ discard block |
||
357 | 357 | $count = 0; |
358 | 358 | $promise = $client->sendAsyncRequest($request); |
359 | 359 | // onFulfilled callable |
360 | - $onFulfilled = function (ResponseInterface $response) use(&$count) { |
|
360 | + $onFulfilled = function(ResponseInterface $response) use(&$count) { |
|
361 | 361 | $this->lastResponse = $response; |
362 | 362 | $this->logResponse("Async Response", $response, $count); |
363 | 363 | return $this->getAsyncOnSuccess()->success($response, $count); |
364 | 364 | }; |
365 | 365 | // onRejected callable |
366 | - $onRejected = function (Exception $e) use($client, $request, &$count, $node) { |
|
366 | + $onRejected = function(Exception $e) use($client, $request, &$count, $node) { |
|
367 | 367 | $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
368 | 368 | $this->getAsyncOnFailure()->failure($e, $request, $count, $node ?? null); |
369 | 369 | if (isset($node)) { |
@@ -379,7 +379,7 @@ discard block |
||
379 | 379 | $promise = $promise->then($onFulfilled, $onRejected); |
380 | 380 | } |
381 | 381 | // Add the last getRetries()+1 callable for managing the exceeded error |
382 | - $promise = $promise->then($onFulfilled, function (Exception $e) use(&$count) { |
|
382 | + $promise = $promise->then($onFulfilled, function(Exception $e) use(&$count) { |
|
383 | 383 | $exceededMsg = sprintf("Exceeded maximum number of retries (%d)", $this->getRetries()); |
384 | 384 | $this->logger->error(sprintf("Retry %d: %s", $count, $e->getMessage())); |
385 | 385 | $this->logger->error($exceededMsg); |
@@ -394,7 +394,7 @@ discard block |
||
394 | 394 | private function getOSVersion() : string |
395 | 395 | { |
396 | 396 | if (!isset($this->OSVersion)) { |
397 | - $disable_functions = (string) ini_get('disable_functions'); |
|
397 | + $disable_functions = (string)ini_get('disable_functions'); |
|
398 | 398 | $this->OSVersion = strpos(strtolower($disable_functions), 'php_uname') !== \false ? '' : php_uname("r"); |
399 | 399 | } |
400 | 400 | return $this->OSVersion; |
@@ -425,7 +425,7 @@ discard block |
||
425 | 425 | $fullUrl = sprintf("%s://%s:%s%s", $request->getUri()->getScheme(), $request->getUri()->getHost(), $request->getUri()->getPort(), $request->getUri()->getPath()); |
426 | 426 | $queryString = $request->getUri()->getQuery(); |
427 | 427 | if (!empty($queryString)) { |
428 | - $fullUrl .= '?' . $queryString; |
|
428 | + $fullUrl .= '?'.$queryString; |
|
429 | 429 | } |
430 | 430 | return $fullUrl; |
431 | 431 | } |
@@ -27,84 +27,84 @@ |
||
27 | 27 | use Throwable; |
28 | 28 | class TransportBuilder |
29 | 29 | { |
30 | - protected ClientInterface $client; |
|
31 | - protected NodePoolInterface $nodePool; |
|
32 | - protected LoggerInterface $logger; |
|
33 | - protected array $hosts = []; |
|
34 | - protected TracerInterface $OTelTracer; |
|
35 | - public final function __construct() |
|
36 | - { |
|
37 | - } |
|
38 | - public static function create() : TransportBuilder |
|
39 | - { |
|
40 | - return new static(); |
|
41 | - } |
|
42 | - public function setClient(ClientInterface $client) : self |
|
43 | - { |
|
44 | - $this->client = $client; |
|
45 | - return $this; |
|
46 | - } |
|
47 | - public function getClient() : ClientInterface |
|
48 | - { |
|
49 | - if (empty($this->client)) { |
|
50 | - $this->client = Psr18ClientDiscovery::find(); |
|
51 | - } |
|
52 | - return $this->client; |
|
53 | - } |
|
54 | - public function setNodePool(NodePoolInterface $nodePool) : self |
|
55 | - { |
|
56 | - $this->nodePool = $nodePool; |
|
57 | - return $this; |
|
58 | - } |
|
59 | - public function getNodePool() : NodePoolInterface |
|
60 | - { |
|
61 | - if (empty($this->nodePool)) { |
|
62 | - $this->nodePool = new SimpleNodePool(new RoundRobin(), new NoResurrect()); |
|
63 | - } |
|
64 | - return $this->nodePool; |
|
65 | - } |
|
66 | - public function setLogger(LoggerInterface $logger) : self |
|
67 | - { |
|
68 | - $this->logger = $logger; |
|
69 | - return $this; |
|
70 | - } |
|
71 | - public function getLogger() : LoggerInterface |
|
72 | - { |
|
73 | - if (empty($this->logger)) { |
|
74 | - $this->logger = new NullLogger(); |
|
75 | - } |
|
76 | - return $this->logger; |
|
77 | - } |
|
78 | - public function setHosts(array $hosts) : self |
|
79 | - { |
|
80 | - $this->hosts = $hosts; |
|
81 | - return $this; |
|
82 | - } |
|
83 | - public function getHosts() : array |
|
84 | - { |
|
85 | - return $this->hosts; |
|
86 | - } |
|
87 | - public function setCloudId(string $cloudId) : self |
|
88 | - { |
|
89 | - $this->hosts = [$this->parseElasticCloudId($cloudId)]; |
|
90 | - return $this; |
|
91 | - } |
|
92 | - public function build() : Transport |
|
93 | - { |
|
94 | - return new Transport($this->getClient(), $this->getNodePool()->setHosts($this->hosts), $this->getLogger()); |
|
95 | - } |
|
96 | - /** |
|
97 | - * Return the URL of Elastic Cloud from the Cloud ID |
|
98 | - */ |
|
99 | - private function parseElasticCloudId(string $cloudId) : string |
|
100 | - { |
|
101 | - try { |
|
102 | - list($name, $encoded) = \explode(':', $cloudId); |
|
103 | - list($uri, $uuids) = \explode('$', \base64_decode($encoded)); |
|
104 | - list($es, ) = \explode(':', $uuids); |
|
105 | - return \sprintf("https://%s.%s", $es, $uri); |
|
106 | - } catch (Throwable $t) { |
|
107 | - throw new Exception\CloudIdParseException('Cloud ID not valid'); |
|
108 | - } |
|
109 | - } |
|
30 | + protected ClientInterface $client; |
|
31 | + protected NodePoolInterface $nodePool; |
|
32 | + protected LoggerInterface $logger; |
|
33 | + protected array $hosts = []; |
|
34 | + protected TracerInterface $OTelTracer; |
|
35 | + public final function __construct() |
|
36 | + { |
|
37 | + } |
|
38 | + public static function create() : TransportBuilder |
|
39 | + { |
|
40 | + return new static(); |
|
41 | + } |
|
42 | + public function setClient(ClientInterface $client) : self |
|
43 | + { |
|
44 | + $this->client = $client; |
|
45 | + return $this; |
|
46 | + } |
|
47 | + public function getClient() : ClientInterface |
|
48 | + { |
|
49 | + if (empty($this->client)) { |
|
50 | + $this->client = Psr18ClientDiscovery::find(); |
|
51 | + } |
|
52 | + return $this->client; |
|
53 | + } |
|
54 | + public function setNodePool(NodePoolInterface $nodePool) : self |
|
55 | + { |
|
56 | + $this->nodePool = $nodePool; |
|
57 | + return $this; |
|
58 | + } |
|
59 | + public function getNodePool() : NodePoolInterface |
|
60 | + { |
|
61 | + if (empty($this->nodePool)) { |
|
62 | + $this->nodePool = new SimpleNodePool(new RoundRobin(), new NoResurrect()); |
|
63 | + } |
|
64 | + return $this->nodePool; |
|
65 | + } |
|
66 | + public function setLogger(LoggerInterface $logger) : self |
|
67 | + { |
|
68 | + $this->logger = $logger; |
|
69 | + return $this; |
|
70 | + } |
|
71 | + public function getLogger() : LoggerInterface |
|
72 | + { |
|
73 | + if (empty($this->logger)) { |
|
74 | + $this->logger = new NullLogger(); |
|
75 | + } |
|
76 | + return $this->logger; |
|
77 | + } |
|
78 | + public function setHosts(array $hosts) : self |
|
79 | + { |
|
80 | + $this->hosts = $hosts; |
|
81 | + return $this; |
|
82 | + } |
|
83 | + public function getHosts() : array |
|
84 | + { |
|
85 | + return $this->hosts; |
|
86 | + } |
|
87 | + public function setCloudId(string $cloudId) : self |
|
88 | + { |
|
89 | + $this->hosts = [$this->parseElasticCloudId($cloudId)]; |
|
90 | + return $this; |
|
91 | + } |
|
92 | + public function build() : Transport |
|
93 | + { |
|
94 | + return new Transport($this->getClient(), $this->getNodePool()->setHosts($this->hosts), $this->getLogger()); |
|
95 | + } |
|
96 | + /** |
|
97 | + * Return the URL of Elastic Cloud from the Cloud ID |
|
98 | + */ |
|
99 | + private function parseElasticCloudId(string $cloudId) : string |
|
100 | + { |
|
101 | + try { |
|
102 | + list($name, $encoded) = \explode(':', $cloudId); |
|
103 | + list($uri, $uuids) = \explode('$', \base64_decode($encoded)); |
|
104 | + list($es, ) = \explode(':', $uuids); |
|
105 | + return \sprintf("https://%s.%s", $es, $uri); |
|
106 | + } catch (Throwable $t) { |
|
107 | + throw new Exception\CloudIdParseException('Cloud ID not valid'); |
|
108 | + } |
|
109 | + } |
|
110 | 110 | } |
@@ -20,72 +20,72 @@ |
||
20 | 20 | use OCA\FullTextSearch_Elasticsearch\Vendor\OpenTelemetry\API\Trace\TracerProviderInterface; |
21 | 21 | class OpenTelemetry |
22 | 22 | { |
23 | - const OTEL_TRACER_NAME = 'elasticsearch-api'; |
|
24 | - const PSR7_OTEL_ATTRIBUTE_NAME = 'otel-elastic-transport'; |
|
25 | - // Valid values for the enabled config are 'true' and 'false' |
|
26 | - const ENV_VARIABLE_ENABLED = 'OTEL_PHP_INSTRUMENTATION_ELASTICSEARCH_ENABLED'; |
|
27 | - /** |
|
28 | - * Describes how to handle search queries in the request body when assigned to |
|
29 | - * span attribute. |
|
30 | - * Valid values are 'raw', 'omit', 'sanitize'. Default is 'omit' |
|
31 | - */ |
|
32 | - const ALLOWED_BODY_STRATEGIES = ['raw', 'omit', 'sanitize']; |
|
33 | - const ENV_VARIABLE_BODY_STRATEGY = 'OTEL_PHP_INSTRUMENTATION_ELASTICSEARCH_CAPTURE_SEARCH_QUERY'; |
|
34 | - const DEFAULT_BODY_STRATEGY = 'omit'; |
|
35 | - /** |
|
36 | - * A string list of keys whose values are redacted. This is only relevant if the body strategy is |
|
37 | - * 'sanitize'. For example, a config 'sensitive-key,other-key' will redact the values at |
|
38 | - * 'sensitive-key' and 'other-key' in addition to the default keys |
|
39 | - */ |
|
40 | - const ENV_VARIABLE_BODY_SANITIZE_KEYS = 'OTEL_PHP_INSTRUMENTATION_ELASTICSEARCH_SEARCH_QUERY_SANITIZE_KEYS'; |
|
41 | - const DEFAULT_SANITIZER_KEY_PATTERNS = ['password', 'passwd', 'pwd', 'secret', 'key', 'token', 'session', 'credit', 'card', 'auth', 'set-cookie', 'email', 'tel', 'phone']; |
|
42 | - const REDACTED_STRING = 'REDACTED'; |
|
43 | - public static function redactBody(string $body) : string |
|
44 | - { |
|
45 | - switch (self::getBodyStrategy()) { |
|
46 | - case 'sanitize': |
|
47 | - $sanitizeKeys = \getenv(self::ENV_VARIABLE_BODY_SANITIZE_KEYS); |
|
48 | - $sanitizeKeys = \false !== $sanitizeKeys ? \explode(',', $sanitizeKeys) : []; |
|
49 | - return self::sanitizeBody($body, $sanitizeKeys); |
|
50 | - case 'raw': |
|
51 | - return $body; |
|
52 | - default: |
|
53 | - return ''; |
|
54 | - } |
|
55 | - } |
|
56 | - private static function getBodyStrategy() : string |
|
57 | - { |
|
58 | - $strategy = \getenv(self::ENV_VARIABLE_BODY_STRATEGY); |
|
59 | - if (\false === $strategy) { |
|
60 | - $strategy = self::DEFAULT_BODY_STRATEGY; |
|
61 | - } |
|
62 | - if (!\in_array($strategy, self::ALLOWED_BODY_STRATEGIES)) { |
|
63 | - throw new InvalidArgumentException(\sprintf('The body strategy specified %s is not valid. The available strategies are %s', $strategy, \implode(',', self::ALLOWED_BODY_STRATEGIES))); |
|
64 | - } |
|
65 | - return $strategy; |
|
66 | - } |
|
67 | - public static function getTracer(TracerProviderInterface $tracerProvider) : TracerInterface |
|
68 | - { |
|
69 | - return $tracerProvider->getTracer(self::OTEL_TRACER_NAME, Transport::VERSION); |
|
70 | - } |
|
71 | - private static function sanitizeBody(string $body, array $sanitizeKeys) : string |
|
72 | - { |
|
73 | - if (empty($body)) { |
|
74 | - return ''; |
|
75 | - } |
|
76 | - $json = \json_decode($body, \true); |
|
77 | - if (!\is_array($json)) { |
|
78 | - return ''; |
|
79 | - } |
|
80 | - $patterns = \array_merge(self::DEFAULT_SANITIZER_KEY_PATTERNS, $sanitizeKeys); |
|
81 | - // Convert the patterns array into a regex |
|
82 | - $regex = \sprintf('/%s/', \implode('|', $patterns)); |
|
83 | - // Recursively traverse the array and redact the specified keys |
|
84 | - \array_walk_recursive($json, function (&$value, $key) use($regex) { |
|
85 | - if (\preg_match($regex, $key, $matches)) { |
|
86 | - $value = self::REDACTED_STRING; |
|
87 | - } |
|
88 | - }); |
|
89 | - return JsonSerializer::serialize($json); |
|
90 | - } |
|
23 | + const OTEL_TRACER_NAME = 'elasticsearch-api'; |
|
24 | + const PSR7_OTEL_ATTRIBUTE_NAME = 'otel-elastic-transport'; |
|
25 | + // Valid values for the enabled config are 'true' and 'false' |
|
26 | + const ENV_VARIABLE_ENABLED = 'OTEL_PHP_INSTRUMENTATION_ELASTICSEARCH_ENABLED'; |
|
27 | + /** |
|
28 | + * Describes how to handle search queries in the request body when assigned to |
|
29 | + * span attribute. |
|
30 | + * Valid values are 'raw', 'omit', 'sanitize'. Default is 'omit' |
|
31 | + */ |
|
32 | + const ALLOWED_BODY_STRATEGIES = ['raw', 'omit', 'sanitize']; |
|
33 | + const ENV_VARIABLE_BODY_STRATEGY = 'OTEL_PHP_INSTRUMENTATION_ELASTICSEARCH_CAPTURE_SEARCH_QUERY'; |
|
34 | + const DEFAULT_BODY_STRATEGY = 'omit'; |
|
35 | + /** |
|
36 | + * A string list of keys whose values are redacted. This is only relevant if the body strategy is |
|
37 | + * 'sanitize'. For example, a config 'sensitive-key,other-key' will redact the values at |
|
38 | + * 'sensitive-key' and 'other-key' in addition to the default keys |
|
39 | + */ |
|
40 | + const ENV_VARIABLE_BODY_SANITIZE_KEYS = 'OTEL_PHP_INSTRUMENTATION_ELASTICSEARCH_SEARCH_QUERY_SANITIZE_KEYS'; |
|
41 | + const DEFAULT_SANITIZER_KEY_PATTERNS = ['password', 'passwd', 'pwd', 'secret', 'key', 'token', 'session', 'credit', 'card', 'auth', 'set-cookie', 'email', 'tel', 'phone']; |
|
42 | + const REDACTED_STRING = 'REDACTED'; |
|
43 | + public static function redactBody(string $body) : string |
|
44 | + { |
|
45 | + switch (self::getBodyStrategy()) { |
|
46 | + case 'sanitize': |
|
47 | + $sanitizeKeys = \getenv(self::ENV_VARIABLE_BODY_SANITIZE_KEYS); |
|
48 | + $sanitizeKeys = \false !== $sanitizeKeys ? \explode(',', $sanitizeKeys) : []; |
|
49 | + return self::sanitizeBody($body, $sanitizeKeys); |
|
50 | + case 'raw': |
|
51 | + return $body; |
|
52 | + default: |
|
53 | + return ''; |
|
54 | + } |
|
55 | + } |
|
56 | + private static function getBodyStrategy() : string |
|
57 | + { |
|
58 | + $strategy = \getenv(self::ENV_VARIABLE_BODY_STRATEGY); |
|
59 | + if (\false === $strategy) { |
|
60 | + $strategy = self::DEFAULT_BODY_STRATEGY; |
|
61 | + } |
|
62 | + if (!\in_array($strategy, self::ALLOWED_BODY_STRATEGIES)) { |
|
63 | + throw new InvalidArgumentException(\sprintf('The body strategy specified %s is not valid. The available strategies are %s', $strategy, \implode(',', self::ALLOWED_BODY_STRATEGIES))); |
|
64 | + } |
|
65 | + return $strategy; |
|
66 | + } |
|
67 | + public static function getTracer(TracerProviderInterface $tracerProvider) : TracerInterface |
|
68 | + { |
|
69 | + return $tracerProvider->getTracer(self::OTEL_TRACER_NAME, Transport::VERSION); |
|
70 | + } |
|
71 | + private static function sanitizeBody(string $body, array $sanitizeKeys) : string |
|
72 | + { |
|
73 | + if (empty($body)) { |
|
74 | + return ''; |
|
75 | + } |
|
76 | + $json = \json_decode($body, \true); |
|
77 | + if (!\is_array($json)) { |
|
78 | + return ''; |
|
79 | + } |
|
80 | + $patterns = \array_merge(self::DEFAULT_SANITIZER_KEY_PATTERNS, $sanitizeKeys); |
|
81 | + // Convert the patterns array into a regex |
|
82 | + $regex = \sprintf('/%s/', \implode('|', $patterns)); |
|
83 | + // Recursively traverse the array and redact the specified keys |
|
84 | + \array_walk_recursive($json, function (&$value, $key) use($regex) { |
|
85 | + if (\preg_match($regex, $key, $matches)) { |
|
86 | + $value = self::REDACTED_STRING; |
|
87 | + } |
|
88 | + }); |
|
89 | + return JsonSerializer::serialize($json); |
|
90 | + } |
|
91 | 91 | } |
@@ -11,7 +11,7 @@ discard block |
||
11 | 11 | * Elasticsearch B.V licenses this file to you under the MIT License. |
12 | 12 | * See the LICENSE file in the project root for more information. |
13 | 13 | */ |
14 | -declare (strict_types=1); |
|
14 | +declare(strict_types=1); |
|
15 | 15 | namespace OCA\FullTextSearch_Elasticsearch\Vendor\Elastic\Transport; |
16 | 16 | |
17 | 17 | use OCA\FullTextSearch_Elasticsearch\Vendor\Elastic\Transport\Exception\InvalidArgumentException; |
@@ -81,7 +81,7 @@ discard block |
||
81 | 81 | // Convert the patterns array into a regex |
82 | 82 | $regex = \sprintf('/%s/', \implode('|', $patterns)); |
83 | 83 | // Recursively traverse the array and redact the specified keys |
84 | - \array_walk_recursive($json, function (&$value, $key) use($regex) { |
|
84 | + \array_walk_recursive($json, function(&$value, $key) use($regex) { |
|
85 | 85 | if (\preg_match($regex, $key, $matches)) { |
86 | 86 | $value = self::REDACTED_STRING; |
87 | 87 | } |
@@ -18,8 +18,7 @@ |
||
18 | 18 | use OCA\FullTextSearch_Elasticsearch\Vendor\Elastic\Transport\Serializer\JsonSerializer; |
19 | 19 | use OCA\FullTextSearch_Elasticsearch\Vendor\OpenTelemetry\API\Trace\TracerInterface; |
20 | 20 | use OCA\FullTextSearch_Elasticsearch\Vendor\OpenTelemetry\API\Trace\TracerProviderInterface; |
21 | -class OpenTelemetry |
|
22 | -{ |
|
21 | +class OpenTelemetry { |
|
23 | 22 | const OTEL_TRACER_NAME = 'elasticsearch-api'; |
24 | 23 | const PSR7_OTEL_ATTRIBUTE_NAME = 'otel-elastic-transport'; |
25 | 24 | // Valid values for the enabled config are 'true' and 'false' |