diff options
Diffstat (limited to 'vendor/open-telemetry/api/Baggage/Propagation')
-rw-r--r-- | vendor/open-telemetry/api/Baggage/Propagation/BaggagePropagator.php | 92 | ||||
-rw-r--r-- | vendor/open-telemetry/api/Baggage/Propagation/Parser.php | 69 |
2 files changed, 161 insertions, 0 deletions
diff --git a/vendor/open-telemetry/api/Baggage/Propagation/BaggagePropagator.php b/vendor/open-telemetry/api/Baggage/Propagation/BaggagePropagator.php new file mode 100644 index 000000000..fae62dcab --- /dev/null +++ b/vendor/open-telemetry/api/Baggage/Propagation/BaggagePropagator.php @@ -0,0 +1,92 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\API\Baggage\Propagation; + +use OpenTelemetry\API\Baggage\Baggage; +use OpenTelemetry\API\Baggage\BaggageBuilderInterface; +use OpenTelemetry\API\Baggage\Entry; /** @phan-suppress-current-line PhanUnreferencedUseNormal */ +use OpenTelemetry\Context\Context; +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter; +use OpenTelemetry\Context\Propagation\PropagationGetterInterface; +use OpenTelemetry\Context\Propagation\PropagationSetterInterface; +use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface; +use function rtrim; +use function urlencode; + +/** + * @see https://www.w3.org/TR/baggage + */ +final class BaggagePropagator implements TextMapPropagatorInterface +{ + public const BAGGAGE = 'baggage'; + + private static ?self $instance = null; + + public static function getInstance(): self + { + if (null === self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } + + public function fields(): array + { + return [self::BAGGAGE]; + } + + public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void + { + $setter ??= ArrayAccessGetterSetter::getInstance(); + $context ??= Context::getCurrent(); + + $baggage = Baggage::fromContext($context); + + if ($baggage->isEmpty()) { + return; + } + + $headerString = ''; + + /** @var Entry $entry */ + foreach ($baggage->getAll() as $key => $entry) { + $value = urlencode($entry->getValue()); + $headerString.= "{$key}={$value}"; + + if (($metadata = $entry->getMetadata()->getValue()) !== '' && ($metadata = $entry->getMetadata()->getValue()) !== '0') { + $headerString .= ";{$metadata}"; + } + + $headerString .= ','; + } + + if ($headerString !== '' && $headerString !== '0') { + $headerString = rtrim($headerString, ','); + $setter->set($carrier, self::BAGGAGE, $headerString); + } + } + + public function extract($carrier, PropagationGetterInterface $getter = null, ContextInterface $context = null): ContextInterface + { + $getter ??= ArrayAccessGetterSetter::getInstance(); + $context ??= Context::getCurrent(); + + if (!$baggageHeader = $getter->get($carrier, self::BAGGAGE)) { + return $context; + } + + $baggageBuilder = Baggage::getBuilder(); + $this->extractValue($baggageHeader, $baggageBuilder); + + return $context->withContextValue($baggageBuilder->build()); + } + + private function extractValue(string $baggageHeader, BaggageBuilderInterface $baggageBuilder): void + { + (new Parser($baggageHeader))->parseInto($baggageBuilder); + } +} diff --git a/vendor/open-telemetry/api/Baggage/Propagation/Parser.php b/vendor/open-telemetry/api/Baggage/Propagation/Parser.php new file mode 100644 index 000000000..3518b858d --- /dev/null +++ b/vendor/open-telemetry/api/Baggage/Propagation/Parser.php @@ -0,0 +1,69 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\API\Baggage\Propagation; + +use function explode; +use OpenTelemetry\API\Baggage\BaggageBuilderInterface; +use OpenTelemetry\API\Baggage\Metadata; +use function str_replace; +use function trim; +use function urldecode; + +final class Parser +{ + private const EXCLUDED_KEY_CHARS = [' ', '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}']; + private const EXCLUDED_VALUE_CHARS = [' ', '"', ',', ';', '\\']; + private const EQUALS = '='; + + /** @readonly */ + private string $baggageHeader; + + public function __construct(string $baggageHeader) + { + $this->baggageHeader = $baggageHeader; + } + + public function parseInto(BaggageBuilderInterface $baggageBuilder): void + { + foreach (explode(',', $this->baggageHeader) as $baggageString) { + if (empty(trim($baggageString))) { + continue; + } + + $explodedString = explode(';', $baggageString, 2); + + $keyValue = trim($explodedString[0]); + + if (empty($keyValue) || mb_strpos($keyValue, self::EQUALS) === false) { + continue; + } + + $metadataString = $explodedString[1] ?? null; + + if ($metadataString && !empty(trim(($metadataString)))) { + $metadata = new Metadata(trim($metadataString)); + } else { + $metadata = null; + } + + [$key, $value] = explode(self::EQUALS, $keyValue, 2); + + $key = urldecode($key); + $value = urldecode($value); + + $key = str_replace(self::EXCLUDED_KEY_CHARS, '', trim($key), $invalidKeyCharacters); + if (empty($key) || $invalidKeyCharacters > 0) { + continue; + } + + $value = str_replace(self::EXCLUDED_VALUE_CHARS, '', trim($value), $invalidValueCharacters); + if (empty($value) || $invalidValueCharacters > 0) { + continue; + } + + $baggageBuilder->set($key, $value, $metadata); + } + } +} |