public function __invoke()

in src/EndpointDiscovery/EndpointDiscoveryMiddleware.php [62:172]


    public function __invoke(CommandInterface $cmd, RequestInterface $request)
    {
        $nextHandler = $this->nextHandler;
        $op = $this->service->getOperation($cmd->getName())->toArray();

        // Continue only if endpointdiscovery trait is set
        if (isset($op['endpointdiscovery'])) {
            $config = ConfigurationProvider::unwrap($this->config);
            $isRequired = !empty($op['endpointdiscovery']['required']);

            if ($isRequired && !($config->isEnabled())) {
                throw new UnresolvedEndpointException('This operation '
                    . 'requires the use of endpoint discovery, but this has '
                    . 'been disabled in the configuration. Enable endpoint '
                    . 'discovery or use a different operation.');
            }

            // Continue only if enabled by config
            if ($config->isEnabled()) {
                if (isset($op['endpointoperation'])) {
                    throw new UnresolvedEndpointException('This operation is '
                        . 'contradictorily marked both as using endpoint discovery '
                        . 'and being the endpoint discovery operation. Please '
                        . 'verify the accuracy of your model files.');
                }

                // Original endpoint may be used if discovery optional
                $originalUri = $request->getUri();

                $identifiers = $this->getIdentifiers($op);

                $cacheKey = $this->getCacheKey(
                    $this->client->getCredentials()->wait(),
                    $cmd,
                    $identifiers
                );

                // Check/create cache
                if (!isset(self::$cache)) {
                    self::$cache = new LruArrayCache($config->getCacheLimit());
                }

                if (empty($endpointList = self::$cache->get($cacheKey))) {
                    $endpointList = new EndpointList([]);
                }
                $endpoint = $endpointList->getActive();

                // Retrieve endpoints if there is no active endpoint
                if (empty($endpoint)) {
                    try {
                        $endpoint = $this->discoverEndpoint(
                            $cacheKey,
                            $cmd,
                            $identifiers
                        );
                    } catch (\Exception $e) {
                        // Use cached endpoint, expired or active, if any remain
                        $endpoint = $endpointList->getEndpoint();

                        if (empty($endpoint)) {
                            return $this->handleDiscoveryException(
                                $isRequired,
                                $originalUri,
                                $e,
                                $cmd,
                                $request
                            );
                        }
                    }
                }

                $request = $this->modifyRequest($request, $endpoint);

                $g = function ($value) use (
                    $cacheKey,
                    $cmd,
                    $identifiers,
                    $isRequired,
                    $originalUri,
                    $request,
                    &$endpoint,
                    &$g
                ) {
                    if ($value instanceof AwsException
                        && (
                            $value->getAwsErrorCode() == 'InvalidEndpointException'
                            || $value->getStatusCode() == 421
                        )
                    ) {
                        return $this->handleInvalidEndpoint(
                            $cacheKey,
                            $cmd,
                            $identifiers,
                            $isRequired,
                            $originalUri,
                            $request,
                            $value,
                            $endpoint,
                            $g
                        );
                    }
                    
                    return $value;
                };

                return $nextHandler($cmd, $request)->otherwise($g);
            }
        }

        return $nextHandler($cmd, $request);
    }