1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 21:22:40 +00:00

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
This commit is contained in:
J. King 2020-10-27 10:49:54 -04:00
parent 7ef02e1d65
commit 0117e7f9bf
2 changed files with 11 additions and 8 deletions

View file

@ -22,7 +22,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
public const LEVEL = 3; public const LEVEL = 3;
protected const GENERIC_ICON_TYPE = "image/png;base64"; protected const GENERIC_ICON_TYPE = "image/png;base64";
protected const GENERIC_ICON_DATA = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2NgYGBgAAAABQABijPjAAAAAABJRU5ErkJggg=="; 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 // 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"]; 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": case "OPTIONS":
return new EmptyResponse(204, [ return new EmptyResponse(204, [
'Allow' => "POST", 'Allow' => "POST",
'Accept' => self::ACCEPTED_TYPE, 'Accept' => implode(", ", self::ACCEPTED_TYPES),
]); ]);
case "GET": // HTTP violation required for client "Unread" on iOS
case "POST": case "POST":
if (!HTTP::matchType($req, self::ACCEPTED_TYPE, "")) { if (!HTTP::matchType($req, "", ...self::ACCEPTED_TYPES)) {
return new EmptyResponse(415, ['Accept' => self::ACCEPTED_TYPE]); return new EmptyResponse(415, ['Accept' => implode(", ", self::ACCEPTED_TYPES)]);
} }
$out = [ $out = [
'api_version' => self::LEVEL, 'api_version' => self::LEVEL,

View file

@ -428,8 +428,10 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
public function provideInvalidRequests(): iterable { public function provideInvalidRequests(): iterable {
return [ return [
'Not an API request' => [$this->req(""), new EmptyResponse(404)], 'Not an API request' => [$this->req(""), new EmptyResponse(404)],
'Wrong method' => [$this->req("api", "", "GET"), new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])], 'Wrong method' => [$this->req("api", "", "PUT"), 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"])], '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")); $act = $this->h->dispatch($this->req("api", "", "OPTIONS"));
$exp = new EmptyResponse(204, [ $exp = new EmptyResponse(204, [
'Allow' => "POST", 'Allow' => "POST",
'Accept' => "application/x-www-form-urlencoded", 'Accept' => "application/x-www-form-urlencoded, multipart/form-data",
]); ]);
$this->assertMessage($exp, $act); $this->assertMessage($exp, $act);
} }