Browse Source

Relax Fever's HTTP correctness for client compat

- Unread on iOS appears to send all API requests as GETs
- Newsflash on Linux sends multipart/form-data input
rpm
J. King 3 years ago
parent
commit
0117e7f9bf
  1. 9
      lib/REST/Fever/API.php
  2. 10
      tests/cases/REST/Fever/TestAPI.php

9
lib/REST/Fever/API.php

@ -22,7 +22,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
public const LEVEL = 3;
protected const GENERIC_ICON_TYPE = "image/png;base64";
protected const GENERIC_ICON_DATA = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2NgYGBgAAAABQABijPjAAAAAABJRU5ErkJggg==";
protected const ACCEPTED_TYPE = "application/x-www-form-urlencoded";
protected const ACCEPTED_TYPES = ["application/x-www-form-urlencoded", "multipart/form-data"];
// GET parameters for which we only check presence: these will be converted to booleans
protected const PARAM_BOOL = ["groups", "feeds", "items", "favicons", "links", "unread_item_ids", "saved_item_ids"];
@ -68,11 +68,12 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
case "OPTIONS":
return new EmptyResponse(204, [
'Allow' => "POST",
'Accept' => self::ACCEPTED_TYPE,
'Accept' => implode(", ", self::ACCEPTED_TYPES),
]);
case "GET": // HTTP violation required for client "Unread" on iOS
case "POST":
if (!HTTP::matchType($req, self::ACCEPTED_TYPE, "")) {
return new EmptyResponse(415, ['Accept' => self::ACCEPTED_TYPE]);
if (!HTTP::matchType($req, "", ...self::ACCEPTED_TYPES)) {
return new EmptyResponse(415, ['Accept' => implode(", ", self::ACCEPTED_TYPES)]);
}
$out = [
'api_version' => self::LEVEL,

10
tests/cases/REST/Fever/TestAPI.php

@ -427,9 +427,11 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
public function provideInvalidRequests(): iterable {
return [
'Not an API request' => [$this->req(""), new EmptyResponse(404)],
'Wrong method' => [$this->req("api", "", "GET"), new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])],
'Wrong content type' => [$this->req("api", '{"api_key":"validToken"}', "POST", "application/json"), new EmptyResponse(415, ['Accept' => "application/x-www-form-urlencoded"])],
'Not an API request' => [$this->req(""), new EmptyResponse(404)],
'Wrong method' => [$this->req("api", "", "PUT"), new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])],
'Non-standard method' => [$this->req("api", "", "GET"), new JsonResponse([])],
'Wrong content type' => [$this->req("api", '{"api_key":"validToken"}', "POST", "application/json"), new EmptyResponse(415, ['Accept' => "application/x-www-form-urlencoded, multipart/form-data"])],
'Non-standard content type' => [$this->req("api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1"), new JsonResponse([])],
];
}
@ -499,7 +501,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
$act = $this->h->dispatch($this->req("api", "", "OPTIONS"));
$exp = new EmptyResponse(204, [
'Allow' => "POST",
'Accept' => "application/x-www-form-urlencoded",
'Accept' => "application/x-www-form-urlencoded, multipart/form-data",
]);
$this->assertMessage($exp, $act);
}

Loading…
Cancel
Save