misuzu/src/WebFinger/WebFingerRoutes.php
2025-02-26 22:03:13 +00:00

115 lines
3.7 KiB
PHP

<?php
namespace Misuzu\WebFinger;
use Index\XArray;
use Index\Http\{HttpResponseBuilder,HttpRequest};
use Index\Http\Routing\{HttpGet,HttpOptions,RouteHandler,RouteHandlerCommon};
class WebFingerRoutes implements RouteHandler {
use RouteHandlerCommon;
public function __construct(
private WebFingerRegistry $registry
) {}
/**
* @param WebFingerProperty[] $propInfos
* @return array<string, ?string>
*/
private static function extractProps(array $propInfos): array {
$props = [];
foreach($propInfos as $propInfo)
$props[$propInfo->name] = $propInfo->value;
return $props;
}
/**
* @param WebFingerTitle[] $titleInfos
* @return array<string, string>
*/
private static function extractTitles(array $titleInfos): array {
$titles = [];
foreach($titleInfos as $titleInfo)
$titles[$titleInfo->lang] = $titleInfo->value;
return $titles;
}
/**
* @param WebFingerLink[] $linkInfos
* @return array{rel: string, type?: string, href?: string, titles?: array<string, string>, properties?: array<string, ?string>}[]
*/
private static function extractLinks(array $linkInfos): array {
$links = [];
foreach($linkInfos as $linkInfo) {
$link = ['rel' => $linkInfo->relation];
if($linkInfo->type !== null)
$link['type'] = $linkInfo->type;
if($linkInfo->href !== null)
$link['href'] = $linkInfo->href;
if(!empty($linkInfo->titles))
$link['titles'] = self::extractTitles($linkInfo->titles);
if(!empty($linkInfo->properties))
$link['properties'] = self::extractProps($linkInfo->properties);
$links[] = $link;
}
return $links;
}
/**
* @return int|array{
* subject?: string,
* aliases?: string[],
* properties?: array<string, ?string>,
* links?: array{
* rel: string,
* type?: string,
* href?: string,
* titles?: array<string, string>,
* properties?: array<string, ?string>
* }[]
* }
*/
#[HttpOptions('/.well-known/webfinger')]
#[HttpGet('/.well-known/webfinger')]
public function getWebFinger(HttpResponseBuilder $response, HttpRequest $request): array|int {
$response->setHeader('Access-Control-Allow-Origin', '*');
if($request->method === 'OPTIONS')
return 204;
$resInfos = $this->registry->resolve(trim((string)$request->getParam('resource')));
if(empty($resInfos))
return 404;
$subject = null;
$aliases = [];
$properties = [];
$links = [];
foreach($resInfos as $resInfo) {
if($resInfo->subject !== null && $subject === null)
$subject = $resInfo->subject;
if(!empty($resInfo->aliases))
$aliases = array_unique(array_merge($aliases, $resInfo->aliases));
if(!empty($resInfo->properties))
$properties = array_merge($properties, self::extractProps($resInfo->properties));
if(!empty($resInfo->links))
$links = array_merge($links, self::extractLinks($resInfo->links));
}
$result = [];
if($subject !== null)
$result['subject'] = $subject;
if(!empty($aliases))
$result['aliases'] = $aliases;
if(!empty($properties))
$result['properties'] = $properties;
if(!empty($links))
$result['links'] = $links;
if(empty($result))
return 404;
$response->setContentType('application/jrd+json');
return $result;
}
}