public function getObjectSecurelyAsync()

in src/EncryptionClient.php [312:403]


    public function getObjectSecurelyAsync(Models\GetObjectRequest $request, array $args = []): GuzzleHttp\Promise\Promise
    {
        $rangeHeader = null;
        $discardCount = 0;
        $adjustOffset = 0;
        if ($request->rangeHeader != null) {
            $ranges = Utils::parseHttpRange($request->rangeHeader);
            if ($ranges === false) {
                throw new \InvalidArgumentException("request.rangeHeader is invalid, got $request->rangeHeader");
            }
            $start = $ranges[0] < 0 ? 0 : $ranges[0];
            $adjustOffset = $this->adjustRangeStart($start);
            $discardCount = $start - $adjustOffset;
            if ($discardCount > 0) {
                // bytes=0-1023 or bytes=0-
                $rangeHeader = sprintf('bytes=%d-', $adjustOffset);
                if ($ranges[1] >= 0) {
                    $rangeHeader .= strval($ranges[1]);
                }
            }
        }

        $eRequest = $request;
        if ($rangeHeader != null) {
            $eRequest = clone $request;
            $eRequest->rangeHeader = $rangeHeader;
            $eRequest->rangeBehavior = 'standard';
        }

        // stream mode
        if (
            isset($args['request_options']) &&
            isset($args['request_options']['stream']) &&
            $args['request_options']['stream'] === true
        ) {
            /**
             * @var Crypto\ContentCipherInterface $contentCipher
             */
            $contentCipher = null;
            $args['request_options'] = array_merge($args['request_options'], [
                'on_headers' => function ($response) use (&$contentCipher) {
                    $contentCipher = $this->contentCipherfromHeaders($response);
                }
            ]);
            return $this->client->getObjectAsync($eRequest, $args)->then(
                function (Models\GetObjectResult $result) use (&$adjustOffset, &$discardCount, &$contentCipher) {
                    $body = $result->body;
                    if ($contentCipher !== null) {
                        $cipher = $contentCipher->getCipher($adjustOffset);
                        $body = new Crypto\ReadDecryptStream($body, $cipher);
                    }
                    if ($discardCount > 0) {
                        $body->read($discardCount);
                    }
                    $result = $this->adjustGetObjectResult($result, $discardCount);
                    $result->body = $body;
                    return $result;
                }
            );
        }

        // non stream mode, and save into
        $sink = null;
        if (isset($args['request_options']) && isset($args['request_options']['sink'])) {
            $sink = $args['request_options']['sink'];
        }
        $fromFilepath = \is_string($sink);
        $stream = $fromFilepath ?
            new GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+') : Utils::streamFor($sink);

        $esink = new Crypto\LazyDecryptStream(
            $stream,
            $discardCount,
            function ($response) {
                return $this->contentCipherfromHeaders($response);
            }
        );

        $args['request_options'] = array_merge($args['request_options'] ?? [], [
            'sink' => $esink
        ]);
        return $this->client->getObjectAsync($eRequest, $args)->then(
            function (Models\GetObjectResult $result) use (&$discardCount, &$fromFilepath) {
                $result = $this->adjustGetObjectResult($result, $discardCount);
                // unwrap stream from LazyDecryptStream
                if ($result->body instanceof Crypto\LazyDecryptStream) {
                    $result->body = $fromFilepath ? null : $result->body->unwrap();
                }
                return $result;
            }
        );
    }