mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Replace instances of Diactoros' EmptyResponse
This commit is contained in:
parent
560d4db139
commit
6c0183faea
16 changed files with 231 additions and 233 deletions
|
@ -7,11 +7,11 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\URL;
|
use JKingWeb\Arsse\Misc\URL;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use Psr\Http\Message\RequestInterface;
|
use Psr\Http\Message\RequestInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\ServerRequestFactory;
|
use Laminas\Diactoros\ServerRequestFactory;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
class REST {
|
class REST {
|
||||||
public const API_LIST = [
|
public const API_LIST = [
|
||||||
|
@ -101,7 +101,7 @@ class REST {
|
||||||
$res = $drv->dispatch($req);
|
$res = $drv->dispatch($req);
|
||||||
}
|
}
|
||||||
} catch (REST\Exception501 $e) {
|
} catch (REST\Exception501 $e) {
|
||||||
$res = new EmptyResponse(501);
|
$res = HTTP::respEmpty(501);
|
||||||
}
|
}
|
||||||
// modify the response so that it has all the required metadata
|
// modify the response so that it has all the required metadata
|
||||||
return $this->normalizeResponse($res, $req);
|
return $this->normalizeResponse($res, $req);
|
||||||
|
@ -180,7 +180,7 @@ class REST {
|
||||||
}
|
}
|
||||||
// if the response is to a HEAD request, the body should be omitted
|
// if the response is to a HEAD request, the body should be omitted
|
||||||
if ($req && $req->getMethod() === "HEAD") {
|
if ($req && $req->getMethod() === "HEAD") {
|
||||||
$res = new EmptyResponse($res->getStatusCode(), $res->getHeaders());
|
$res = HTTP::respEmpty($res->getStatusCode(), $res->getHeaders());
|
||||||
}
|
}
|
||||||
// if an Allow header field is present, normalize it
|
// if an Allow header field is present, normalize it
|
||||||
if ($res->hasHeader("Allow")) {
|
if ($res->hasHeader("Allow")) {
|
||||||
|
|
|
@ -10,13 +10,12 @@ use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Context\Context;
|
use JKingWeb\Arsse\Context\Context;
|
||||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
|
||||||
use JKingWeb\Arsse\Misc\HTTP;
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Laminas\Diactoros\Response\XmlResponse;
|
use Laminas\Diactoros\Response\XmlResponse;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
public const LEVEL = 3;
|
public const LEVEL = 3;
|
||||||
|
@ -62,11 +61,11 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$P = $this->normalizeInputPost($req->getParsedBody() ?? []);
|
$P = $this->normalizeInputPost($req->getParsedBody() ?? []);
|
||||||
if (!isset($G['api'])) {
|
if (!isset($G['api'])) {
|
||||||
// the original would have shown the Fever UI in the absence of the "api" parameter, but we'll return 404
|
// the original would have shown the Fever UI in the absence of the "api" parameter, but we'll return 404
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
switch ($req->getMethod()) {
|
switch ($req->getMethod()) {
|
||||||
case "OPTIONS":
|
case "OPTIONS":
|
||||||
return new EmptyResponse(204, [
|
return HTTP::respEmpty(204, [
|
||||||
'Allow' => "POST",
|
'Allow' => "POST",
|
||||||
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
||||||
]);
|
]);
|
||||||
|
@ -82,7 +81,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$out['auth'] = 1;
|
$out['auth'] = 1;
|
||||||
} elseif (Arsse::$conf->userHTTPAuthRequired || Arsse::$conf->userPreAuth || $req->getAttribute("authenticationFailed", false)) {
|
} elseif (Arsse::$conf->userHTTPAuthRequired || Arsse::$conf->userPreAuth || $req->getAttribute("authenticationFailed", false)) {
|
||||||
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
|
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
|
||||||
return new EmptyResponse(401);
|
return HTTP::respEmpty(401);
|
||||||
}
|
}
|
||||||
// produce a full response if authenticated or a basic response otherwise
|
// produce a full response if authenticated or a basic response otherwise
|
||||||
if ($this->logIn(strtolower($P['api_key'] ?? ""))) {
|
if ($this->logIn(strtolower($P['api_key'] ?? ""))) {
|
||||||
|
@ -93,7 +92,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// return the result, possibly formatted as XML
|
// return the result, possibly formatted as XML
|
||||||
return $this->formatResponse($out, ($G['api'] === "xml"));
|
return $this->formatResponse($out, ($G['api'] === "xml"));
|
||||||
default:
|
default:
|
||||||
return new EmptyResponse(405, ['Allow' => "OPTIONS,POST"]);
|
return HTTP::respEmpty(405, ['Allow' => "OPTIONS,POST"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST\Miniflux;
|
namespace JKingWeb\Arsse\REST\Miniflux;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
use Laminas\Diactoros\Response\TextResponse;
|
use Laminas\Diactoros\Response\TextResponse;
|
||||||
|
|
||||||
class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
|
@ -18,13 +18,13 @@ class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||||
$target = parse_url($req->getRequestTarget())['path'] ?? "";
|
$target = parse_url($req->getRequestTarget())['path'] ?? "";
|
||||||
if (!in_array($target, ["/version", "/healthcheck"])) {
|
if (!in_array($target, ["/version", "/healthcheck"])) {
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
$method = $req->getMethod();
|
$method = $req->getMethod();
|
||||||
if ($method === "OPTIONS") {
|
if ($method === "OPTIONS") {
|
||||||
return new EmptyResponse(204, ['Allow' => "HEAD, GET"]);
|
return HTTP::respEmpty(204, ['Allow' => "HEAD, GET"]);
|
||||||
} elseif ($method !== "GET") {
|
} elseif ($method !== "GET") {
|
||||||
return new EmptyResponse(405, ['Allow' => "HEAD, GET"]);
|
return HTTP::respEmpty(405, ['Allow' => "HEAD, GET"]);
|
||||||
}
|
}
|
||||||
$out = "";
|
$out = "";
|
||||||
if ($target === "/version") {
|
if ($target === "/version") {
|
||||||
|
|
|
@ -19,6 +19,7 @@ use JKingWeb\Arsse\ImportExport\OPML;
|
||||||
use JKingWeb\Arsse\ImportExport\Exception as ImportException;
|
use JKingWeb\Arsse\ImportExport\Exception as ImportException;
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
use JKingWeb\Arsse\Misc\URL;
|
use JKingWeb\Arsse\Misc\URL;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||||
use JKingWeb\Arsse\REST\Exception;
|
use JKingWeb\Arsse\REST\Exception;
|
||||||
use JKingWeb\Arsse\Rule\Rule;
|
use JKingWeb\Arsse\Rule\Rule;
|
||||||
|
@ -26,7 +27,6 @@ use JKingWeb\Arsse\User\ExceptionConflict;
|
||||||
use JKingWeb\Arsse\User\Exception as UserException;
|
use JKingWeb\Arsse\User\Exception as UserException;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\TextResponse as GenericResponse;
|
use Laminas\Diactoros\Response\TextResponse as GenericResponse;
|
||||||
use Laminas\Diactoros\Uri;
|
use Laminas\Diactoros\Uri;
|
||||||
|
@ -295,10 +295,10 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// @codeCoverageIgnoreStart
|
// @codeCoverageIgnoreStart
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// if there was a REST exception return 400
|
// if there was a REST exception return 400
|
||||||
return new EmptyResponse(400);
|
return HTTP::respEmpty(400);
|
||||||
} catch (AbstractException $e) {
|
} catch (AbstractException $e) {
|
||||||
// if there was any other Arsse exception return 500
|
// if there was any other Arsse exception return 500
|
||||||
return new EmptyResponse(500);
|
return HTTP::respEmpty(500);
|
||||||
}
|
}
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
}
|
}
|
||||||
|
@ -317,11 +317,11 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return self::CALLS[$url][$method];
|
return self::CALLS[$url][$method];
|
||||||
} else {
|
} else {
|
||||||
// otherwise return 405
|
// otherwise return 405
|
||||||
return new EmptyResponse(405, ['Allow' => implode(", ", array_keys(self::CALLS[$url]))]);
|
return HTTP::respEmpty(405, ['Allow' => implode(", ", array_keys(self::CALLS[$url]))]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if the path is not supported, return 404
|
// if the path is not supported, return 404
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,13 +451,13 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
if (in_array("GET", $allowed)) {
|
if (in_array("GET", $allowed)) {
|
||||||
array_unshift($allowed, "HEAD");
|
array_unshift($allowed, "HEAD");
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204, [
|
return HTTP::respEmpty(204, [
|
||||||
'Allow' => implode(", ", $allowed),
|
'Allow' => implode(", ", $allowed),
|
||||||
'Accept' => implode(", ", $url === "/import" ? self::ACCEPTED_TYPES_OPML : self::ACCEPTED_TYPES_JSON),
|
'Accept' => implode(", ", $url === "/import" ? self::ACCEPTED_TYPES_OPML : self::ACCEPTED_TYPES_JSON),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// if the path is not supported, return 404
|
// if the path is not supported, return 404
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionConflict $e) {
|
} catch (ExceptionConflict $e) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a useful subset of user metadata
|
/** Returns a useful subset of user metadata
|
||||||
|
@ -728,7 +728,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function transformFeed(array $sub, int $uid, string $rootName, \DateTimeZone $tz): array {
|
protected function transformFeed(array $sub, int $uid, string $rootName, \DateTimeZone $tz): array {
|
||||||
|
@ -866,7 +866,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
protected function deleteFeed(array $path): ResponseInterface {
|
protected function deleteFeed(array $path): ResponseInterface {
|
||||||
try {
|
try {
|
||||||
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $path[1]);
|
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $path[1]);
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
}
|
}
|
||||||
|
@ -1104,7 +1104,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
}
|
}
|
||||||
assert(isset($in), new \Exception("Unknown status specified"));
|
assert(isset($in), new \Exception("Unknown status specified"));
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, $in, (new Context)->articles($data['entry_ids']));
|
Arsse::$db->articleMark(Arsse::$user->id, $in, (new Context)->articles($data['entry_ids']));
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function massRead(Context $c): void {
|
protected function massRead(Context $c): void {
|
||||||
|
@ -1118,7 +1118,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return new ErrorResponse("403", 403);
|
return new ErrorResponse("403", 403);
|
||||||
}
|
}
|
||||||
$this->massRead(new Context);
|
$this->massRead(new Context);
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function markFeed(array $path): ResponseInterface {
|
protected function markFeed(array $path): ResponseInterface {
|
||||||
|
@ -1127,7 +1127,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function markCategory(array $path): ResponseInterface {
|
protected function markCategory(array $path): ResponseInterface {
|
||||||
|
@ -1144,7 +1144,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function toggleEntryBookmark(array $path): ResponseInterface {
|
protected function toggleEntryBookmark(array $path): ResponseInterface {
|
||||||
|
@ -1162,7 +1162,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function refreshFeed(array $path): ResponseInterface {
|
protected function refreshFeed(array $path): ResponseInterface {
|
||||||
|
@ -1172,13 +1172,13 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function refreshAllFeeds(): ResponseInterface {
|
protected function refreshAllFeeds(): ResponseInterface {
|
||||||
// NOTE: This is a no-op
|
// NOTE: This is a no-op
|
||||||
// It could be implemented, but the need is considered low since we use a dynamic schedule always
|
// It could be implemented, but the need is considered low since we use a dynamic schedule always
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function opmlImport(string $data): ResponseInterface {
|
protected function opmlImport(string $data): ResponseInterface {
|
||||||
|
|
|
@ -18,7 +18,6 @@ use JKingWeb\Arsse\REST\Exception;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
public const VERSION = "11.0.5";
|
public const VERSION = "11.0.5";
|
||||||
|
@ -86,19 +85,19 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
if ($req->getAttribute("authenticated", false)) {
|
if ($req->getAttribute("authenticated", false)) {
|
||||||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||||
} else {
|
} else {
|
||||||
return new EmptyResponse(401);
|
return HTTP::respEmpty(401);
|
||||||
}
|
}
|
||||||
// normalize the input
|
// normalize the input
|
||||||
$data = (string) $req->getBody();
|
$data = (string) $req->getBody();
|
||||||
if ($data) {
|
if ($data) {
|
||||||
// if the entity body is not JSON according to content type, return "415 Unsupported Media Type"
|
// if the entity body is not JSON according to content type, return "415 Unsupported Media Type"
|
||||||
if (!HTTP::matchType($req, "", self::ACCEPTED_TYPE)) {
|
if (!HTTP::matchType($req, "", self::ACCEPTED_TYPE)) {
|
||||||
return new EmptyResponse(415, ['Accept' => self::ACCEPTED_TYPE]);
|
return HTTP::respEmpty(415, ['Accept' => self::ACCEPTED_TYPE]);
|
||||||
}
|
}
|
||||||
$data = @json_decode($data, true);
|
$data = @json_decode($data, true);
|
||||||
if (json_last_error() !== \JSON_ERROR_NONE) {
|
if (json_last_error() !== \JSON_ERROR_NONE) {
|
||||||
// if the body could not be parsed as JSON, return "400 Bad Request"
|
// if the body could not be parsed as JSON, return "400 Bad Request"
|
||||||
return new EmptyResponse(400);
|
return HTTP::respEmpty(400);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$data = [];
|
$data = [];
|
||||||
|
@ -117,10 +116,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// @codeCoverageIgnoreStart
|
// @codeCoverageIgnoreStart
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// if there was a REST exception return 400
|
// if there was a REST exception return 400
|
||||||
return new EmptyResponse(400);
|
return HTTP::respEmpty(400);
|
||||||
} catch (AbstractException $e) {
|
} catch (AbstractException $e) {
|
||||||
// if there was any other Arsse exception return 500
|
// if there was any other Arsse exception return 500
|
||||||
return new EmptyResponse(500);
|
return HTTP::respEmpty(500);
|
||||||
}
|
}
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
}
|
}
|
||||||
|
@ -162,11 +161,11 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return $this->paths[$url][$method];
|
return $this->paths[$url][$method];
|
||||||
} else {
|
} else {
|
||||||
// otherwise return 405
|
// otherwise return 405
|
||||||
return new EmptyResponse(405, ['Allow' => implode(", ", array_keys($this->paths[$url]))]);
|
return HTTP::respEmpty(405, ['Allow' => implode(", ", array_keys($this->paths[$url]))]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if the path is not supported, return 404
|
// if the path is not supported, return 404
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,13 +267,13 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
if (in_array("GET", $allowed)) {
|
if (in_array("GET", $allowed)) {
|
||||||
array_unshift($allowed, "HEAD");
|
array_unshift($allowed, "HEAD");
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204, [
|
return HTTP::respEmpty(204, [
|
||||||
'Allow' => implode(",", $allowed),
|
'Allow' => implode(",", $allowed),
|
||||||
'Accept' => self::ACCEPTED_TYPE,
|
'Accept' => self::ACCEPTED_TYPE,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// if the path is not supported, return 404
|
// if the path is not supported, return 404
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,12 +293,12 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
switch ($e->getCode()) {
|
switch ($e->getCode()) {
|
||||||
// folder already exists
|
// folder already exists
|
||||||
case 10236: return new EmptyResponse(409);
|
case 10236: return HTTP::respEmpty(409);
|
||||||
// folder name not acceptable
|
// folder name not acceptable
|
||||||
case 10231:
|
case 10231:
|
||||||
case 10232: return new EmptyResponse(422);
|
case 10232: return HTTP::respEmpty(422);
|
||||||
// other errors related to input
|
// other errors related to input
|
||||||
default: return new EmptyResponse(400); // @codeCoverageIgnore
|
default: return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$folder = $this->folderTranslate(Arsse::$db->folderPropertiesGet(Arsse::$user->id, $folder));
|
$folder = $this->folderTranslate(Arsse::$db->folderPropertiesGet(Arsse::$user->id, $folder));
|
||||||
|
@ -313,9 +312,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->folderRemove(Arsse::$user->id, (int) $url[1]);
|
Arsse::$db->folderRemove(Arsse::$user->id, (int) $url[1]);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// folder does not exist
|
// folder does not exist
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rename a folder (also supports moving nesting folders, but this is not a feature of the API)
|
// rename a folder (also supports moving nesting folders, but this is not a feature of the API)
|
||||||
|
@ -325,24 +324,24 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
switch ($e->getCode()) {
|
switch ($e->getCode()) {
|
||||||
// folder does not exist
|
// folder does not exist
|
||||||
case 10239: return new EmptyResponse(404);
|
case 10239: return HTTP::respEmpty(404);
|
||||||
// folder already exists
|
// folder already exists
|
||||||
case 10236: return new EmptyResponse(409);
|
case 10236: return HTTP::respEmpty(409);
|
||||||
// folder name not acceptable
|
// folder name not acceptable
|
||||||
case 10231:
|
case 10231:
|
||||||
case 10232: return new EmptyResponse(422);
|
case 10232: return HTTP::respEmpty(422);
|
||||||
// other errors related to input
|
// other errors related to input
|
||||||
default: return new EmptyResponse(400); // @codeCoverageIgnore
|
default: return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark all articles associated with a folder as read
|
// mark all articles associated with a folder as read
|
||||||
protected function folderMarkRead(array $url, array $data): ResponseInterface {
|
protected function folderMarkRead(array $url, array $data): ResponseInterface {
|
||||||
if (!ValueInfo::id($data['newestItemId'])) {
|
if (!ValueInfo::id($data['newestItemId'])) {
|
||||||
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
}
|
}
|
||||||
// build the context
|
// build the context
|
||||||
$c = (new Context)->hidden(false);
|
$c = (new Context)->hidden(false);
|
||||||
|
@ -353,15 +352,15 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// folder does not exist
|
// folder does not exist
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return list of feeds which should be refreshed
|
// return list of feeds which should be refreshed
|
||||||
protected function feedListStale(array $url, array $data): ResponseInterface {
|
protected function feedListStale(array $url, array $data): ResponseInterface {
|
||||||
if (!$this->isAdmin()) {
|
if (!$this->isAdmin()) {
|
||||||
return new EmptyResponse(403);
|
return HTTP::respEmpty(403);
|
||||||
}
|
}
|
||||||
// list stale feeds which should be checked for updates
|
// list stale feeds which should be checked for updates
|
||||||
$feeds = Arsse::$db->feedListStale();
|
$feeds = Arsse::$db->feedListStale();
|
||||||
|
@ -376,21 +375,21 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// refresh a feed
|
// refresh a feed
|
||||||
protected function feedUpdate(array $url, array $data): ResponseInterface {
|
protected function feedUpdate(array $url, array $data): ResponseInterface {
|
||||||
if (!$this->isAdmin()) {
|
if (!$this->isAdmin()) {
|
||||||
return new EmptyResponse(403);
|
return HTTP::respEmpty(403);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Arsse::$db->feedUpdate($data['feedId']);
|
Arsse::$db->feedUpdate($data['feedId']);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
switch ($e->getCode()) {
|
switch ($e->getCode()) {
|
||||||
case 10239: // feed does not exist
|
case 10239: // feed does not exist
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
case 10237: // feed ID invalid
|
case 10237: // feed ID invalid
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
default: // other errors related to input
|
default: // other errors related to input
|
||||||
return new EmptyResponse(400); // @codeCoverageIgnore
|
return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a new feed
|
// add a new feed
|
||||||
|
@ -401,10 +400,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$id = Arsse::$db->subscriptionAdd(Arsse::$user->id, (string) $data['url']);
|
$id = Arsse::$db->subscriptionAdd(Arsse::$user->id, (string) $data['url']);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// feed already exists
|
// feed already exists
|
||||||
return new EmptyResponse(409);
|
return HTTP::respEmpty(409);
|
||||||
} catch (FeedException $e) {
|
} catch (FeedException $e) {
|
||||||
// feed could not be retrieved
|
// feed could not be retrieved
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
}
|
}
|
||||||
// if a folder was specified, move the feed to the correct folder; silently ignore errors
|
// if a folder was specified, move the feed to the correct folder; silently ignore errors
|
||||||
if ($data['folderId']) {
|
if ($data['folderId']) {
|
||||||
|
@ -447,9 +446,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $url[1]);
|
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $url[1]);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// feed does not exist
|
// feed does not exist
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rename a feed
|
// rename a feed
|
||||||
|
@ -459,22 +458,22 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
switch ($e->getCode()) {
|
switch ($e->getCode()) {
|
||||||
// subscription does not exist
|
// subscription does not exist
|
||||||
case 10239: return new EmptyResponse(404);
|
case 10239: return HTTP::respEmpty(404);
|
||||||
// name is invalid
|
// name is invalid
|
||||||
case 10231:
|
case 10231:
|
||||||
case 10232: return new EmptyResponse(422);
|
case 10232: return HTTP::respEmpty(422);
|
||||||
// other errors related to input
|
// other errors related to input
|
||||||
default: return new EmptyResponse(400); // @codeCoverageIgnore
|
default: return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// move a feed to a folder
|
// move a feed to a folder
|
||||||
protected function subscriptionMove(array $url, array $data): ResponseInterface {
|
protected function subscriptionMove(array $url, array $data): ResponseInterface {
|
||||||
// if no folder is specified this is an error
|
// if no folder is specified this is an error
|
||||||
if (!isset($data['folderId'])) {
|
if (!isset($data['folderId'])) {
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
}
|
}
|
||||||
// perform the move
|
// perform the move
|
||||||
try {
|
try {
|
||||||
|
@ -482,22 +481,22 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
switch ($e->getCode()) {
|
switch ($e->getCode()) {
|
||||||
case 10239: // subscription does not exist
|
case 10239: // subscription does not exist
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
case 10235: // folder does not exist
|
case 10235: // folder does not exist
|
||||||
case 10237: // folder ID is invalid
|
case 10237: // folder ID is invalid
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
default: // other errors related to input
|
default: // other errors related to input
|
||||||
return new EmptyResponse(400); // @codeCoverageIgnore
|
return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark all articles associated with a subscription as read
|
// mark all articles associated with a subscription as read
|
||||||
protected function subscriptionMarkRead(array $url, array $data): ResponseInterface {
|
protected function subscriptionMarkRead(array $url, array $data): ResponseInterface {
|
||||||
if (!ValueInfo::id($data['newestItemId'])) {
|
if (!ValueInfo::id($data['newestItemId'])) {
|
||||||
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
}
|
}
|
||||||
// build the context
|
// build the context
|
||||||
$c = (new Context)->hidden(false);
|
$c = (new Context)->hidden(false);
|
||||||
|
@ -508,9 +507,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// subscription does not exist
|
// subscription does not exist
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// list articles and their properties
|
// list articles and their properties
|
||||||
|
@ -579,7 +578,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
], [$reverse ? "edition desc" : "edition"]);
|
], [$reverse ? "edition desc" : "edition"]);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// ID of subscription or folder is not valid
|
// ID of subscription or folder is not valid
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
}
|
}
|
||||||
$out = [];
|
$out = [];
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
|
@ -593,14 +592,14 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
protected function articleMarkReadAll(array $url, array $data): ResponseInterface {
|
protected function articleMarkReadAll(array $url, array $data): ResponseInterface {
|
||||||
if (!ValueInfo::id($data['newestItemId'])) {
|
if (!ValueInfo::id($data['newestItemId'])) {
|
||||||
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
||||||
return new EmptyResponse(422);
|
return HTTP::respEmpty(422);
|
||||||
}
|
}
|
||||||
// build the context
|
// build the context
|
||||||
$c = (new Context)->hidden(false);
|
$c = (new Context)->hidden(false);
|
||||||
$c->editionRange(null, (int) $data['newestItemId']);
|
$c->editionRange(null, (int) $data['newestItemId']);
|
||||||
// perform the operation
|
// perform the operation
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark a single article as read
|
// mark a single article as read
|
||||||
|
@ -614,9 +613,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// ID is not valid
|
// ID is not valid
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark a single article as read
|
// mark a single article as read
|
||||||
|
@ -630,9 +629,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
// ID is not valid
|
// ID is not valid
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark an array of articles as read
|
// mark an array of articles as read
|
||||||
|
@ -646,7 +645,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark an array of articles as starred
|
// mark an array of articles as starred
|
||||||
|
@ -660,7 +659,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
}
|
}
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function userStatus(array $url, array $data): ResponseInterface {
|
protected function userStatus(array $url, array $data): ResponseInterface {
|
||||||
|
@ -674,18 +673,18 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
|
|
||||||
protected function cleanupBefore(array $url, array $data): ResponseInterface {
|
protected function cleanupBefore(array $url, array $data): ResponseInterface {
|
||||||
if (!$this->isAdmin()) {
|
if (!$this->isAdmin()) {
|
||||||
return new EmptyResponse(403);
|
return HTTP::respEmpty(403);
|
||||||
}
|
}
|
||||||
Service::cleanupPre();
|
Service::cleanupPre();
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function cleanupAfter(array $url, array $data): ResponseInterface {
|
protected function cleanupAfter(array $url, array $data): ResponseInterface {
|
||||||
if (!$this->isAdmin()) {
|
if (!$this->isAdmin()) {
|
||||||
return new EmptyResponse(403);
|
return HTTP::respEmpty(403);
|
||||||
}
|
}
|
||||||
Service::cleanupPost();
|
Service::cleanupPost();
|
||||||
return new EmptyResponse(204);
|
return HTTP::respEmpty(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the server version
|
// return the server version
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST\NextcloudNews;
|
namespace JKingWeb\Arsse\REST\NextcloudNews;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
class Versions implements \JKingWeb\Arsse\REST\Handler {
|
class Versions implements \JKingWeb\Arsse\REST\Handler {
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
@ -18,12 +18,12 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
||||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||||
if (!preg_match("<^/?$>D", $req->getRequestTarget())) {
|
if (!preg_match("<^/?$>D", $req->getRequestTarget())) {
|
||||||
// if the request path is more than an empty string or a slash, the client is probably trying a version we don't support
|
// if the request path is more than an empty string or a slash, the client is probably trying a version we don't support
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
switch ($req->getMethod()) {
|
switch ($req->getMethod()) {
|
||||||
case "OPTIONS":
|
case "OPTIONS":
|
||||||
// if the request method is OPTIONS, respond accordingly
|
// if the request method is OPTIONS, respond accordingly
|
||||||
return new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
return HTTP::respEmpty(204, ['Allow' => "HEAD,GET"]);
|
||||||
case "GET":
|
case "GET":
|
||||||
// otherwise return the supported versions
|
// otherwise return the supported versions
|
||||||
$out = [
|
$out = [
|
||||||
|
@ -34,7 +34,7 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
||||||
return new Response($out);
|
return new Response($out);
|
||||||
default:
|
default:
|
||||||
// if any other method was used, this is an error
|
// if any other method was used, this is an error
|
||||||
return new EmptyResponse(405, ['Allow' => "HEAD,GET"]);
|
return HTTP::respEmpty(405, ['Allow' => "HEAD,GET"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ use JKingWeb\Arsse\Service;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
use JKingWeb\Arsse\Context\Context;
|
use JKingWeb\Arsse\Context\Context;
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||||
use JKingWeb\Arsse\AbstractException;
|
use JKingWeb\Arsse\AbstractException;
|
||||||
use JKingWeb\Arsse\ExceptionType;
|
use JKingWeb\Arsse\ExceptionType;
|
||||||
|
@ -21,7 +22,6 @@ use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
public const LEVEL = 15; // emulated API level
|
public const LEVEL = 15; // emulated API level
|
||||||
|
@ -96,11 +96,11 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||||
if (!preg_match("<^(?:/(?:index\.php)?)?$>D", $req->getRequestTarget())) {
|
if (!preg_match("<^(?:/(?:index\.php)?)?$>D", $req->getRequestTarget())) {
|
||||||
// reject paths other than the index
|
// reject paths other than the index
|
||||||
return new EmptyResponse(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
if ($req->getMethod() === "OPTIONS") {
|
if ($req->getMethod() === "OPTIONS") {
|
||||||
// respond to OPTIONS rquests; the response is a fib, as we technically accept any type or method
|
// respond to OPTIONS rquests; the response is a fib, as we technically accept any type or method
|
||||||
return new EmptyResponse(204, [
|
return HTTP::respEmpty(204, [
|
||||||
'Allow' => "POST",
|
'Allow' => "POST",
|
||||||
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
||||||
]);
|
]);
|
||||||
|
@ -125,7 +125,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||||
} elseif (Arsse::$conf->userHTTPAuthRequired || Arsse::$conf->userPreAuth || $req->getAttribute("authenticationFailed", false)) {
|
} elseif (Arsse::$conf->userHTTPAuthRequired || Arsse::$conf->userPreAuth || $req->getAttribute("authenticationFailed", false)) {
|
||||||
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
|
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
|
||||||
return new EmptyResponse(401);
|
return HTTP::respEmpty(401);
|
||||||
}
|
}
|
||||||
if (strtolower((string) $data['op']) !== "login") {
|
if (strtolower((string) $data['op']) !== "login") {
|
||||||
// unless logging in, a session identifier is required
|
// unless logging in, a session identifier is required
|
||||||
|
@ -148,7 +148,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
'content' => $e->getData(),
|
'content' => $e->getData(),
|
||||||
]);
|
]);
|
||||||
} catch (AbstractException $e) {
|
} catch (AbstractException $e) {
|
||||||
return new EmptyResponse(500);
|
return HTTP::respEmpty(500);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// absence of a request body indicates an error
|
// absence of a request body indicates an error
|
||||||
|
|
|
@ -7,10 +7,10 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST\TinyTinyRSS;
|
namespace JKingWeb\Arsse\REST\TinyTinyRSS;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse as Response;
|
|
||||||
|
|
||||||
class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
@ -22,25 +22,25 @@ class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||||
} elseif ($req->getAttribute("authenticationFailed", false) || Arsse::$conf->userHTTPAuthRequired) {
|
} elseif ($req->getAttribute("authenticationFailed", false) || Arsse::$conf->userHTTPAuthRequired) {
|
||||||
// otherwise if HTTP authentication failed or did not occur when it is required, deny access at the HTTP level
|
// otherwise if HTTP authentication failed or did not occur when it is required, deny access at the HTTP level
|
||||||
return new Response(401);
|
return HTTP::respEmpty(401);
|
||||||
}
|
}
|
||||||
if ($req->getMethod() !== "GET") {
|
if ($req->getMethod() !== "GET") {
|
||||||
// only GET requests are allowed
|
// only GET requests are allowed
|
||||||
return new Response(405, ['Allow' => "GET"]);
|
return HTTP::respEmpty(405, ['Allow' => "GET"]);
|
||||||
} elseif (!preg_match("<^(\d+)\.ico$>D", $req->getRequestTarget(), $match) || !((int) $match[1])) {
|
} elseif (!preg_match("<^(\d+)\.ico$>D", $req->getRequestTarget(), $match) || !((int) $match[1])) {
|
||||||
return new Response(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$url = Arsse::$db->subscriptionIcon(Arsse::$user->id ?? null, (int) $match[1], false)['url'] ?? null;
|
$url = Arsse::$db->subscriptionIcon(Arsse::$user->id ?? null, (int) $match[1], false)['url'] ?? null;
|
||||||
if (!$url) {
|
if (!$url) {
|
||||||
return new Response(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
if (($pos = strpos($url, "\r")) !== false || ($pos = strpos($url, "\n")) !== false) {
|
if (($pos = strpos($url, "\r")) !== false || ($pos = strpos($url, "\n")) !== false) {
|
||||||
$url = substr($url, 0, $pos);
|
$url = substr($url, 0, $pos);
|
||||||
}
|
}
|
||||||
return new Response(301, ['Location' => $url]);
|
return HTTP::respEmpty(301, ['Location' => $url]);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
return new Response(404);
|
return HTTP::respEmpty(404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace JKingWeb\Arsse\TestCase\REST\Fever;
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\User;
|
use JKingWeb\Arsse\User;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Test\Result;
|
use JKingWeb\Arsse\Test\Result;
|
||||||
use JKingWeb\Arsse\Context\Context;
|
use JKingWeb\Arsse\Context\Context;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
|
@ -17,7 +18,6 @@ use JKingWeb\Arsse\REST\Fever\API;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Laminas\Diactoros\Response\XmlResponse;
|
use Laminas\Diactoros\Response\XmlResponse;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\Fever\API<extended> */
|
/** @covers \JKingWeb\Arsse\REST\Fever\API<extended> */
|
||||||
class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
@ -194,7 +194,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
public function provideTokenAuthenticationRequests(): iterable {
|
public function provideTokenAuthenticationRequests(): iterable {
|
||||||
$success = new JsonResponse(['auth' => 1]);
|
$success = new JsonResponse(['auth' => 1]);
|
||||||
$failure = new JsonResponse(['auth' => 0]);
|
$failure = new JsonResponse(['auth' => 0]);
|
||||||
$denied = new EmptyResponse(401);
|
$denied = HTTP::respEmpty(401);
|
||||||
return [
|
return [
|
||||||
[false, true, null, [], ['api' => null], $failure],
|
[false, true, null, [], ['api' => null], $failure],
|
||||||
[false, false, null, [], ['api' => null], $failure],
|
[false, false, null, [], ['api' => null], $failure],
|
||||||
|
@ -421,8 +421,8 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function provideInvalidRequests(): iterable {
|
public function provideInvalidRequests(): iterable {
|
||||||
return [
|
return [
|
||||||
'Not an API request' => ["", "", "POST", null, new EmptyResponse(404)],
|
'Not an API request' => ["", "", "POST", null, HTTP::respEmpty(404)],
|
||||||
'Wrong method' => ["api", "", "PUT", null, new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])],
|
'Wrong method' => ["api", "", "PUT", null, HTTP::respEmpty(405, ['Allow' => "OPTIONS,POST"])],
|
||||||
'Non-standard method' => ["api", "", "GET", null, new JsonResponse([])],
|
'Non-standard method' => ["api", "", "GET", null, new JsonResponse([])],
|
||||||
'Wrong content type' => ["api", '{"api_key":"validToken"}', "POST", "application/json", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
'Wrong content type' => ["api", '{"api_key":"validToken"}', "POST", "application/json", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
||||||
'Non-standard content type' => ["api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
'Non-standard content type' => ["api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
||||||
|
@ -494,7 +494,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAnswerOptionsRequest(): void {
|
public function testAnswerOptionsRequest(): void {
|
||||||
$exp = new EmptyResponse(204, [
|
$exp = HTTP::respEmpty(204, [
|
||||||
'Allow' => "POST",
|
'Allow' => "POST",
|
||||||
'Accept' => "application/x-www-form-urlencoded, multipart/form-data",
|
'Accept' => "application/x-www-form-urlencoded, multipart/form-data",
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\TestCase\REST\Miniflux;
|
namespace JKingWeb\Arsse\TestCase\REST\Miniflux;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\REST\Miniflux\Status;
|
use JKingWeb\Arsse\REST\Miniflux\Status;
|
||||||
use JKingWeb\Arsse\REST\Miniflux\V1;
|
use JKingWeb\Arsse\REST\Miniflux\V1;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
use Laminas\Diactoros\Response\TextResponse;
|
use Laminas\Diactoros\Response\TextResponse;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\Miniflux\Status */
|
/** @covers \JKingWeb\Arsse\REST\Miniflux\Status */
|
||||||
|
@ -23,12 +23,12 @@ class TestStatus extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
public function provideRequests(): iterable {
|
public function provideRequests(): iterable {
|
||||||
return [
|
return [
|
||||||
["/version", "GET", new TextResponse(V1::VERSION)],
|
["/version", "GET", new TextResponse(V1::VERSION)],
|
||||||
["/version", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])],
|
["/version", "POST", HTTP::respEmpty(405, ['Allow' => "HEAD, GET"])],
|
||||||
["/version", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])],
|
["/version", "OPTIONS", HTTP::respEmpty(204, ['Allow' => "HEAD, GET"])],
|
||||||
["/healthcheck", "GET", new TextResponse("OK")],
|
["/healthcheck", "GET", new TextResponse("OK")],
|
||||||
["/healthcheck", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])],
|
["/healthcheck", "POST", HTTP::respEmpty(405, ['Allow' => "HEAD, GET"])],
|
||||||
["/healthcheck", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])],
|
["/healthcheck", "OPTIONS", HTTP::respEmpty(204, ['Allow' => "HEAD, GET"])],
|
||||||
["/version/", "GET", new EmptyResponse(404)],
|
["/version/", "GET", HTTP::respEmpty(404)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use JKingWeb\Arsse\Context\RootContext;
|
||||||
use JKingWeb\Arsse\Context\UnionContext;
|
use JKingWeb\Arsse\Context\UnionContext;
|
||||||
use JKingWeb\Arsse\User;
|
use JKingWeb\Arsse\User;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Db\Transaction;
|
use JKingWeb\Arsse\Db\Transaction;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\REST\Miniflux\V1;
|
use JKingWeb\Arsse\REST\Miniflux\V1;
|
||||||
|
@ -26,7 +27,6 @@ use JKingWeb\Arsse\User\ExceptionInput as UserExceptionInput;
|
||||||
use JKingWeb\Arsse\Test\Result;
|
use JKingWeb\Arsse\Test\Result;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
use Laminas\Diactoros\Response\TextResponse;
|
use Laminas\Diactoros\Response\TextResponse;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\Miniflux\V1<extended> */
|
/** @covers \JKingWeb\Arsse\REST\Miniflux\V1<extended> */
|
||||||
|
@ -102,7 +102,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
/** @dataProvider provideAuthResponses */
|
/** @dataProvider provideAuthResponses */
|
||||||
public function testAuthenticateAUser($token, bool $auth, bool $success): void {
|
public function testAuthenticateAUser($token, bool $auth, bool $success): void {
|
||||||
$exp = $success ? new EmptyResponse(404) : new ErrorResponse("401", 401);
|
$exp = $success ? HTTP::respEmpty(404) : new ErrorResponse("401", 401);
|
||||||
$user = "john.doe@example.com";
|
$user = "john.doe@example.com";
|
||||||
if ($token !== null) {
|
if ($token !== null) {
|
||||||
$headers = ['X-Auth-Token' => $token];
|
$headers = ['X-Auth-Token' => $token];
|
||||||
|
@ -133,7 +133,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
/** @dataProvider provideInvalidPaths */
|
/** @dataProvider provideInvalidPaths */
|
||||||
public function testRespondToInvalidPaths($path, $method, $code, $allow = null): void {
|
public function testRespondToInvalidPaths($path, $method, $code, $allow = null): void {
|
||||||
$exp = new EmptyResponse($code, $allow ? ['Allow' => $allow] : []);
|
$exp = HTTP::respEmpty($code, $allow ? ['Allow' => $allow] : []);
|
||||||
$this->assertMessage($exp, $this->req($method, $path));
|
$this->assertMessage($exp, $this->req($method, $path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
/** @dataProvider provideOptionsRequests */
|
/** @dataProvider provideOptionsRequests */
|
||||||
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
||||||
$exp = new EmptyResponse(204, [
|
$exp = HTTP::respEmpty(204, [
|
||||||
'Allow' => $allow,
|
'Allow' => $allow,
|
||||||
'Accept' => $accept,
|
'Accept' => $accept,
|
||||||
]);
|
]);
|
||||||
|
@ -382,7 +382,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
Arsse::$user->method("remove")->willReturn(true);
|
Arsse::$user->method("remove")->willReturn(true);
|
||||||
Arsse::$user->expects($this->exactly(1))->method("lookup")->with(2112);
|
Arsse::$user->expects($this->exactly(1))->method("lookup")->with(2112);
|
||||||
Arsse::$user->expects($this->exactly(1))->method("remove")->with("john.doe@example.com");
|
Arsse::$user->expects($this->exactly(1))->method("remove")->with("john.doe@example.com");
|
||||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/users/2112"));
|
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/users/2112"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeleteAMissingUser(): void {
|
public function testDeleteAMissingUser(): void {
|
||||||
|
@ -484,7 +484,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function testDeleteARealCategory(): void {
|
public function testDeleteARealCategory(): void {
|
||||||
$this->dbMock->folderRemove->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
$this->dbMock->folderRemove->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
||||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/categories/2112"));
|
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/categories/2112"));
|
||||||
$this->dbMock->folderRemove->calledWith("john.doe@example.com", 2111);
|
$this->dbMock->folderRemove->calledWith("john.doe@example.com", 2111);
|
||||||
$this->assertMessage(new ErrorResponse("404", 404), $this->req("DELETE", "/categories/47"));
|
$this->assertMessage(new ErrorResponse("404", 404), $this->req("DELETE", "/categories/47"));
|
||||||
$this->dbMock->folderRemove->calledWith("john.doe@example.com", 46);
|
$this->dbMock->folderRemove->calledWith("john.doe@example.com", 46);
|
||||||
|
@ -497,7 +497,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
['id' => 2112],
|
['id' => 2112],
|
||||||
])));
|
])));
|
||||||
$this->dbMock->subscriptionRemove->returns(true);
|
$this->dbMock->subscriptionRemove->returns(true);
|
||||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/categories/1"));
|
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/categories/1"));
|
||||||
Phony::inOrder(
|
Phony::inOrder(
|
||||||
$this->dbMock->begin->calledWith(),
|
$this->dbMock->begin->calledWith(),
|
||||||
$this->dbMock->subscriptionList->calledWith("john.doe@example.com", null, false),
|
$this->dbMock->subscriptionList->calledWith("john.doe@example.com", null, false),
|
||||||
|
@ -680,7 +680,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function testDeleteAFeed(): void {
|
public function testDeleteAFeed(): void {
|
||||||
$this->dbMock->subscriptionRemove->returns(true);
|
$this->dbMock->subscriptionRemove->returns(true);
|
||||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/feeds/2112"));
|
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/feeds/2112"));
|
||||||
$this->dbMock->subscriptionRemove->calledWith(Arsse::$user->id, 2112);
|
$this->dbMock->subscriptionRemove->calledWith(Arsse::$user->id, 2112);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,9 +864,9 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
[['entry_ids' => [1], 'status' => 1], null, new ErrorResponse(["InvalidInputType", 'field' => "status", 'expected' => "string", 'actual' => "integer"], 422)],
|
[['entry_ids' => [1], 'status' => 1], null, new ErrorResponse(["InvalidInputType", 'field' => "status", 'expected' => "string", 'actual' => "integer"], 422)],
|
||||||
[['entry_ids' => [0], 'status' => "read"], null, new ErrorResponse(["InvalidInputValue", 'field' => "entry_ids"], 422)],
|
[['entry_ids' => [0], 'status' => "read"], null, new ErrorResponse(["InvalidInputValue", 'field' => "entry_ids"], 422)],
|
||||||
[['entry_ids' => [1], 'status' => "reread"], null, new ErrorResponse(["InvalidInputValue", 'field' => "status"], 422)],
|
[['entry_ids' => [1], 'status' => "reread"], null, new ErrorResponse(["InvalidInputValue", 'field' => "status"], 422)],
|
||||||
[['entry_ids' => [1, 2], 'status' => "read"], ['read' => true, 'hidden' => false], new EmptyResponse(204)],
|
[['entry_ids' => [1, 2], 'status' => "read"], ['read' => true, 'hidden' => false], HTTP::respEmpty(204)],
|
||||||
[['entry_ids' => [1, 2], 'status' => "unread"], ['read' => false, 'hidden' => false], new EmptyResponse(204)],
|
[['entry_ids' => [1, 2], 'status' => "unread"], ['read' => false, 'hidden' => false], HTTP::respEmpty(204)],
|
||||||
[['entry_ids' => [1, 2], 'status' => "removed"], ['read' => true, 'hidden' => true], new EmptyResponse(204)],
|
[['entry_ids' => [1, 2], 'status' => "removed"], ['read' => true, 'hidden' => true], HTTP::respEmpty(204)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,13 +889,13 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
self::clearData();
|
self::clearData();
|
||||||
$c = (new Context)->hidden(false);
|
$c = (new Context)->hidden(false);
|
||||||
return [
|
return [
|
||||||
["/users/42/mark-all-as-read", $c, 1123, new EmptyResponse(204)],
|
["/users/42/mark-all-as-read", $c, 1123, HTTP::respEmpty(204)],
|
||||||
["/users/2112/mark-all-as-read", $c, null, new ErrorResponse("403", 403)],
|
["/users/2112/mark-all-as-read", $c, null, new ErrorResponse("403", 403)],
|
||||||
["/feeds/47/mark-all-as-read", (clone $c)->subscription(47), 2112, new EmptyResponse(204)],
|
["/feeds/47/mark-all-as-read", (clone $c)->subscription(47), 2112, HTTP::respEmpty(204)],
|
||||||
["/feeds/2112/mark-all-as-read", (clone $c)->subscription(2112), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
["/feeds/2112/mark-all-as-read", (clone $c)->subscription(2112), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
||||||
["/categories/47/mark-all-as-read", (clone $c)->folder(46), 1337, new EmptyResponse(204)],
|
["/categories/47/mark-all-as-read", (clone $c)->folder(46), 1337, HTTP::respEmpty(204)],
|
||||||
["/categories/2112/mark-all-as-read", (clone $c)->folder(2111), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
["/categories/2112/mark-all-as-read", (clone $c)->folder(2111), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
||||||
["/categories/1/mark-all-as-read", (clone $c)->folderShallow(0), 6666, new EmptyResponse(204)],
|
["/categories/1/mark-all-as-read", (clone $c)->folderShallow(0), 6666, HTTP::respEmpty(204)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -929,15 +929,15 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
public function provideBookmarkTogglings(): iterable {
|
public function provideBookmarkTogglings(): iterable {
|
||||||
self::clearData();
|
self::clearData();
|
||||||
return [
|
return [
|
||||||
[1, true, new EmptyResponse(204)],
|
[1, true, HTTP::respEmpty(204)],
|
||||||
[0, false, new EmptyResponse(204)],
|
[0, false, HTTP::respEmpty(204)],
|
||||||
[new ExceptionInput("subjectMissing"), null, new ErrorResponse("404", 404)],
|
[new ExceptionInput("subjectMissing"), null, new ErrorResponse("404", 404)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRefreshAFeed(): void {
|
public function testRefreshAFeed(): void {
|
||||||
$this->dbMock->subscriptionPropertiesGet->returns([]);
|
$this->dbMock->subscriptionPropertiesGet->returns([]);
|
||||||
$this->assertMessage(new EmptyResponse(204), $this->req("PUT", "/feeds/47/refresh"));
|
$this->assertMessage(HTTP::respEmpty(204), $this->req("PUT", "/feeds/47/refresh"));
|
||||||
$this->dbMock->subscriptionPropertiesGet->calledWith(Arsse::$user->id, 47);
|
$this->dbMock->subscriptionPropertiesGet->calledWith(Arsse::$user->id, 47);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,7 +948,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRefreshAllFeeds(): void {
|
public function testRefreshAllFeeds(): void {
|
||||||
$this->assertMessage(new EmptyResponse(204), $this->req("PUT", "/feeds/refresh"));
|
$this->assertMessage(HTTP::respEmpty(204), $this->req("PUT", "/feeds/refresh"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideImports */
|
/** @dataProvider provideImports */
|
||||||
|
|
|
@ -11,13 +11,13 @@ use JKingWeb\Arsse\User;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
use JKingWeb\Arsse\Test\Result;
|
use JKingWeb\Arsse\Test\Result;
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Context\Context;
|
use JKingWeb\Arsse\Context\Context;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\Db\Transaction;
|
use JKingWeb\Arsse\Db\Transaction;
|
||||||
use JKingWeb\Arsse\REST\NextcloudNews\V1_2;
|
use JKingWeb\Arsse\REST\NextcloudNews\V1_2;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\V1_2<extended> */
|
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\V1_2<extended> */
|
||||||
class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
@ -336,13 +336,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendAuthenticationChallenge(): void {
|
public function testSendAuthenticationChallenge(): void {
|
||||||
$exp = new EmptyResponse(401);
|
$exp = HTTP::respEmpty(401);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/", "", [], false));
|
$this->assertMessage($exp, $this->req("GET", "/", "", [], false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideInvalidPaths */
|
/** @dataProvider provideInvalidPaths */
|
||||||
public function testRespondToInvalidPaths($path, $method, $code, $allow = null): void {
|
public function testRespondToInvalidPaths($path, $method, $code, $allow = null): void {
|
||||||
$exp = new EmptyResponse($code, $allow ? ['Allow' => $allow] : []);
|
$exp = HTTP::respEmpty($code, $allow ? ['Allow' => $allow] : []);
|
||||||
$this->assertMessage($exp, $this->req($method, $path));
|
$this->assertMessage($exp, $this->req($method, $path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,16 +374,16 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRespondToInvalidInputTypes(): void {
|
public function testRespondToInvalidInputTypes(): void {
|
||||||
$exp = new EmptyResponse(415, ['Accept' => "application/json"]);
|
$exp = HTTP::respEmpty(415, ['Accept' => "application/json"]);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => "application/xml"]));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => "application/xml"]));
|
||||||
$exp = new EmptyResponse(400);
|
$exp = HTTP::respEmpty(400);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>'));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>'));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => null]));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => null]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideOptionsRequests */
|
/** @dataProvider provideOptionsRequests */
|
||||||
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
||||||
$exp = new EmptyResponse(204, [
|
$exp = HTTP::respEmpty(204, [
|
||||||
'Allow' => $allow,
|
'Allow' => $allow,
|
||||||
'Accept' => $accept,
|
'Accept' => $accept,
|
||||||
]);
|
]);
|
||||||
|
@ -436,19 +436,19 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
[['name' => "Software"], false, 1, new Response(['folders' => [['id' => 1, 'name' => "Software"]]])],
|
[['name' => "Software"], false, 1, new Response(['folders' => [['id' => 1, 'name' => "Software"]]])],
|
||||||
[['name' => "Hardware"], true, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
[['name' => "Hardware"], true, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
||||||
[['name' => "Hardware"], false, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
[['name' => "Hardware"], false, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
||||||
[['name' => "Software"], true, new ExceptionInput("constraintViolation"), new EmptyResponse(409)],
|
[['name' => "Software"], true, new ExceptionInput("constraintViolation"), HTTP::respEmpty(409)],
|
||||||
[['name' => ""], true, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
[['name' => ""], true, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||||
[['name' => " "], true, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
[['name' => " "], true, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||||
[['name' => null], true, new ExceptionInput("missing"), new EmptyResponse(422)],
|
[['name' => null], true, new ExceptionInput("missing"), HTTP::respEmpty(422)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRemoveAFolder(): void {
|
public function testRemoveAFolder(): void {
|
||||||
$this->dbMock->folderRemove->with($this->userId, 1)->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
$this->dbMock->folderRemove->with($this->userId, 1)->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("DELETE", "/folders/1"));
|
$this->assertMessage($exp, $this->req("DELETE", "/folders/1"));
|
||||||
// fail on the second invocation because it no longer exists
|
// fail on the second invocation because it no longer exists
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("DELETE", "/folders/1"));
|
$this->assertMessage($exp, $this->req("DELETE", "/folders/1"));
|
||||||
$this->dbMock->folderRemove->times(2)->calledWith($this->userId, 1);
|
$this->dbMock->folderRemove->times(2)->calledWith($this->userId, 1);
|
||||||
}
|
}
|
||||||
|
@ -467,12 +467,12 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function provideFolderRenamings(): array {
|
public function provideFolderRenamings(): array {
|
||||||
return [
|
return [
|
||||||
[['name' => "Software"], 1, true, new EmptyResponse(204)],
|
[['name' => "Software"], 1, true, HTTP::respEmpty(204)],
|
||||||
[['name' => "Software"], 2, new ExceptionInput("constraintViolation"), new EmptyResponse(409)],
|
[['name' => "Software"], 2, new ExceptionInput("constraintViolation"), HTTP::respEmpty(409)],
|
||||||
[['name' => "Software"], 3, new ExceptionInput("subjectMissing"), new EmptyResponse(404)],
|
[['name' => "Software"], 3, new ExceptionInput("subjectMissing"), HTTP::respEmpty(404)],
|
||||||
[['name' => ""], 2, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
[['name' => ""], 2, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||||
[['name' => " "], 2, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
[['name' => " "], 2, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||||
[['name' => null], 2, new ExceptionInput("missing"), new EmptyResponse(422)],
|
[['name' => null], 2, new ExceptionInput("missing"), HTTP::respEmpty(422)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,19 +540,19 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
return [
|
return [
|
||||||
[['url' => "http://example.com/news.atom", 'folderId' => 3], 2112, 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), new Response(['feeds' => [$this->feeds['rest'][0]]])],
|
[['url' => "http://example.com/news.atom", 'folderId' => 3], 2112, 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), new Response(['feeds' => [$this->feeds['rest'][0]]])],
|
||||||
[['url' => "http://example.org/news.atom", 'folderId' => 8], 42, 4758915, $this->feeds['db'][1], true, new Response(['feeds' => [$this->feeds['rest'][1]], 'newestItemId' => 4758915])],
|
[['url' => "http://example.org/news.atom", 'folderId' => 8], 42, 4758915, $this->feeds['db'][1], true, new Response(['feeds' => [$this->feeds['rest'][1]], 'newestItemId' => 4758915])],
|
||||||
[['url' => "http://example.com/news.atom", 'folderId' => 3], new ExceptionInput("constraintViolation"), 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), new EmptyResponse(409)],
|
[['url' => "http://example.com/news.atom", 'folderId' => 3], new ExceptionInput("constraintViolation"), 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), HTTP::respEmpty(409)],
|
||||||
[['url' => "http://example.org/news.atom", 'folderId' => 8], new ExceptionInput("constraintViolation"), 4758915, $this->feeds['db'][1], true, new EmptyResponse(409)],
|
[['url' => "http://example.org/news.atom", 'folderId' => 8], new ExceptionInput("constraintViolation"), 4758915, $this->feeds['db'][1], true, HTTP::respEmpty(409)],
|
||||||
[[], $feedException, 0, [], false, new EmptyResponse(422)],
|
[[], $feedException, 0, [], false, HTTP::respEmpty(422)],
|
||||||
[['url' => "http://example.net/news.atom", 'folderId' => -1], 47, 2112, $this->feeds['db'][2], new ExceptionInput("typeViolation"), new Response(['feeds' => [$this->feeds['rest'][2]], 'newestItemId' => 2112])],
|
[['url' => "http://example.net/news.atom", 'folderId' => -1], 47, 2112, $this->feeds['db'][2], new ExceptionInput("typeViolation"), new Response(['feeds' => [$this->feeds['rest'][2]], 'newestItemId' => 2112])],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRemoveASubscription(): void {
|
public function testRemoveASubscription(): void {
|
||||||
$this->dbMock->subscriptionRemove->with($this->userId, 1)->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
$this->dbMock->subscriptionRemove->with($this->userId, 1)->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("DELETE", "/feeds/1"));
|
$this->assertMessage($exp, $this->req("DELETE", "/feeds/1"));
|
||||||
// fail on the second invocation because it no longer exists
|
// fail on the second invocation because it no longer exists
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("DELETE", "/feeds/1"));
|
$this->assertMessage($exp, $this->req("DELETE", "/feeds/1"));
|
||||||
$this->dbMock->subscriptionRemove->times(2)->calledWith($this->userId, 1);
|
$this->dbMock->subscriptionRemove->times(2)->calledWith($this->userId, 1);
|
||||||
}
|
}
|
||||||
|
@ -571,17 +571,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, ['folder' => 2112])->throws(new ExceptionInput("idMissing")); // folder does not exist
|
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, ['folder' => 2112])->throws(new ExceptionInput("idMissing")); // folder does not exist
|
||||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, ['folder' => -1])->throws(new ExceptionInput("typeViolation")); // folder is invalid
|
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, ['folder' => -1])->throws(new ExceptionInput("typeViolation")); // folder is invalid
|
||||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 42, $this->anything())->throws(new ExceptionInput("subjectMissing")); // subscription does not exist
|
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 42, $this->anything())->throws(new ExceptionInput("subjectMissing")); // subscription does not exist
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[0])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[0])));
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[1])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[1])));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[2])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[2])));
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/move", json_encode($in[3])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/move", json_encode($in[3])));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[4])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[4])));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[5])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[5])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,17 +601,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, $this->identicalTo(['title' => ""]))->throws(new ExceptionInput("missing"));
|
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, $this->identicalTo(['title' => ""]))->throws(new ExceptionInput("missing"));
|
||||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, $this->identicalTo(['title' => false]))->throws(new ExceptionInput("missing"));
|
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, $this->identicalTo(['title' => false]))->throws(new ExceptionInput("missing"));
|
||||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 42, $this->anything())->throws(new ExceptionInput("subjectMissing"));
|
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 42, $this->anything())->throws(new ExceptionInput("subjectMissing"));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[0])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[0])));
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[1])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[1])));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[2])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[2])));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[3])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[3])));
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/rename", json_encode($in[4])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/rename", json_encode($in[4])));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[6])));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[6])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,7 +633,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function testListStaleFeedsWithoutAuthority(): void {
|
public function testListStaleFeedsWithoutAuthority(): void {
|
||||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||||
$exp = new EmptyResponse(403);
|
$exp = HTTP::respEmpty(403);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/feeds/all"));
|
$this->assertMessage($exp, $this->req("GET", "/feeds/all"));
|
||||||
$this->dbMock->feedListStale->never()->called();
|
$this->dbMock->feedListStale->never()->called();
|
||||||
}
|
}
|
||||||
|
@ -649,11 +649,11 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$this->dbMock->feedUpdate->with(42)->returns(true);
|
$this->dbMock->feedUpdate->with(42)->returns(true);
|
||||||
$this->dbMock->feedUpdate->with(2112)->throws(new ExceptionInput("subjectMissing"));
|
$this->dbMock->feedUpdate->with(2112)->throws(new ExceptionInput("subjectMissing"));
|
||||||
$this->dbMock->feedUpdate->with($this->lessThan(1))->throws(new ExceptionInput("typeViolation"));
|
$this->dbMock->feedUpdate->with($this->lessThan(1))->throws(new ExceptionInput("typeViolation"));
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[0])));
|
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[0])));
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[1])));
|
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[1])));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[2])));
|
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[2])));
|
||||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[3])));
|
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[3])));
|
||||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[4])));
|
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[4])));
|
||||||
|
@ -661,7 +661,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function testUpdateAFeedWithoutAuthority(): void {
|
public function testUpdateAFeedWithoutAuthority(): void {
|
||||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||||
$exp = new EmptyResponse(403);
|
$exp = HTTP::respEmpty(403);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", ['feedId' => 42]));
|
$this->assertMessage($exp, $this->req("GET", "/feeds/update", ['feedId' => 42]));
|
||||||
$this->dbMock->feedUpdate->never()->called();
|
$this->dbMock->feedUpdate->never()->called();
|
||||||
}
|
}
|
||||||
|
@ -684,7 +684,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$t = Date::normalize(time());
|
$t = Date::normalize(time());
|
||||||
$out = new Result($this->v($this->articles['db']));
|
$out = new Result($this->v($this->articles['db']));
|
||||||
$r200 = new Response(['items' => $this->articles['rest']]);
|
$r200 = new Response(['items' => $this->articles['rest']]);
|
||||||
$r422 = new EmptyResponse(422);
|
$r422 = HTTP::respEmpty(422);
|
||||||
return [
|
return [
|
||||||
["/items", [], clone $c, $out, $r200],
|
["/items", [], clone $c, $out, $r200],
|
||||||
["/items", ['type' => 0, 'id' => 42], (clone $c)->subscription(42), new ExceptionInput("idMissing"), $r422],
|
["/items", ['type' => 0, 'id' => 42], (clone $c)->subscription(42), new ExceptionInput("idMissing"), $r422],
|
||||||
|
@ -720,13 +720,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$in = json_encode(['newestItemId' => 2112]);
|
$in = json_encode(['newestItemId' => 2112]);
|
||||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->folder(1)->editionRange(null, 2112)->hidden(false)))->returns(42);
|
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->folder(1)->editionRange(null, 2112)->hidden(false)))->returns(42);
|
||||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->folder(42)->editionRange(null, 2112)->hidden(false)))->throws(new ExceptionInput("idMissing")); // folder doesn't exist
|
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->folder(42)->editionRange(null, 2112)->hidden(false)))->throws(new ExceptionInput("idMissing")); // folder doesn't exist
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read", $in));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read", $in));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read?newestItemId=2112"));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read?newestItemId=2112"));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read"));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read?newestItemId=ook"));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read?newestItemId=ook"));
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/folders/42/read", $in));
|
$this->assertMessage($exp, $this->req("PUT", "/folders/42/read", $in));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,13 +735,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$in = json_encode(['newestItemId' => 2112]);
|
$in = json_encode(['newestItemId' => 2112]);
|
||||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->subscription(1)->editionRange(null, 2112)->hidden(false)))->returns(42);
|
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->subscription(1)->editionRange(null, 2112)->hidden(false)))->returns(42);
|
||||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->subscription(42)->editionRange(null, 2112)->hidden(false)))->throws(new ExceptionInput("idMissing")); // subscription doesn't exist
|
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->subscription(42)->editionRange(null, 2112)->hidden(false)))->throws(new ExceptionInput("idMissing")); // subscription doesn't exist
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read", $in));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read", $in));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read?newestItemId=2112"));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read?newestItemId=2112"));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read"));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read?newestItemId=ook"));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read?newestItemId=ook"));
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/read", $in));
|
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/read", $in));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,10 +749,10 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$read = ['read' => true];
|
$read = ['read' => true];
|
||||||
$in = json_encode(['newestItemId' => 2112]);
|
$in = json_encode(['newestItemId' => 2112]);
|
||||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->editionRange(null, 2112)))->returns(42);
|
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->editionRange(null, 2112)))->returns(42);
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/read", $in));
|
$this->assertMessage($exp, $this->req("PUT", "/items/read", $in));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/read?newestItemId=2112"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/read?newestItemId=2112"));
|
||||||
$exp = new EmptyResponse(422);
|
$exp = HTTP::respEmpty(422);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/read"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/read"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/read?newestItemId=ook"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/read?newestItemId=ook"));
|
||||||
}
|
}
|
||||||
|
@ -770,12 +770,12 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$this->dbMock->articleMark->with($this->userId, $star, $this->equalTo((new Context)->article(2112)))->throws(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist
|
$this->dbMock->articleMark->with($this->userId, $star, $this->equalTo((new Context)->article(2112)))->throws(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist
|
||||||
$this->dbMock->articleMark->with($this->userId, $unstar, $this->equalTo((new Context)->article(4)))->returns(42);
|
$this->dbMock->articleMark->with($this->userId, $unstar, $this->equalTo((new Context)->article(4)))->returns(42);
|
||||||
$this->dbMock->articleMark->with($this->userId, $unstar, $this->equalTo((new Context)->article(1337)))->throws(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist
|
$this->dbMock->articleMark->with($this->userId, $unstar, $this->equalTo((new Context)->article(1337)))->throws(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/1/read"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/1/read"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/2/unread"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/2/unread"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/1/3/star"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/1/3/star"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/4400/4/unstar"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/4400/4/unstar"));
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/42/read"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/42/read"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/47/unread"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/47/unread"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/1/2112/star"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/1/2112/star"));
|
||||||
|
@ -801,7 +801,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->anything())->returns(42);
|
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->anything())->returns(42);
|
||||||
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->equalTo((new Context)->editions([])))->throws(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->equalTo((new Context)->editions([])))->throws(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
||||||
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->equalTo((new Context)->articles([])))->throws(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->equalTo((new Context)->articles([])))->throws(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/read/multiple"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/read/multiple"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/unread/multiple"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/unread/multiple"));
|
||||||
$this->assertMessage($exp, $this->req("PUT", "/items/star/multiple"));
|
$this->assertMessage($exp, $this->req("PUT", "/items/star/multiple"));
|
||||||
|
@ -860,28 +860,28 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function testCleanUpBeforeUpdate(): void {
|
public function testCleanUpBeforeUpdate(): void {
|
||||||
$this->dbMock->feedCleanup->with()->returns(true);
|
$this->dbMock->feedCleanup->with()->returns(true);
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/before-update"));
|
$this->assertMessage($exp, $this->req("GET", "/cleanup/before-update"));
|
||||||
$this->dbMock->feedCleanup->calledWith();
|
$this->dbMock->feedCleanup->calledWith();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCleanUpBeforeUpdateWithoutAuthority(): void {
|
public function testCleanUpBeforeUpdateWithoutAuthority(): void {
|
||||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||||
$exp = new EmptyResponse(403);
|
$exp = HTTP::respEmpty(403);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/before-update"));
|
$this->assertMessage($exp, $this->req("GET", "/cleanup/before-update"));
|
||||||
$this->dbMock->feedCleanup->never()->called();
|
$this->dbMock->feedCleanup->never()->called();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCleanUpAfterUpdate(): void {
|
public function testCleanUpAfterUpdate(): void {
|
||||||
$this->dbMock->articleCleanup->with()->returns(true);
|
$this->dbMock->articleCleanup->with()->returns(true);
|
||||||
$exp = new EmptyResponse(204);
|
$exp = HTTP::respEmpty(204);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/after-update"));
|
$this->assertMessage($exp, $this->req("GET", "/cleanup/after-update"));
|
||||||
$this->dbMock->articleCleanup->calledWith();
|
$this->dbMock->articleCleanup->calledWith();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCleanUpAfterUpdateWithoutAuthority(): void {
|
public function testCleanUpAfterUpdateWithoutAuthority(): void {
|
||||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||||
$exp = new EmptyResponse(403);
|
$exp = HTTP::respEmpty(403);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/after-update"));
|
$this->assertMessage($exp, $this->req("GET", "/cleanup/after-update"));
|
||||||
$this->dbMock->feedCleanup->never()->called();
|
$this->dbMock->feedCleanup->never()->called();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\TestCase\REST\NextcloudNews;
|
namespace JKingWeb\Arsse\TestCase\REST\NextcloudNews;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\REST\NextcloudNews\Versions;
|
use JKingWeb\Arsse\REST\NextcloudNews\Versions;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\Versions */
|
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\Versions */
|
||||||
class TestVersions extends \JKingWeb\Arsse\Test\AbstractTest {
|
class TestVersions extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
@ -32,17 +32,17 @@ class TestVersions extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRespondToOptionsRequest(): void {
|
public function testRespondToOptionsRequest(): void {
|
||||||
$exp = new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
$exp = HTTP::respEmpty(204, ['Allow' => "HEAD,GET"]);
|
||||||
$this->assertMessage($exp, $this->req("OPTIONS", "/"));
|
$this->assertMessage($exp, $this->req("OPTIONS", "/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUseIncorrectMethod(): void {
|
public function testUseIncorrectMethod(): void {
|
||||||
$exp = new EmptyResponse(405, ['Allow' => "HEAD,GET"]);
|
$exp = HTTP::respEmpty(405, ['Allow' => "HEAD,GET"]);
|
||||||
$this->assertMessage($exp, $this->req("POST", "/"));
|
$this->assertMessage($exp, $this->req("POST", "/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUseIncorrectPath(): void {
|
public function testUseIncorrectPath(): void {
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("GET", "/ook"));
|
$this->assertMessage($exp, $this->req("GET", "/ook"));
|
||||||
$this->assertMessage($exp, $this->req("OPTIONS", "/ook"));
|
$this->assertMessage($exp, $this->req("OPTIONS", "/ook"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,13 +12,13 @@ use JKingWeb\Arsse\REST;
|
||||||
use JKingWeb\Arsse\REST\Exception501;
|
use JKingWeb\Arsse\REST\Exception501;
|
||||||
use JKingWeb\Arsse\REST\NextcloudNews\V1_2 as NCN;
|
use JKingWeb\Arsse\REST\NextcloudNews\V1_2 as NCN;
|
||||||
use JKingWeb\Arsse\REST\TinyTinyRSS\API as TTRSS;
|
use JKingWeb\Arsse\REST\TinyTinyRSS\API as TTRSS;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use Psr\Http\Message\RequestInterface;
|
use Psr\Http\Message\RequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Request;
|
use Laminas\Diactoros\Request;
|
||||||
use Laminas\Diactoros\Response;
|
use Laminas\Diactoros\Response;
|
||||||
use Laminas\Diactoros\ServerRequest;
|
use Laminas\Diactoros\ServerRequest;
|
||||||
use Laminas\Diactoros\Response\TextResponse;
|
use Laminas\Diactoros\Response\TextResponse;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST */
|
/** @covers \JKingWeb\Arsse\REST */
|
||||||
class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
@ -96,7 +96,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
public function testSendAuthenticationChallenges(): void {
|
public function testSendAuthenticationChallenges(): void {
|
||||||
self::setConf();
|
self::setConf();
|
||||||
$r = new REST();
|
$r = new REST();
|
||||||
$in = new EmptyResponse(401);
|
$in = HTTP::respEmpty(401);
|
||||||
$exp = $in->withHeader("WWW-Authenticate", 'Basic realm="OOK", charset="UTF-8"');
|
$exp = $in->withHeader("WWW-Authenticate", 'Basic realm="OOK", charset="UTF-8"');
|
||||||
$act = $r->challenge($in, "OOK");
|
$act = $r->challenge($in, "OOK");
|
||||||
$this->assertMessage($exp, $act);
|
$this->assertMessage($exp, $act);
|
||||||
|
@ -190,8 +190,8 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
public function testAddCorsHeaders(string $reqMethod, array $reqHeaders, array $resHeaders, array $expHeaders): void {
|
public function testAddCorsHeaders(string $reqMethod, array $reqHeaders, array $resHeaders, array $expHeaders): void {
|
||||||
$r = new REST();
|
$r = new REST();
|
||||||
$req = new Request("", $reqMethod, "php://memory", $reqHeaders);
|
$req = new Request("", $reqMethod, "php://memory", $reqHeaders);
|
||||||
$res = new EmptyResponse(204, $resHeaders);
|
$res = HTTP::respEmpty(204, $resHeaders);
|
||||||
$exp = new EmptyResponse(204, $expHeaders);
|
$exp = HTTP::respEmpty(204, $expHeaders);
|
||||||
$act = $r->corsApply($res, $req);
|
$act = $r->corsApply($res, $req);
|
||||||
$this->assertMessage($exp, $act);
|
$this->assertMessage($exp, $act);
|
||||||
}
|
}
|
||||||
|
@ -268,21 +268,21 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$stream = fopen("php://memory", "w+b");
|
$stream = fopen("php://memory", "w+b");
|
||||||
fwrite($stream, "ook");
|
fwrite($stream, "ook");
|
||||||
return [
|
return [
|
||||||
[new EmptyResponse(204), new EmptyResponse(204)],
|
[HTTP::respEmpty(204), HTTP::respEmpty(204)],
|
||||||
[new EmptyResponse(401), new EmptyResponse(401, ['WWW-Authenticate' => "Fake Value"])],
|
[HTTP::respEmpty(401), HTTP::respEmpty(401, ['WWW-Authenticate' => "Fake Value"])],
|
||||||
[new EmptyResponse(204, ['Allow' => "PUT"]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
[HTTP::respEmpty(204, ['Allow' => "PUT"]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||||
[new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
[HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||||
[new EmptyResponse(204, ['Allow' => "PUT,OPTIONS"]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
[HTTP::respEmpty(204, ['Allow' => "PUT,OPTIONS"]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||||
[new EmptyResponse(204, ['Allow' => ["PUT", "OPTIONS"]]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
[HTTP::respEmpty(204, ['Allow' => ["PUT", "OPTIONS"]]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||||
[new EmptyResponse(204, ['Allow' => ["PUT, DELETE", "OPTIONS"]]), new EmptyResponse(204, ['Allow' => "PUT, DELETE, OPTIONS"])],
|
[HTTP::respEmpty(204, ['Allow' => ["PUT, DELETE", "OPTIONS"]]), HTTP::respEmpty(204, ['Allow' => "PUT, DELETE, OPTIONS"])],
|
||||||
[new EmptyResponse(204, ['Allow' => "HEAD,GET"]), new EmptyResponse(204, ['Allow' => "HEAD, GET, OPTIONS"])],
|
[HTTP::respEmpty(204, ['Allow' => "HEAD,GET"]), HTTP::respEmpty(204, ['Allow' => "HEAD, GET, OPTIONS"])],
|
||||||
[new EmptyResponse(204, ['Allow' => "GET"]), new EmptyResponse(204, ['Allow' => "GET, HEAD, OPTIONS"])],
|
[HTTP::respEmpty(204, ['Allow' => "GET"]), HTTP::respEmpty(204, ['Allow' => "GET, HEAD, OPTIONS"])],
|
||||||
[new TextResponse("ook", 200), new TextResponse("ook", 200, ['Content-Length' => "3"])],
|
[new TextResponse("ook", 200), new TextResponse("ook", 200, ['Content-Length' => "3"])],
|
||||||
[new TextResponse("", 200), new TextResponse("", 200, ['Content-Length' => "0"])],
|
[new TextResponse("", 200), new TextResponse("", 200, ['Content-Length' => "0"])],
|
||||||
[new TextResponse("ook", 404), new TextResponse("ook", 404, ['Content-Length' => "3"])],
|
[new TextResponse("ook", 404), new TextResponse("ook", 404, ['Content-Length' => "3"])],
|
||||||
[new TextResponse("", 404), new TextResponse("", 404)],
|
[new TextResponse("", 404), new TextResponse("", 404)],
|
||||||
[new Response($stream, 200), new Response($stream, 200, ['Content-Length' => "3"]), new Request("", "GET")],
|
[new Response($stream, 200), new Response($stream, 200, ['Content-Length' => "3"]), new Request("", "GET")],
|
||||||
[new Response($stream, 200), new EmptyResponse(200, ['Content-Length' => "3"]), new Request("", "HEAD")],
|
[new Response($stream, 200), HTTP::respEmpty(200, ['Content-Length' => "3"]), new Request("", "HEAD")],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
});
|
});
|
||||||
if ($called) {
|
if ($called) {
|
||||||
$hMock = $this->mock($class);
|
$hMock = $this->mock($class);
|
||||||
$hMock->dispatch->returns(new EmptyResponse(204));
|
$hMock->dispatch->returns(HTTP::respEmpty(204));
|
||||||
$this->objMock->get->with($class)->returns($hMock);
|
$this->objMock->get->with($class)->returns($hMock);
|
||||||
Arsse::$obj = $this->objMock->get();
|
Arsse::$obj = $this->objMock->get();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use JKingWeb\Arsse\User;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
use JKingWeb\Arsse\Test\Result;
|
use JKingWeb\Arsse\Test\Result;
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Context\Context;
|
use JKingWeb\Arsse\Context\Context;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\Db\Transaction;
|
use JKingWeb\Arsse\Db\Transaction;
|
||||||
|
@ -18,7 +19,6 @@ use JKingWeb\Arsse\REST\TinyTinyRSS\API;
|
||||||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\TinyTinyRSS\API<extended>
|
/** @covers \JKingWeb\Arsse\REST\TinyTinyRSS\API<extended>
|
||||||
* @covers \JKingWeb\Arsse\REST\TinyTinyRSS\Exception */
|
* @covers \JKingWeb\Arsse\REST\TinyTinyRSS\Exception */
|
||||||
|
@ -188,12 +188,12 @@ LONG_STRING;
|
||||||
$this->assertMessage($exp, $this->req(null, "POST", "", ""));
|
$this->assertMessage($exp, $this->req(null, "POST", "", ""));
|
||||||
$this->assertMessage($exp, $this->req(null, "POST", "/", ""));
|
$this->assertMessage($exp, $this->req(null, "POST", "/", ""));
|
||||||
$this->assertMessage($exp, $this->req(null, "POST", "/index.php", ""));
|
$this->assertMessage($exp, $this->req(null, "POST", "/index.php", ""));
|
||||||
$exp = new EmptyResponse(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req(null, "POST", "/bad/path", ""));
|
$this->assertMessage($exp, $this->req(null, "POST", "/bad/path", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHandleOptionsRequest(): void {
|
public function testHandleOptionsRequest(): void {
|
||||||
$exp = new EmptyResponse(204, [
|
$exp = HTTP::respEmpty(204, [
|
||||||
'Allow' => "POST",
|
'Allow' => "POST",
|
||||||
'Accept' => "application/json, text/json",
|
'Accept' => "application/json, text/json",
|
||||||
]);
|
]);
|
||||||
|
@ -215,7 +215,7 @@ LONG_STRING;
|
||||||
$this->userMock->auth->with("jane.doe@example.com", "superman")->returns(true);
|
$this->userMock->auth->with("jane.doe@example.com", "superman")->returns(true);
|
||||||
$this->dbMock->sessionCreate->with("john.doe@example.com")->returns("PriestsOfSyrinx", "SolarFederation");
|
$this->dbMock->sessionCreate->with("john.doe@example.com")->returns("PriestsOfSyrinx", "SolarFederation");
|
||||||
$this->dbMock->sessionCreate->with("jane.doe@example.com")->returns("ClockworkAngels", "SevenCitiesOfGold");
|
$this->dbMock->sessionCreate->with("jane.doe@example.com")->returns("ClockworkAngels", "SevenCitiesOfGold");
|
||||||
if ($sessions instanceof EmptyResponse) {
|
if ($sessions instanceof ResponseInterface) {
|
||||||
$exp1 = $sessions;
|
$exp1 = $sessions;
|
||||||
$exp2 = $sessions;
|
$exp2 = $sessions;
|
||||||
} elseif ($sessions) {
|
} elseif ($sessions) {
|
||||||
|
@ -260,7 +260,7 @@ LONG_STRING;
|
||||||
'op' => "isLoggedIn",
|
'op' => "isLoggedIn",
|
||||||
'sid' => $data,
|
'sid' => $data,
|
||||||
];
|
];
|
||||||
if ($result instanceof EmptyResponse) {
|
if ($result instanceof ResponseInterface) {
|
||||||
$exp1 = $result;
|
$exp1 = $result;
|
||||||
$exp2 = null;
|
$exp2 = null;
|
||||||
} elseif ($result) {
|
} elseif ($result) {
|
||||||
|
@ -333,7 +333,7 @@ LONG_STRING;
|
||||||
'userHTTPAuthRequired' => true,
|
'userHTTPAuthRequired' => true,
|
||||||
'userSessionEnforced' => false,
|
'userSessionEnforced' => false,
|
||||||
];
|
];
|
||||||
$http401 = new EmptyResponse(401);
|
$http401 = HTTP::respEmpty(401);
|
||||||
if ($type === "login") {
|
if ($type === "login") {
|
||||||
return [
|
return [
|
||||||
// conf, user, data, result
|
// conf, user, data, result
|
||||||
|
@ -532,7 +532,7 @@ LONG_STRING;
|
||||||
'user' => $this->userId,
|
'user' => $this->userId,
|
||||||
'password' => "secret",
|
'password' => "secret",
|
||||||
];
|
];
|
||||||
$exp = new EmptyResponse(500);
|
$exp = HTTP::respEmpty(500);
|
||||||
$this->assertMessage($exp, $this->req($data));
|
$this->assertMessage($exp, $this->req($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ namespace JKingWeb\Arsse\TestCase\REST\TinyTinyRSS;
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\User;
|
use JKingWeb\Arsse\User;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
|
use JKingWeb\Arsse\Misc\HTTP;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\REST\TinyTinyRSS\Icon;
|
use JKingWeb\Arsse\REST\TinyTinyRSS\Icon;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Laminas\Diactoros\Response\EmptyResponse as Response;
|
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\TinyTinyRSS\Icon<extended> */
|
/** @covers \JKingWeb\Arsse\REST\TinyTinyRSS\Icon<extended> */
|
||||||
class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
@ -51,21 +51,21 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$this->dbMock->subscriptionIcon->with($this->anything(), 2112, false)->returns(['url' => "http://example.net/logo.png"]);
|
$this->dbMock->subscriptionIcon->with($this->anything(), 2112, false)->returns(['url' => "http://example.net/logo.png"]);
|
||||||
$this->dbMock->subscriptionIcon->with($this->anything(), 1337, false)->returns(['url' => "http://example.org/icon.gif\r\nLocation: http://bad.example.com/"]);
|
$this->dbMock->subscriptionIcon->with($this->anything(), 1337, false)->returns(['url' => "http://example.org/icon.gif\r\nLocation: http://bad.example.com/"]);
|
||||||
// these requests should succeed
|
// these requests should succeed
|
||||||
$exp = new Response(301, ['Location' => "http://example.com/favicon.ico"]);
|
$exp = HTTP::respEmpty(301, ['Location' => "http://example.com/favicon.ico"]);
|
||||||
$this->assertMessage($exp, $this->req("42.ico"));
|
$this->assertMessage($exp, $this->req("42.ico"));
|
||||||
$exp = new Response(301, ['Location' => "http://example.net/logo.png"]);
|
$exp = HTTP::respEmpty(301, ['Location' => "http://example.net/logo.png"]);
|
||||||
$this->assertMessage($exp, $this->req("2112.ico"));
|
$this->assertMessage($exp, $this->req("2112.ico"));
|
||||||
$exp = new Response(301, ['Location' => "http://example.org/icon.gif"]);
|
$exp = HTTP::respEmpty(301, ['Location' => "http://example.org/icon.gif"]);
|
||||||
$this->assertMessage($exp, $this->req("1337.ico"));
|
$this->assertMessage($exp, $this->req("1337.ico"));
|
||||||
// these requests should fail
|
// these requests should fail
|
||||||
$exp = new Response(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->req("ook.ico"));
|
$this->assertMessage($exp, $this->req("ook.ico"));
|
||||||
$this->assertMessage($exp, $this->req("ook"));
|
$this->assertMessage($exp, $this->req("ook"));
|
||||||
$this->assertMessage($exp, $this->req("47.ico"));
|
$this->assertMessage($exp, $this->req("47.ico"));
|
||||||
$this->assertMessage($exp, $this->req("2112.png"));
|
$this->assertMessage($exp, $this->req("2112.png"));
|
||||||
$this->assertMessage($exp, $this->req("1123.ico"));
|
$this->assertMessage($exp, $this->req("1123.ico"));
|
||||||
// only GET is allowed
|
// only GET is allowed
|
||||||
$exp = new Response(405, ['Allow' => "GET"]);
|
$exp = HTTP::respEmpty(405, ['Allow' => "GET"]);
|
||||||
$this->assertMessage($exp, $this->req("2112.ico", "PUT"));
|
$this->assertMessage($exp, $this->req("2112.ico", "PUT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,32 +79,32 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$this->dbMock->subscriptionIcon->with(null, 2112, false)->returns($url);
|
$this->dbMock->subscriptionIcon->with(null, 2112, false)->returns($url);
|
||||||
$this->dbMock->subscriptionIcon->with(null, 1337, false)->returns($url);
|
$this->dbMock->subscriptionIcon->with(null, 1337, false)->returns($url);
|
||||||
// these requests should succeed
|
// these requests should succeed
|
||||||
$exp = new Response(301, ['Location' => "http://example.org/icon.gif"]);
|
$exp = HTTP::respEmpty(301, ['Location' => "http://example.org/icon.gif"]);
|
||||||
$this->assertMessage($exp, $this->req("42.ico"));
|
$this->assertMessage($exp, $this->req("42.ico"));
|
||||||
$this->assertMessage($exp, $this->req("2112.ico"));
|
$this->assertMessage($exp, $this->req("2112.ico"));
|
||||||
$this->assertMessage($exp, $this->req("1337.ico"));
|
$this->assertMessage($exp, $this->req("1337.ico"));
|
||||||
$this->assertMessage($exp, $this->reqAuth("42.ico"));
|
$this->assertMessage($exp, $this->reqAuth("42.ico"));
|
||||||
$this->assertMessage($exp, $this->reqAuth("1337.ico"));
|
$this->assertMessage($exp, $this->reqAuth("1337.ico"));
|
||||||
// these requests should fail
|
// these requests should fail
|
||||||
$exp = new Response(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->reqAuth("2112.ico"));
|
$this->assertMessage($exp, $this->reqAuth("2112.ico"));
|
||||||
$exp = new Response(401);
|
$exp = HTTP::respEmpty(401);
|
||||||
$this->assertMessage($exp, $this->reqAuthFailed("42.ico"));
|
$this->assertMessage($exp, $this->reqAuthFailed("42.ico"));
|
||||||
$this->assertMessage($exp, $this->reqAuthFailed("1337.ico"));
|
$this->assertMessage($exp, $this->reqAuthFailed("1337.ico"));
|
||||||
// with HTTP auth required, only authenticated requests should succeed
|
// with HTTP auth required, only authenticated requests should succeed
|
||||||
self::setConf(['userHTTPAuthRequired' => true]);
|
self::setConf(['userHTTPAuthRequired' => true]);
|
||||||
$exp = new Response(301, ['Location' => "http://example.org/icon.gif"]);
|
$exp = HTTP::respEmpty(301, ['Location' => "http://example.org/icon.gif"]);
|
||||||
$this->assertMessage($exp, $this->reqAuth("42.ico"));
|
$this->assertMessage($exp, $this->reqAuth("42.ico"));
|
||||||
$this->assertMessage($exp, $this->reqAuth("1337.ico"));
|
$this->assertMessage($exp, $this->reqAuth("1337.ico"));
|
||||||
// anything else should fail
|
// anything else should fail
|
||||||
$exp = new Response(401);
|
$exp = HTTP::respEmpty(401);
|
||||||
$this->assertMessage($exp, $this->req("42.ico"));
|
$this->assertMessage($exp, $this->req("42.ico"));
|
||||||
$this->assertMessage($exp, $this->req("2112.ico"));
|
$this->assertMessage($exp, $this->req("2112.ico"));
|
||||||
$this->assertMessage($exp, $this->req("1337.ico"));
|
$this->assertMessage($exp, $this->req("1337.ico"));
|
||||||
$this->assertMessage($exp, $this->reqAuthFailed("42.ico"));
|
$this->assertMessage($exp, $this->reqAuthFailed("42.ico"));
|
||||||
$this->assertMessage($exp, $this->reqAuthFailed("1337.ico"));
|
$this->assertMessage($exp, $this->reqAuthFailed("1337.ico"));
|
||||||
// resources for the wrtong user should still fail, too
|
// resources for the wrtong user should still fail, too
|
||||||
$exp = new Response(404);
|
$exp = HTTP::respEmpty(404);
|
||||||
$this->assertMessage($exp, $this->reqAuth("2112.ico"));
|
$this->assertMessage($exp, $this->reqAuth("2112.ico"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue