cache = $cacheFactory->createDistributed('ocm-discovery'); } /** * @param string $remote * @param bool $skipCache * * @return IOCMProvider * @throws OCMProviderException */ public function discover(string $remote, bool $skipCache = false): IOCMProvider { $remote = rtrim($remote, '/'); if (!$skipCache) { try { $cached = $this->cache->get($remote); if ($cached === false) { throw new OCMProviderException('Previous discovery failed.'); } $this->provider->import(json_decode($cached ?? '', true, 8, JSON_THROW_ON_ERROR) ?? []); if ($this->supportedAPIVersion($this->provider->getApiVersion())) { return $this->provider; // if cache looks valid, we use it } } catch (JsonException|OCMProviderException $e) { // we ignore cache on issues } } $client = $this->clientService->newClient(); try { $options = [ 'timeout' => 10, 'connect_timeout' => 10, ]; if ($this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates') === true) { $options['verify'] = false; } $response = $client->get( $remote . '/ocm-provider/', $options, ); if ($response->getStatusCode() === Http::STATUS_OK) { $body = $response->getBody(); // update provider with data returned by the request $this->provider->import(json_decode($body, true, 8, JSON_THROW_ON_ERROR) ?? []); $this->cache->set($remote, $body, 60 * 60 * 24); } } catch (JsonException|OCMProviderException $e) { $this->cache->set($remote, false, 5 * 60); throw new OCMProviderException('data returned by remote seems invalid - ' . ($body ?? '')); } catch (\Exception $e) { $this->cache->set($remote, false, 5 * 60); $this->logger->warning('error while discovering ocm provider', [ 'exception' => $e, 'remote' => $remote ]); throw new OCMProviderException('error while requesting remote ocm provider'); } if (!$this->supportedAPIVersion($this->provider->getApiVersion())) { $this->cache->set($remote, false, 5 * 60); throw new OCMProviderException('API version not supported'); } return $this->provider; } /** * Check the version from remote is supported. * The minor version of the API will be ignored: * 1.0.1 is identified as 1.0 * * @param string $version * * @return bool */ private function supportedAPIVersion(string $version): bool { $dot1 = strpos($version, '.'); $dot2 = strpos($version, '.', $dot1 + 1); if ($dot2 > 0) { $version = substr($version, 0, $dot2); } return (in_array($version, $this->supportedAPIVersion)); } }