Skip to content

Commit f2262d2

Browse files
committed
Add HTTP Link header with the rel parameter for auxiliary resources.
1 parent 779da6d commit f2262d2

1 file changed

Lines changed: 80 additions & 1 deletion

File tree

src/Server.php

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use EasyRdf_Graph as Graph;
77
use Laminas\Diactoros\ServerRequest;
88
use League\Flysystem\FileExistsException;
9+
use League\Flysystem\FileNotFoundException;
910
use League\Flysystem\FilesystemInterface as Filesystem;
1011
use Psr\Http\Message\ResponseInterface as Response;
1112
use Psr\Http\Message\ServerRequestInterface as Request;
@@ -550,8 +551,10 @@ private function handleReadRequest(Response $response, string $path, $contents,
550551
$response = $response->withStatus(200);
551552
} else {
552553
if ($filesystem->asMime($mime)->has($path)) {
553-
$mimetype = $filesystem->asMime($mime)->getMimetype($path);
554554
$contents = $filesystem->asMime($mime)->read($path);
555+
556+
$response = $this->addLinkRelationHeaders($response, $path, $mime);
557+
555558
if (preg_match('/.ttl$/', $path)) {
556559
$mimetype = "text/turtle"; // FIXME: teach flysystem that .ttl means text/turtle
557560
} elseif (preg_match('/.acl$/', $path)) {
@@ -655,4 +658,80 @@ private function listDirectoryAsTurtle($path)
655658

656659
return $container;
657660
}
661+
662+
// =========================================================================
663+
// @TODO: All Auxiliary Resources logic should probably be moved to a separate class.
664+
665+
/**
666+
* Currently, in the spec channel, it is under consideration to use
667+
* <http://www.w3.org/ns/auth/acl#accessControl> or <http://www.w3.org/ns/solid/terms#acl>
668+
* instead of (or besides) "acl" and <https://www.w3.org/ns/iana/link-relations/relation#describedby>
669+
* instead of (or besides) "describedby".
670+
*
671+
* @see https://github.com/solid/specification/issues/172
672+
*/
673+
private function addLinkRelationHeaders(Response $response, string $path, $mime=null): Response
674+
{
675+
// @FIXME: If a `.meta` file is requested, it must have header `Link: </path/to/resource>; rel="describes"`
676+
677+
if ($this->hasAcl($path, $mime)) {
678+
$value = sprintf('<%s>; rel="acl"', $this->getDescribedByPath($path, $mime));
679+
$response = $response->withAddedHeader('Link', $value);
680+
}
681+
682+
if ($this->hasDescribedBy($path, $mime)) {
683+
$value = sprintf('<%s>; rel="describedby"', $this->getDescribedByPath($path, $mime));
684+
$response = $response->withAddedHeader('Link', $value);
685+
}
686+
687+
return $response;
688+
}
689+
690+
private function getAclPath(string $path, $mime = null): string
691+
{
692+
$metadataCache = $this->getMetadata($path, $mime);
693+
694+
return $metadataCache[$path]['acl'] ?? '';
695+
}
696+
697+
private function getDescribedByPath(string $path, $mime = null): string
698+
{
699+
$metadataCache = $this->getMetadata($path, $mime);
700+
701+
return $metadataCache[$path]['describedby'] ?? '';
702+
}
703+
704+
private function getMetadata(string $path, $mime) : array
705+
{
706+
// @NOTE: Because the lookup can be expensive, we cache the result
707+
static $metadataCache = [];
708+
709+
if (isset($metadataCache[$path]) === false) {
710+
$filesystem = $this->filesystem;
711+
712+
try {
713+
if ($mime) {
714+
$metadata = $filesystem->asMime($mime)->getMetadata($path);
715+
} else {
716+
$metadata = $filesystem->getMetadata($path);
717+
}
718+
} catch (FileNotFoundException $e) {
719+
$metadata = [];
720+
}
721+
722+
$metadataCache[$path . $mime] = $metadata;
723+
}
724+
725+
return $metadataCache;
726+
}
727+
728+
private function hasAcl(string $path, $mime = null): bool
729+
{
730+
return $this->getAclPath($path, $mime) !== '';
731+
}
732+
733+
private function hasDescribedBy(string $path, $mime = null): bool
734+
{
735+
return $this->getDescribedByPath($path, $mime) !== '';
736+
}
658737
}

0 commit comments

Comments
 (0)