environment() === 'production') { $bannedInstances = InstanceService::getBannedDomains(); if (in_array($host, $bannedInstances)) { return false; } } return $url; } public static function fetchRequest($url, $returnJsonFormat = false) { $baseHeaders = [ 'Accept' => 'application/activity+json', ]; $headers = HttpSignature::instanceActorSign($url, false, $baseHeaders, 'get'); $headers['Accept'] = 'application/activity+json'; $headers['User-Agent'] = 'PixelFedBot/1.0.0 (Pixelfed/'.config('pixelfed.version').'; +'.config('app.url').')'; try { $res = Http::withOptions([ 'allow_redirects' => [ 'max' => 2, 'protocols' => ['https'], ]]) ->withHeaders($headers) ->timeout(30) ->connectTimeout(5) ->retry(3, 500) ->get($url); } catch (RequestException $e) { return; } catch (ConnectionException $e) { return; } catch (\Exception $e) { return; } if (! $res->ok()) { return; } if (! $res->hasHeader('Content-Type')) { return; } $contentType = $res->getHeader('Content-Type')[0]; if (! $contentType) { return; } // Parse Content-Type: extract media type (case-insensitive) and parameters $contentTypeParts = array_map('trim', explode(';', $contentType)); $mediaType = strtolower($contentTypeParts[0]); $acceptedMediaTypes = [ 'application/activity+json', 'application/ld+json', ]; if (! in_array($mediaType, $acceptedMediaTypes)) { return; } //// For application/ld+json, verify the ActivityStreams profile parameter if ($mediaType === 'application/ld+json') { $hasActivityStreamsProfile = false; foreach (array_slice($contentTypeParts, 1) as $param) { $param = trim($param); if (stripos($param, 'profile=') === 0) { $profile = trim(substr($param, strlen('profile=')), ' "\''); if ($profile === 'https://www.w3.org/ns/activitystreams') { $hasActivityStreamsProfile = true; break; } } } if (! $hasActivityStreamsProfile) { return; } } return $returnJsonFormat ? $res->json() : $res->body(); } }