mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Implement OPTIONS requests for NCNv1; fixes #107
This commit is contained in:
parent
e1f1c8b859
commit
3d958547a5
4 changed files with 72 additions and 15 deletions
|
@ -76,6 +76,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if (!Arsse::$user->authHTTP()) {
|
||||
return new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.self::REALM.'"']);
|
||||
}
|
||||
// handle HTTP OPTIONS requests
|
||||
if ($req->method=="OPTIONS") {
|
||||
return $this->handleHTTPOptions($req->paths);
|
||||
}
|
||||
// normalize the input
|
||||
if ($req->body) {
|
||||
// if the entity body is not JSON according to content type, return "415 Unsupported Media Type"
|
||||
|
@ -144,7 +148,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
throw new Exception405(implode(", ", array_keys($this->paths[$url])));
|
||||
}
|
||||
} else {
|
||||
// if the path is not supported, return 501
|
||||
// if the path is not supported, return 404
|
||||
throw new Exception404();
|
||||
}
|
||||
}
|
||||
|
@ -203,6 +207,26 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return $article;
|
||||
}
|
||||
|
||||
protected function handleHTTPOptions(array $url): Response {
|
||||
// normalize the URL path
|
||||
$url = $this->normalizePath($url);
|
||||
if (isset($this->paths[$url])) {
|
||||
// if the path is supported, respond with the allowed methods and other metadata
|
||||
$allowed = array_keys($this->paths[$url]);
|
||||
// if GET is allowed, so is HEAD
|
||||
if (in_array("GET", $allowed)) {
|
||||
array_unshift($allowed, "HEAD");
|
||||
}
|
||||
return new Response(204, "", "", [
|
||||
"Allow: ".implode(",", $allowed),
|
||||
"Accept: application/json",
|
||||
]);
|
||||
} else {
|
||||
// if the path is not supported, return 404
|
||||
return new Response(404);
|
||||
}
|
||||
}
|
||||
|
||||
// list folders
|
||||
protected function folderList(array $url, array $data): Response {
|
||||
$folders = Arsse::$db->folderList(Arsse::$user->id, null, false)->getAll();
|
||||
|
|
|
@ -13,21 +13,23 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
|||
}
|
||||
|
||||
public function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
||||
if (!preg_match("<^/?$>", $req->path)) {
|
||||
// if the request path is an empty string or just a slash, the client is probably trying a version we don't support
|
||||
return new Response(404);
|
||||
} elseif ($req->method=="OPTIONS") {
|
||||
// if the request method is OPTIONS, respond accordingly
|
||||
return new Response(204, "", "", ["Allow: HEAD,GET"]);
|
||||
} elseif ($req->method != "GET") {
|
||||
// if a method other than GET was used, this is an error
|
||||
if ($req->method != "GET") {
|
||||
return new Response(405, "", "", ["Allow: GET"]);
|
||||
}
|
||||
if (preg_match("<^/?$>", $req->path)) {
|
||||
// if the request path is an empty string or just a slash, return the supported versions
|
||||
return new Response(405, "", "", ["Allow: HEAD,GET"]);
|
||||
} else {
|
||||
// otherwise return the supported versions
|
||||
$out = [
|
||||
'apiLevels' => [
|
||||
'v1-2',
|
||||
]
|
||||
];
|
||||
return new Response(200, $out);
|
||||
} else {
|
||||
// if the URL path was anything else, the client is probably trying a version we don't support
|
||||
return new Response(404);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -311,6 +311,12 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
|||
$this->clearData();
|
||||
}
|
||||
|
||||
public function testSendAuthenticationChallenge() {
|
||||
Phake::when(Arsse::$user)->authHTTP->thenReturn(false);
|
||||
$exp = new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.REST\NextCloudNews\V1_2::REALM.'"']);
|
||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/")));
|
||||
}
|
||||
|
||||
public function testRespondToInvalidPaths() {
|
||||
$errs = [
|
||||
404 => [
|
||||
|
@ -364,10 +370,24 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
|||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '<data/>', 'application/json')));
|
||||
}
|
||||
|
||||
public function testSendAuthenticationChallenge() {
|
||||
Phake::when(Arsse::$user)->authHTTP->thenReturn(false);
|
||||
$exp = new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.REST\NextCloudNews\V1_2::REALM.'"']);
|
||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/")));
|
||||
public function testRespondToOptionsRequests() {
|
||||
$exp = new Response(204, "", "", [
|
||||
"Allow: HEAD,GET,POST",
|
||||
"Accept: application/json",
|
||||
]);
|
||||
$this->assertEquals($exp, $this->h->dispatch(new Request("OPTIONS", "/feeds")));
|
||||
$exp = new Response(204, "", "", [
|
||||
"Allow: DELETE",
|
||||
"Accept: application/json",
|
||||
]);
|
||||
$this->assertEquals($exp, $this->h->dispatch(new Request("OPTIONS", "/feeds/2112")));
|
||||
$exp = new Response(204, "", "", [
|
||||
"Allow: HEAD,GET",
|
||||
"Accept: application/json",
|
||||
]);
|
||||
$this->assertEquals($exp, $this->h->dispatch(new Request("OPTIONS", "/user")));
|
||||
$exp = new Response(404);
|
||||
$this->assertEquals($exp, $this->h->dispatch(new Request("OPTIONS", "/invalid/path")));
|
||||
}
|
||||
|
||||
public function testListFolders() {
|
||||
|
|
|
@ -29,8 +29,16 @@ class TestNCNVersionDiscovery extends Test\AbstractTest {
|
|||
$this->assertEquals($exp, $res);
|
||||
}
|
||||
|
||||
public function testRespondToOptionsRequest() {
|
||||
$exp = new Response(204, "", "", ["Allow: HEAD,GET"]);
|
||||
$h = new REST\NextCloudNews\Versions();
|
||||
$req = new Request("OPTIONS", "/");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertEquals($exp, $res);
|
||||
}
|
||||
|
||||
public function testUseIncorrectMethod() {
|
||||
$exp = new Response(405, "", "", ["Allow: GET"]);
|
||||
$exp = new Response(405, "", "", ["Allow: HEAD,GET"]);
|
||||
$h = new REST\NextCloudNews\Versions();
|
||||
$req = new Request("POST", "/");
|
||||
$res = $h->dispatch($req);
|
||||
|
@ -43,5 +51,8 @@ class TestNCNVersionDiscovery extends Test\AbstractTest {
|
|||
$req = new Request("GET", "/ook");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertEquals($exp, $res);
|
||||
$req = new Request("OPTIONS", "/ook");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertEquals($exp, $res);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue