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;
|
||||
|
||||
use JKingWeb\Arsse\Misc\URL;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\ServerRequestFactory;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class REST {
|
||||
public const API_LIST = [
|
||||
|
@ -101,7 +101,7 @@ class REST {
|
|||
$res = $drv->dispatch($req);
|
||||
}
|
||||
} catch (REST\Exception501 $e) {
|
||||
$res = new EmptyResponse(501);
|
||||
$res = HTTP::respEmpty(501);
|
||||
}
|
||||
// modify the response so that it has all the required metadata
|
||||
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 ($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 ($res->hasHeader("Allow")) {
|
||||
|
|
|
@ -10,13 +10,12 @@ use JKingWeb\Arsse\Arsse;
|
|||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Laminas\Diactoros\Response\XmlResponse;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public const LEVEL = 3;
|
||||
|
@ -62,11 +61,11 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$P = $this->normalizeInputPost($req->getParsedBody() ?? []);
|
||||
if (!isset($G['api'])) {
|
||||
// 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()) {
|
||||
case "OPTIONS":
|
||||
return new EmptyResponse(204, [
|
||||
return HTTP::respEmpty(204, [
|
||||
'Allow' => "POST",
|
||||
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
||||
]);
|
||||
|
@ -82,7 +81,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$out['auth'] = 1;
|
||||
} 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
|
||||
return new EmptyResponse(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
// produce a full response if authenticated or a basic response otherwise
|
||||
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 $this->formatResponse($out, ($G['api'] === "xml"));
|
||||
default:
|
||||
return new EmptyResponse(405, ['Allow' => "OPTIONS,POST"]);
|
||||
return HTTP::respEmpty(405, ['Allow' => "OPTIONS,POST"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST\Miniflux;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
|
||||
class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
|
@ -18,13 +18,13 @@ class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
$target = parse_url($req->getRequestTarget())['path'] ?? "";
|
||||
if (!in_array($target, ["/version", "/healthcheck"])) {
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
$method = $req->getMethod();
|
||||
if ($method === "OPTIONS") {
|
||||
return new EmptyResponse(204, ['Allow' => "HEAD, GET"]);
|
||||
return HTTP::respEmpty(204, ['Allow' => "HEAD, GET"]);
|
||||
} elseif ($method !== "GET") {
|
||||
return new EmptyResponse(405, ['Allow' => "HEAD, GET"]);
|
||||
return HTTP::respEmpty(405, ['Allow' => "HEAD, GET"]);
|
||||
}
|
||||
$out = "";
|
||||
if ($target === "/version") {
|
||||
|
|
|
@ -19,6 +19,7 @@ use JKingWeb\Arsse\ImportExport\OPML;
|
|||
use JKingWeb\Arsse\ImportExport\Exception as ImportException;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\URL;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||
use JKingWeb\Arsse\REST\Exception;
|
||||
use JKingWeb\Arsse\Rule\Rule;
|
||||
|
@ -26,7 +27,6 @@ use JKingWeb\Arsse\User\ExceptionConflict;
|
|||
use JKingWeb\Arsse\User\Exception as UserException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\TextResponse as GenericResponse;
|
||||
use Laminas\Diactoros\Uri;
|
||||
|
@ -295,10 +295,10 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
// if there was a REST exception return 400
|
||||
return new EmptyResponse(400);
|
||||
return HTTP::respEmpty(400);
|
||||
} catch (AbstractException $e) {
|
||||
// if there was any other Arsse exception return 500
|
||||
return new EmptyResponse(500);
|
||||
return HTTP::respEmpty(500);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
@ -317,11 +317,11 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return self::CALLS[$url][$method];
|
||||
} else {
|
||||
// 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 {
|
||||
// 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)) {
|
||||
array_unshift($allowed, "HEAD");
|
||||
}
|
||||
return new EmptyResponse(204, [
|
||||
return HTTP::respEmpty(204, [
|
||||
'Allow' => implode(", ", $allowed),
|
||||
'Accept' => implode(", ", $url === "/import" ? self::ACCEPTED_TYPES_OPML : self::ACCEPTED_TYPES_JSON),
|
||||
]);
|
||||
} else {
|
||||
// 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) {
|
||||
return new ErrorResponse("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
/** Returns a useful subset of user metadata
|
||||
|
@ -728,7 +728,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
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 {
|
||||
|
@ -866,7 +866,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
protected function deleteFeed(array $path): ResponseInterface {
|
||||
try {
|
||||
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $path[1]);
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
}
|
||||
|
@ -1104,7 +1104,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
assert(isset($in), new \Exception("Unknown status specified"));
|
||||
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 {
|
||||
|
@ -1118,7 +1118,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return new ErrorResponse("403", 403);
|
||||
}
|
||||
$this->massRead(new Context);
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function markFeed(array $path): ResponseInterface {
|
||||
|
@ -1127,7 +1127,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function markCategory(array $path): ResponseInterface {
|
||||
|
@ -1144,7 +1144,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function toggleEntryBookmark(array $path): ResponseInterface {
|
||||
|
@ -1162,7 +1162,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function refreshFeed(array $path): ResponseInterface {
|
||||
|
@ -1172,13 +1172,13 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function refreshAllFeeds(): ResponseInterface {
|
||||
// NOTE: This is a no-op
|
||||
// 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 {
|
||||
|
|
|
@ -18,7 +18,6 @@ use JKingWeb\Arsse\REST\Exception;
|
|||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public const VERSION = "11.0.5";
|
||||
|
@ -86,19 +85,19 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if ($req->getAttribute("authenticated", false)) {
|
||||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||
} else {
|
||||
return new EmptyResponse(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
// normalize the input
|
||||
$data = (string) $req->getBody();
|
||||
if ($data) {
|
||||
// if the entity body is not JSON according to content type, return "415 Unsupported Media 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);
|
||||
if (json_last_error() !== \JSON_ERROR_NONE) {
|
||||
// if the body could not be parsed as JSON, return "400 Bad Request"
|
||||
return new EmptyResponse(400);
|
||||
return HTTP::respEmpty(400);
|
||||
}
|
||||
} else {
|
||||
$data = [];
|
||||
|
@ -117,10 +116,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
// if there was a REST exception return 400
|
||||
return new EmptyResponse(400);
|
||||
return HTTP::respEmpty(400);
|
||||
} catch (AbstractException $e) {
|
||||
// if there was any other Arsse exception return 500
|
||||
return new EmptyResponse(500);
|
||||
return HTTP::respEmpty(500);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
@ -162,11 +161,11 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return $this->paths[$url][$method];
|
||||
} else {
|
||||
// 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 {
|
||||
// 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)) {
|
||||
array_unshift($allowed, "HEAD");
|
||||
}
|
||||
return new EmptyResponse(204, [
|
||||
return HTTP::respEmpty(204, [
|
||||
'Allow' => implode(",", $allowed),
|
||||
'Accept' => self::ACCEPTED_TYPE,
|
||||
]);
|
||||
} else {
|
||||
// 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) {
|
||||
switch ($e->getCode()) {
|
||||
// folder already exists
|
||||
case 10236: return new EmptyResponse(409);
|
||||
case 10236: return HTTP::respEmpty(409);
|
||||
// folder name not acceptable
|
||||
case 10231:
|
||||
case 10232: return new EmptyResponse(422);
|
||||
case 10232: return HTTP::respEmpty(422);
|
||||
// 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));
|
||||
|
@ -313,9 +312,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->folderRemove(Arsse::$user->id, (int) $url[1]);
|
||||
} catch (ExceptionInput $e) {
|
||||
// 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)
|
||||
|
@ -325,24 +324,24 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
// folder does not exist
|
||||
case 10239: return new EmptyResponse(404);
|
||||
case 10239: return HTTP::respEmpty(404);
|
||||
// folder already exists
|
||||
case 10236: return new EmptyResponse(409);
|
||||
case 10236: return HTTP::respEmpty(409);
|
||||
// folder name not acceptable
|
||||
case 10231:
|
||||
case 10232: return new EmptyResponse(422);
|
||||
case 10232: return HTTP::respEmpty(422);
|
||||
// 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
|
||||
protected function folderMarkRead(array $url, array $data): ResponseInterface {
|
||||
if (!ValueInfo::id($data['newestItemId'])) {
|
||||
// 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
|
||||
$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);
|
||||
} catch (ExceptionInput $e) {
|
||||
// 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
|
||||
protected function feedListStale(array $url, array $data): ResponseInterface {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
// list stale feeds which should be checked for updates
|
||||
$feeds = Arsse::$db->feedListStale();
|
||||
|
@ -376,21 +375,21 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// refresh a feed
|
||||
protected function feedUpdate(array $url, array $data): ResponseInterface {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
try {
|
||||
Arsse::$db->feedUpdate($data['feedId']);
|
||||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10239: // feed does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
case 10237: // feed ID invalid
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
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
|
||||
|
@ -401,10 +400,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$id = Arsse::$db->subscriptionAdd(Arsse::$user->id, (string) $data['url']);
|
||||
} catch (ExceptionInput $e) {
|
||||
// feed already exists
|
||||
return new EmptyResponse(409);
|
||||
return HTTP::respEmpty(409);
|
||||
} catch (FeedException $e) {
|
||||
// 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 ($data['folderId']) {
|
||||
|
@ -447,9 +446,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $url[1]);
|
||||
} catch (ExceptionInput $e) {
|
||||
// feed does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// rename a feed
|
||||
|
@ -459,22 +458,22 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
// subscription does not exist
|
||||
case 10239: return new EmptyResponse(404);
|
||||
case 10239: return HTTP::respEmpty(404);
|
||||
// name is invalid
|
||||
case 10231:
|
||||
case 10232: return new EmptyResponse(422);
|
||||
case 10232: return HTTP::respEmpty(422);
|
||||
// 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
|
||||
protected function subscriptionMove(array $url, array $data): ResponseInterface {
|
||||
// if no folder is specified this is an error
|
||||
if (!isset($data['folderId'])) {
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
// perform the move
|
||||
try {
|
||||
|
@ -482,22 +481,22 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10239: // subscription does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
case 10235: // folder does not exist
|
||||
case 10237: // folder ID is invalid
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
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
|
||||
protected function subscriptionMarkRead(array $url, array $data): ResponseInterface {
|
||||
if (!ValueInfo::id($data['newestItemId'])) {
|
||||
// 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
|
||||
$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);
|
||||
} catch (ExceptionInput $e) {
|
||||
// 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
|
||||
|
@ -579,7 +578,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
], [$reverse ? "edition desc" : "edition"]);
|
||||
} catch (ExceptionInput $e) {
|
||||
// ID of subscription or folder is not valid
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
$out = [];
|
||||
foreach ($items as $item) {
|
||||
|
@ -593,14 +592,14 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
protected function articleMarkReadAll(array $url, array $data): ResponseInterface {
|
||||
if (!ValueInfo::id($data['newestItemId'])) {
|
||||
// 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
|
||||
$c = (new Context)->hidden(false);
|
||||
$c->editionRange(null, (int) $data['newestItemId']);
|
||||
// perform the operation
|
||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// 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);
|
||||
} catch (ExceptionInput $e) {
|
||||
// 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
|
||||
|
@ -630,9 +629,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
// 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
|
||||
|
@ -646,7 +645,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// 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);
|
||||
} catch (ExceptionInput $e) {
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
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 {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
Service::cleanupPre();
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function cleanupAfter(array $url, array $data): ResponseInterface {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
Service::cleanupPost();
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// return the server version
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST\NextcloudNews;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class Versions implements \JKingWeb\Arsse\REST\Handler {
|
||||
public function __construct() {
|
||||
|
@ -18,12 +18,12 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
|||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
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
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
switch ($req->getMethod()) {
|
||||
case "OPTIONS":
|
||||
// if the request method is OPTIONS, respond accordingly
|
||||
return new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
||||
return HTTP::respEmpty(204, ['Allow' => "HEAD,GET"]);
|
||||
case "GET":
|
||||
// otherwise return the supported versions
|
||||
$out = [
|
||||
|
@ -34,7 +34,7 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
|||
return new Response($out);
|
||||
default:
|
||||
// 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\Context\Context;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||
use JKingWeb\Arsse\AbstractException;
|
||||
use JKingWeb\Arsse\ExceptionType;
|
||||
|
@ -21,7 +22,6 @@ use JKingWeb\Arsse\Feed\Exception as FeedException;
|
|||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public const LEVEL = 15; // emulated API level
|
||||
|
@ -96,11 +96,11 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
if (!preg_match("<^(?:/(?:index\.php)?)?$>D", $req->getRequestTarget())) {
|
||||
// reject paths other than the index
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
if ($req->getMethod() === "OPTIONS") {
|
||||
// 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",
|
||||
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
||||
]);
|
||||
|
@ -125,7 +125,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||
} 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
|
||||
return new EmptyResponse(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
if (strtolower((string) $data['op']) !== "login") {
|
||||
// unless logging in, a session identifier is required
|
||||
|
@ -148,7 +148,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
'content' => $e->getData(),
|
||||
]);
|
||||
} catch (AbstractException $e) {
|
||||
return new EmptyResponse(500);
|
||||
return HTTP::respEmpty(500);
|
||||
}
|
||||
} else {
|
||||
// absence of a request body indicates an error
|
||||
|
|
|
@ -7,10 +7,10 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse\REST\TinyTinyRSS;
|
||||
|
||||
use JKingWeb\Arsse\Arsse;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse as Response;
|
||||
|
||||
class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public function __construct() {
|
||||
|
@ -22,25 +22,25 @@ class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||
} 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
|
||||
return new Response(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
if ($req->getMethod() !== "GET") {
|
||||
// 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])) {
|
||||
return new Response(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
try {
|
||||
$url = Arsse::$db->subscriptionIcon(Arsse::$user->id ?? null, (int) $match[1], false)['url'] ?? null;
|
||||
if (!$url) {
|
||||
return new Response(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
if (($pos = strpos($url, "\r")) !== false || ($pos = strpos($url, "\n")) !== false) {
|
||||
$url = substr($url, 0, $pos);
|
||||
}
|
||||
return new Response(301, ['Location' => $url]);
|
||||
return HTTP::respEmpty(301, ['Location' => $url]);
|
||||
} 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\User;
|
||||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Test\Result;
|
||||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
|
@ -17,7 +18,6 @@ use JKingWeb\Arsse\REST\Fever\API;
|
|||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Laminas\Diactoros\Response\XmlResponse;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\Fever\API<extended> */
|
||||
class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -194,7 +194,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideTokenAuthenticationRequests(): iterable {
|
||||
$success = new JsonResponse(['auth' => 1]);
|
||||
$failure = new JsonResponse(['auth' => 0]);
|
||||
$denied = new EmptyResponse(401);
|
||||
$denied = HTTP::respEmpty(401);
|
||||
return [
|
||||
[false, true, 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 {
|
||||
return [
|
||||
'Not an API request' => ["", "", "POST", null, new EmptyResponse(404)],
|
||||
'Wrong method' => ["api", "", "PUT", null, new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])],
|
||||
'Not an API request' => ["", "", "POST", null, HTTP::respEmpty(404)],
|
||||
'Wrong method' => ["api", "", "PUT", null, HTTP::respEmpty(405, ['Allow' => "OPTIONS,POST"])],
|
||||
'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
|
||||
'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 {
|
||||
$exp = new EmptyResponse(204, [
|
||||
$exp = HTTP::respEmpty(204, [
|
||||
'Allow' => "POST",
|
||||
'Accept' => "application/x-www-form-urlencoded, multipart/form-data",
|
||||
]);
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\TestCase\REST\Miniflux;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\REST\Miniflux\Status;
|
||||
use JKingWeb\Arsse\REST\Miniflux\V1;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\Miniflux\Status */
|
||||
|
@ -23,12 +23,12 @@ class TestStatus extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideRequests(): iterable {
|
||||
return [
|
||||
["/version", "GET", new TextResponse(V1::VERSION)],
|
||||
["/version", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])],
|
||||
["/version", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])],
|
||||
["/version", "POST", HTTP::respEmpty(405, ['Allow' => "HEAD, GET"])],
|
||||
["/version", "OPTIONS", HTTP::respEmpty(204, ['Allow' => "HEAD, GET"])],
|
||||
["/healthcheck", "GET", new TextResponse("OK")],
|
||||
["/healthcheck", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])],
|
||||
["/healthcheck", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])],
|
||||
["/version/", "GET", new EmptyResponse(404)],
|
||||
["/healthcheck", "POST", HTTP::respEmpty(405, ['Allow' => "HEAD, GET"])],
|
||||
["/healthcheck", "OPTIONS", HTTP::respEmpty(204, ['Allow' => "HEAD, GET"])],
|
||||
["/version/", "GET", HTTP::respEmpty(404)],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ use JKingWeb\Arsse\Context\RootContext;
|
|||
use JKingWeb\Arsse\Context\UnionContext;
|
||||
use JKingWeb\Arsse\User;
|
||||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\REST\Miniflux\V1;
|
||||
|
@ -26,7 +27,6 @@ use JKingWeb\Arsse\User\ExceptionInput as UserExceptionInput;
|
|||
use JKingWeb\Arsse\Test\Result;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\Miniflux\V1<extended> */
|
||||
|
@ -102,7 +102,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideAuthResponses */
|
||||
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";
|
||||
if ($token !== null) {
|
||||
$headers = ['X-Auth-Token' => $token];
|
||||
|
@ -133,7 +133,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideInvalidPaths */
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideOptionsRequests */
|
||||
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
||||
$exp = new EmptyResponse(204, [
|
||||
$exp = HTTP::respEmpty(204, [
|
||||
'Allow' => $allow,
|
||||
'Accept' => $accept,
|
||||
]);
|
||||
|
@ -382,7 +382,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$user->method("remove")->willReturn(true);
|
||||
Arsse::$user->expects($this->exactly(1))->method("lookup")->with(2112);
|
||||
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 {
|
||||
|
@ -484,7 +484,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function testDeleteARealCategory(): void {
|
||||
$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->assertMessage(new ErrorResponse("404", 404), $this->req("DELETE", "/categories/47"));
|
||||
$this->dbMock->folderRemove->calledWith("john.doe@example.com", 46);
|
||||
|
@ -497,7 +497,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['id' => 2112],
|
||||
])));
|
||||
$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(
|
||||
$this->dbMock->begin->calledWith(),
|
||||
$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 {
|
||||
$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);
|
||||
}
|
||||
|
||||
|
@ -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' => [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, 2], 'status' => "read"], ['read' => true, 'hidden' => false], new EmptyResponse(204)],
|
||||
[['entry_ids' => [1, 2], 'status' => "unread"], ['read' => false, 'hidden' => false], new EmptyResponse(204)],
|
||||
[['entry_ids' => [1, 2], 'status' => "removed"], ['read' => true, 'hidden' => true], 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], HTTP::respEmpty(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();
|
||||
$c = (new Context)->hidden(false);
|
||||
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)],
|
||||
["/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)],
|
||||
["/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/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 {
|
||||
self::clearData();
|
||||
return [
|
||||
[1, true, new EmptyResponse(204)],
|
||||
[0, false, new EmptyResponse(204)],
|
||||
[1, true, HTTP::respEmpty(204)],
|
||||
[0, false, HTTP::respEmpty(204)],
|
||||
[new ExceptionInput("subjectMissing"), null, new ErrorResponse("404", 404)],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRefreshAFeed(): void {
|
||||
$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);
|
||||
}
|
||||
|
||||
|
@ -948,7 +948,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
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 */
|
||||
|
|
|
@ -11,13 +11,13 @@ use JKingWeb\Arsse\User;
|
|||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Test\Result;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\REST\NextcloudNews\V1_2;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\V1_2<extended> */
|
||||
class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -336,13 +336,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function testSendAuthenticationChallenge(): void {
|
||||
$exp = new EmptyResponse(401);
|
||||
$exp = HTTP::respEmpty(401);
|
||||
$this->assertMessage($exp, $this->req("GET", "/", "", [], false));
|
||||
}
|
||||
|
||||
/** @dataProvider provideInvalidPaths */
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -374,16 +374,16 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
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"]));
|
||||
$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/>', ['Content-Type' => null]));
|
||||
}
|
||||
|
||||
/** @dataProvider provideOptionsRequests */
|
||||
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
||||
$exp = new EmptyResponse(204, [
|
||||
$exp = HTTP::respEmpty(204, [
|
||||
'Allow' => $allow,
|
||||
'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' => "Hardware"], true, "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' => ""], true, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => " "], true, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => null], true, new ExceptionInput("missing"), new EmptyResponse(422)],
|
||||
[['name' => "Software"], true, new ExceptionInput("constraintViolation"), HTTP::respEmpty(409)],
|
||||
[['name' => ""], true, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => " "], true, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => null], true, new ExceptionInput("missing"), HTTP::respEmpty(422)],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRemoveAFolder(): void {
|
||||
$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"));
|
||||
// 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->dbMock->folderRemove->times(2)->calledWith($this->userId, 1);
|
||||
}
|
||||
|
@ -467,12 +467,12 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideFolderRenamings(): array {
|
||||
return [
|
||||
[['name' => "Software"], 1, true, new EmptyResponse(204)],
|
||||
[['name' => "Software"], 2, new ExceptionInput("constraintViolation"), new EmptyResponse(409)],
|
||||
[['name' => "Software"], 3, new ExceptionInput("subjectMissing"), new EmptyResponse(404)],
|
||||
[['name' => ""], 2, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => " "], 2, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => null], 2, new ExceptionInput("missing"), new EmptyResponse(422)],
|
||||
[['name' => "Software"], 1, true, HTTP::respEmpty(204)],
|
||||
[['name' => "Software"], 2, new ExceptionInput("constraintViolation"), HTTP::respEmpty(409)],
|
||||
[['name' => "Software"], 3, new ExceptionInput("subjectMissing"), HTTP::respEmpty(404)],
|
||||
[['name' => ""], 2, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => " "], 2, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => null], 2, new ExceptionInput("missing"), HTTP::respEmpty(422)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -540,19 +540,19 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
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.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.org/news.atom", 'folderId' => 8], new ExceptionInput("constraintViolation"), 4758915, $this->feeds['db'][1], true, new EmptyResponse(409)],
|
||||
[[], $feedException, 0, [], false, new EmptyResponse(422)],
|
||||
[['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, HTTP::respEmpty(409)],
|
||||
[[], $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])],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRemoveASubscription(): void {
|
||||
$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"));
|
||||
// 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->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' => -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
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$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])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$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])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$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])));
|
||||
}
|
||||
|
||||
|
@ -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' => false]))->throws(new ExceptionInput("missing"));
|
||||
$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])));
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$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])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$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])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[6])));
|
||||