[CORE][Router] Properly act on Accept headers

This commit is contained in:
Diogo Peralta Cordeiro 2021-10-19 23:46:01 +01:00
parent 99fd2f725b
commit 028ea79fff
No known key found for this signature in database
GPG Key ID: 18D2D35001FBFAB0
3 changed files with 18 additions and 46 deletions

View File

@ -39,6 +39,12 @@ class ActivityPub extends Plugin
*/
public function onAddRoute(RouteLoader $r): bool
{
$r->connect(
'activitypub_inbox',
'/inbox.json',
[Inbox::class, 'handle'],
options: ['accept' => self::$accept_headers, 'format' => self::$accept_headers[0]]
);
$r->connect(
'activitypub_actor_inbox',
'/actor/{gsactor_id<\d+>}/inbox.json',
@ -51,48 +57,9 @@ class ActivityPub extends Plugin
[Inbox::class, 'handle'],
options: ['accept' => self::$accept_headers, 'format' => self::$accept_headers[0]]
);
$r->connect(
'activitypub_inbox',
'/inbox.json',
[Inbox::class, 'handle'],
options: ['accept' => self::$accept_headers, 'format' => self::$accept_headers[0]]
);
return Event::next;
}
/**
* Validate HTTP Accept headers
*
* @param bool $strict Strict mode
*
* @throws Exception when strict mode enabled
*/
public static function validateAcceptHeader(array|string|null $accept, bool $strict): bool
{
if (\is_string($accept)
&& \in_array($accept, self::$accept_headers)
) {
return true;
} elseif (\is_array($accept)
&& \count(
array_intersect($accept, self::$accept_headers),
) > 0
) {
return true;
}
if (!$strict) {
return false;
}
throw new Exception(
sprintf(
"HTTP Accept header error. Given: '%s'",
$accept,
),
);
}
/**
* @throws Exception
*/

View File

@ -47,12 +47,6 @@ class Inbox extends Controller
}
}
// Check accept header
ActivityPub::validateAcceptHeader(
$this->request->headers->get('accept'),
true,
);
// TODO: Check if Actor can post
// Get content

View File

@ -100,6 +100,17 @@ class RouteLoader extends Loader
*/
public function connect(string $id, string $uri_path, $target, ?array $options = [], ?array $param_reqs = [])
{
// XXX: This hack can definitely be optimised by actually intersecting the arrays,
// maybe this helps: https://backbeat.tech/blog/symfony-routing-tricks-part-1
// see: https://symfony.com/index.php/doc/3.1/components/http_foundation.html#accessing-accept-headers-data
if (isset($options['accept'])) {
$accept_header_condition = '';
foreach ($options['accept'] as $accept) {
$accept_header_condition .= "('$accept' in request.getAcceptableContentTypes()) ||";
}
$accept_header_condition = substr($accept_header_condition, 0, -3);
}
$this->rc->add(
$id,
new Route(
@ -134,7 +145,7 @@ class RouteLoader extends Loader
methods: $options['http-methods'] ?? $options['methods'] ?? [],
// condition = '' -- Symfony condition expression,
// see https://symfony.com/doc/current/routing.html#matching-expressions
condition: isset($options['accept']) ? "request.headers.get('Accept') in " . json_encode($options['accept']) : ($options['condition'] ?? ''),
condition: isset($options['accept']) ? $accept_header_condition : ($options['condition'] ?? ''),
),
);
}