Merge pull request #11135 from nupplaphil/bug/halcyon

Add OPTIONS endpoint
This commit is contained in:
Michael Vogel 2022-01-05 07:38:42 +01:00 committed by GitHub
commit 2b74e41312
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 500 additions and 162 deletions

View file

@ -53,7 +53,7 @@ function pubsub_init(App $a)
$nick = ((DI::args()->getArgc() > 1) ? trim(DI::args()->getArgv()[1]) : ''); $nick = ((DI::args()->getArgc() > 1) ? trim(DI::args()->getArgv()[1]) : '');
$contact_id = ((DI::args()->getArgc() > 2) ? intval(DI::args()->getArgv()[2]) : 0 ); $contact_id = ((DI::args()->getArgc() > 2) ? intval(DI::args()->getArgv()[2]) : 0 );
if ($_SERVER['REQUEST_METHOD'] === 'GET') { if (DI::args()->getMethod() === App\Router::GET) {
$hub_mode = trim($_GET['hub_mode'] ?? ''); $hub_mode = trim($_GET['hub_mode'] ?? '');
$hub_topic = trim($_GET['hub_topic'] ?? ''); $hub_topic = trim($_GET['hub_topic'] ?? '');
$hub_challenge = trim($_GET['hub_challenge'] ?? ''); $hub_challenge = trim($_GET['hub_challenge'] ?? '');

View file

@ -43,7 +43,7 @@ function pubsubhubbub_init(App $a) {
// [hub_secret] => af11... // [hub_secret] => af11...
// [hub_topic] => http://friendica.local/dfrn_poll/sazius // [hub_topic] => http://friendica.local/dfrn_poll/sazius
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (DI::args()->getMethod() === App\Router::POST) {
$hub_mode = $_POST['hub_mode'] ?? ''; $hub_mode = $_POST['hub_mode'] ?? '';
$hub_callback = $_POST['hub_callback'] ?? ''; $hub_callback = $_POST['hub_callback'] ?? '';
$hub_verify_token = $_POST['hub_verify_token'] ?? ''; $hub_verify_token = $_POST['hub_verify_token'] ?? '';

View file

@ -52,14 +52,19 @@ class Arguments
* @var int The count of arguments * @var int The count of arguments
*/ */
private $argc; private $argc;
/**
* @var string The used HTTP method
*/
private $method;
public function __construct(string $queryString = '', string $command = '', string $moduleName = '', array $argv = [], int $argc = 0) public function __construct(string $queryString = '', string $command = '', string $moduleName = '', array $argv = [], int $argc = 0, string $method = Router::GET)
{ {
$this->queryString = $queryString; $this->queryString = $queryString;
$this->command = $command; $this->command = $command;
$this->moduleName = $moduleName; $this->moduleName = $moduleName;
$this->argv = $argv; $this->argv = $argv;
$this->argc = $argc; $this->argc = $argc;
$this->method = $method;
} }
/** /**
@ -94,6 +99,14 @@ class Arguments
return $this->argv; return $this->argv;
} }
/**
* @return string The used HTTP method
*/
public function getMethod()
{
return $this->method;
}
/** /**
* @return int The count of arguments of this call * @return int The count of arguments of this call
*/ */
@ -199,6 +212,8 @@ class Arguments
$module = "login"; $module = "login";
} }
return new Arguments($queryString, $command, $module, $argv, $argc); $httpMethod = in_array($server['REQUEST_METHOD'] ?? '', Router::ALLOWED_METHODS) ? $server['REQUEST_METHOD'] : Router::GET;
return new Arguments($queryString, $command, $module, $argv, $argc, $httpMethod);
} }
} }

View file

@ -378,6 +378,12 @@ class Page implements ArrayAccess
*/ */
public function exit(ResponseInterface $response) public function exit(ResponseInterface $response)
{ {
header(sprintf("HTTP/%s %s %s",
$response->getProtocolVersion(),
$response->getStatusCode(),
$response->getReasonPhrase())
);
foreach ($response->getHeaders() as $key => $header) { foreach ($response->getHeaders() as $key => $header) {
if (is_array($header)) { if (is_array($header)) {
$header_str = implode(',', $header); $header_str = implode(',', $header);

View file

@ -37,10 +37,11 @@ use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\LegacyModule; use Friendica\LegacyModule;
use Friendica\Module\HTTPException\MethodNotAllowed; use Friendica\Module\HTTPException\MethodNotAllowed;
use Friendica\Module\HTTPException\PageNotFound; use Friendica\Module\HTTPException\PageNotFound;
use Friendica\Module\Special\Options;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Network\HTTPException\MethodNotAllowedException; use Friendica\Network\HTTPException\MethodNotAllowedException;
use Friendica\Network\HTTPException\NoContentException;
use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\NotFoundException;
use Friendica\Util\Router\FriendicaGroupCountBased;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
/** /**
@ -74,11 +75,6 @@ class Router
/** @var RouteCollector */ /** @var RouteCollector */
protected $routeCollector; protected $routeCollector;
/**
* @var string The HTTP method
*/
private $httpMethod;
/** /**
* @var array Module parameters * @var array Module parameters
*/ */
@ -128,31 +124,18 @@ class Router
*/ */
public function __construct(array $server, string $baseRoutesFilepath, L10n $l10n, ICanCache $cache, ICanLock $lock, IManageConfigValues $config, Arguments $args, LoggerInterface $logger, Dice $dice, RouteCollector $routeCollector = null) public function __construct(array $server, string $baseRoutesFilepath, L10n $l10n, ICanCache $cache, ICanLock $lock, IManageConfigValues $config, Arguments $args, LoggerInterface $logger, Dice $dice, RouteCollector $routeCollector = null)
{ {
$this->baseRoutesFilepath = $baseRoutesFilepath; $this->baseRoutesFilepath = $baseRoutesFilepath;
$this->l10n = $l10n; $this->l10n = $l10n;
$this->cache = $cache; $this->cache = $cache;
$this->lock = $lock; $this->lock = $lock;
$this->args = $args; $this->args = $args;
$this->config = $config; $this->config = $config;
$this->dice = $dice; $this->dice = $dice;
$this->server = $server; $this->server = $server;
$this->logger = $logger; $this->logger = $logger;
$this->dice_profiler_threshold = $config->get('system', 'dice_profiler_threshold', 0); $this->dice_profiler_threshold = $config->get('system', 'dice_profiler_threshold', 0);
$httpMethod = $this->server['REQUEST_METHOD'] ?? self::GET; $this->routeCollector = $routeCollector ?? new RouteCollector(new Std(), new GroupCountBased());
// @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
// @todo Check allowed methods per requested path
if ($httpMethod === static::OPTIONS) {
header('Allow: ' . implode(',', Router::ALLOWED_METHODS));
throw new NoContentException();
}
$this->httpMethod = in_array($httpMethod, self::ALLOWED_METHODS) ? $httpMethod : self::GET;
$this->routeCollector = isset($routeCollector) ?
$routeCollector :
new RouteCollector(new Std(), new GroupCountBased());
if ($this->baseRoutesFilepath && !file_exists($this->baseRoutesFilepath)) { if ($this->baseRoutesFilepath && !file_exists($this->baseRoutesFilepath)) {
throw new HTTPException\InternalServerErrorException('Routes file path does\'n exist.'); throw new HTTPException\InternalServerErrorException('Routes file path does\'n exist.');
@ -171,9 +154,7 @@ class Router
*/ */
public function loadRoutes(array $routes) public function loadRoutes(array $routes)
{ {
$routeCollector = (isset($this->routeCollector) ? $routeCollector = ($this->routeCollector ?? new RouteCollector(new Std(), new GroupCountBased()));
$this->routeCollector :
new RouteCollector(new Std(), new GroupCountBased()));
$this->addRoutes($routeCollector, $routes); $this->addRoutes($routeCollector, $routes);
@ -191,7 +172,10 @@ class Router
if ($this->isGroup($config)) { if ($this->isGroup($config)) {
$this->addGroup($route, $config, $routeCollector); $this->addGroup($route, $config, $routeCollector);
} elseif ($this->isRoute($config)) { } elseif ($this->isRoute($config)) {
$routeCollector->addRoute($config[1], $route, $config[0]); // Always add the OPTIONS endpoint to a route
$httpMethods = (array) $config[1];
$httpMethods[] = Router::OPTIONS;
$routeCollector->addRoute($httpMethods, $route, $config[0]);
} else { } else {
throw new HTTPException\InternalServerErrorException("Wrong route config for route '" . print_r($route, true) . "'"); throw new HTTPException\InternalServerErrorException("Wrong route config for route '" . print_r($route, true) . "'");
} }
@ -274,18 +258,24 @@ class Router
$cmd = $this->args->getCommand(); $cmd = $this->args->getCommand();
$cmd = '/' . ltrim($cmd, '/'); $cmd = '/' . ltrim($cmd, '/');
$dispatcher = new Dispatcher\GroupCountBased($this->getCachedDispatchData()); $dispatcher = new FriendicaGroupCountBased($this->getCachedDispatchData());
$this->parameters = []; $this->parameters = [];
$routeInfo = $dispatcher->dispatch($this->httpMethod, $cmd); // Check if the HTTP method is OPTIONS and return the special Options Module with the possible HTTP methods
if ($routeInfo[0] === Dispatcher::FOUND) { if ($this->args->getMethod() === static::OPTIONS) {
$moduleClass = $routeInfo[1]; $moduleClass = Options::class;
$this->parameters = $routeInfo[2]; $this->parameters = ['allowedMethods' => $dispatcher->getOptions($cmd)];
} elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) {
throw new HTTPException\MethodNotAllowedException($this->l10n->t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1])));
} else { } else {
throw new HTTPException\NotFoundException($this->l10n->t('Page not found.')); $routeInfo = $dispatcher->dispatch($this->args->getMethod(), $cmd);
if ($routeInfo[0] === Dispatcher::FOUND) {
$moduleClass = $routeInfo[1];
$this->parameters = $routeInfo[2];
} elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) {
throw new HTTPException\MethodNotAllowedException($this->l10n->t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1])));
} else {
throw new HTTPException\NotFoundException($this->l10n->t('Page not found.'));
}
} }
return $moduleClass; return $moduleClass;
@ -385,13 +375,13 @@ class Router
*/ */
private function getCachedDispatchData() private function getCachedDispatchData()
{ {
$routerDispatchData = $this->cache->get('routerDispatchData'); $routerDispatchData = $this->cache->get('routerDispatchData');
$lastRoutesFileModifiedTime = $this->cache->get('lastRoutesFileModifiedTime'); $lastRoutesFileModifiedTime = $this->cache->get('lastRoutesFileModifiedTime');
$forceRecompute = false; $forceRecompute = false;
if ($this->baseRoutesFilepath) { if ($this->baseRoutesFilepath) {
$routesFileModifiedTime = filemtime($this->baseRoutesFilepath); $routesFileModifiedTime = filemtime($this->baseRoutesFilepath);
$forceRecompute = $lastRoutesFileModifiedTime != $routesFileModifiedTime; $forceRecompute = $lastRoutesFileModifiedTime != $routesFileModifiedTime;
} }
if (!$forceRecompute && $routerDispatchData) { if (!$forceRecompute && $routerDispatchData) {

View file

@ -179,23 +179,23 @@ abstract class BaseModule implements ICanHandleRequests
public function run(array $request = []): ResponseInterface public function run(array $request = []): ResponseInterface
{ {
// @see https://github.com/tootsuite/mastodon/blob/c3aef491d66aec743a3a53e934a494f653745b61/config/initializers/cors.rb // @see https://github.com/tootsuite/mastodon/blob/c3aef491d66aec743a3a53e934a494f653745b61/config/initializers/cors.rb
if (substr($request['pagename'] ?? '', 0, 12) == '.well-known/') { if (substr($this->args->getQueryString(), 0, 12) == '.well-known/') {
$this->response->setHeader('*', 'Access-Control-Allow-Origin'); $this->response->setHeader('*', 'Access-Control-Allow-Origin');
$this->response->setHeader('*', 'Access-Control-Allow-Headers'); $this->response->setHeader('*', 'Access-Control-Allow-Headers');
$this->response->setHeader(Router::GET, 'Access-Control-Allow-Methods'); $this->response->setHeader(Router::GET, 'Access-Control-Allow-Methods');
$this->response->setHeader('false', 'Access-Control-Allow-Credentials'); $this->response->setHeader('false', 'Access-Control-Allow-Credentials');
} elseif (substr($request['pagename'] ?? '', 0, 8) == 'profile/') { } elseif (substr($this->args->getQueryString(), 0, 8) == 'profile/') {
$this->response->setHeader('*', 'Access-Control-Allow-Origin'); $this->response->setHeader('*', 'Access-Control-Allow-Origin');
$this->response->setHeader('*', 'Access-Control-Allow-Headers'); $this->response->setHeader('*', 'Access-Control-Allow-Headers');
$this->response->setHeader(Router::GET, 'Access-Control-Allow-Methods'); $this->response->setHeader(Router::GET, 'Access-Control-Allow-Methods');
$this->response->setHeader('false', 'Access-Control-Allow-Credentials'); $this->response->setHeader('false', 'Access-Control-Allow-Credentials');
} elseif (substr($request['pagename'] ?? '', 0, 4) == 'api/') { } elseif (substr($this->args->getQueryString(), 0, 4) == 'api/') {
$this->response->setHeader('*', 'Access-Control-Allow-Origin'); $this->response->setHeader('*', 'Access-Control-Allow-Origin');
$this->response->setHeader('*', 'Access-Control-Allow-Headers'); $this->response->setHeader('*', 'Access-Control-Allow-Headers');
$this->response->setHeader(implode(',', Router::ALLOWED_METHODS), 'Access-Control-Allow-Methods'); $this->response->setHeader(implode(',', Router::ALLOWED_METHODS), 'Access-Control-Allow-Methods');
$this->response->setHeader('false', 'Access-Control-Allow-Credentials'); $this->response->setHeader('false', 'Access-Control-Allow-Credentials');
$this->response->setHeader('Link', 'Access-Control-Expose-Headers'); $this->response->setHeader('Link', 'Access-Control-Expose-Headers');
} elseif (substr($request['pagename'] ?? '', 0, 11) == 'oauth/token') { } elseif (substr($this->args->getQueryString(), 0, 11) == 'oauth/token') {
$this->response->setHeader('*', 'Access-Control-Allow-Origin'); $this->response->setHeader('*', 'Access-Control-Allow-Origin');
$this->response->setHeader('*', 'Access-Control-Allow-Headers'); $this->response->setHeader('*', 'Access-Control-Allow-Headers');
$this->response->setHeader(Router::POST, 'Access-Control-Allow-Methods'); $this->response->setHeader(Router::POST, 'Access-Control-Allow-Methods');
@ -211,7 +211,7 @@ abstract class BaseModule implements ICanHandleRequests
$this->profiler->set(microtime(true) - $timestamp, 'init'); $this->profiler->set(microtime(true) - $timestamp, 'init');
switch ($this->server['REQUEST_METHOD'] ?? Router::GET) { switch ($this->args->getMethod()) {
case Router::DELETE: case Router::DELETE:
$this->delete($request); $this->delete($request);
break; break;

View file

@ -31,18 +31,20 @@ interface ICanCreateResponses
*/ */
const X_HEADER = 'X-RESPONSE-TYPE'; const X_HEADER = 'X-RESPONSE-TYPE';
const TYPE_HTML = 'html'; const TYPE_HTML = 'html';
const TYPE_XML = 'xml'; const TYPE_XML = 'xml';
const TYPE_JSON = 'json'; const TYPE_JSON = 'json';
const TYPE_ATOM = 'atom'; const TYPE_ATOM = 'atom';
const TYPE_RSS = 'rss'; const TYPE_RSS = 'rss';
const TYPE_BLANK = 'blank';
const ALLOWED_TYPES = [ const ALLOWED_TYPES = [
self::TYPE_HTML, self::TYPE_HTML,
self::TYPE_XML, self::TYPE_XML,
self::TYPE_JSON, self::TYPE_JSON,
self::TYPE_ATOM, self::TYPE_ATOM,
self::TYPE_RSS self::TYPE_RSS,
self::TYPE_BLANK,
]; ];
/** /**
@ -70,6 +72,16 @@ interface ICanCreateResponses
*/ */
public function setType(string $type, ?string $content_type = null): void; public function setType(string $type, ?string $content_type = null): void;
/**
* Sets the status and the reason for the response
*
* @param int $status The HTTP status code
* @param null|string $reason Reason phrase (when empty a default will be used based on the status code)
*
* @return void
*/
public function setStatus(int $status = 200, ?string $reason = null): void;
/** /**
* Creates a PSR-7 compliant interface * Creates a PSR-7 compliant interface
* @see https://www.php-fig.org/psr/psr-7/ * @see https://www.php-fig.org/psr/psr-7/

View file

@ -21,10 +21,9 @@
namespace Friendica\Core; namespace Friendica\Core;
use Exception;
use Friendica\App;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\DI; use Friendica\DI;
use Friendica\Module\Response;
use Friendica\Network\HTTPException\FoundException; use Friendica\Network\HTTPException\FoundException;
use Friendica\Network\HTTPException\MovedPermanentlyException; use Friendica\Network\HTTPException\MovedPermanentlyException;
use Friendica\Network\HTTPException\TemporaryRedirectException; use Friendica\Network\HTTPException\TemporaryRedirectException;
@ -292,11 +291,9 @@ class System
Logger::notice('xml_status returning non_zero: ' . $st . " message=" . $message); Logger::notice('xml_status returning non_zero: ' . $st . " message=" . $message);
} }
header("Content-type: text/xml"); DI::apiResponse()->setType(Response::TYPE_XML);
DI::apiResponse()->addContent(XML::fromArray(["result" => $result], $xml));
$xmldata = ["result" => $result]; DI::page()->exit(DI::apiResponse()->generate());
echo XML::fromArray($xmldata, $xml);
exit(); exit();
} }
@ -312,11 +309,11 @@ class System
public static function httpExit($val, $message = '', $content = '') public static function httpExit($val, $message = '', $content = '')
{ {
if ($val >= 400) { if ($val >= 400) {
Logger::debug('Exit with error', ['code' => $val, 'message' => $message, 'callstack' => System::callstack(20), 'method' => $_SERVER['REQUEST_METHOD'], 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']); Logger::debug('Exit with error', ['code' => $val, 'message' => $message, 'callstack' => System::callstack(20), 'method' => DI::args()->getMethod(), 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']);
} }
header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $message); DI::apiResponse()->setStatus($val, $message);
DI::apiResponse()->addContent($content);
echo $content; DI::page()->exit(DI::apiResponse()->generate());
exit(); exit();
} }
@ -324,9 +321,9 @@ class System
public static function jsonError($httpCode, $data, $content_type = 'application/json') public static function jsonError($httpCode, $data, $content_type = 'application/json')
{ {
if ($httpCode >= 400) { if ($httpCode >= 400) {
Logger::debug('Exit with error', ['code' => $httpCode, 'content_type' => $content_type, 'callstack' => System::callstack(20), 'method' => $_SERVER['REQUEST_METHOD'], 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']); Logger::debug('Exit with error', ['code' => $httpCode, 'content_type' => $content_type, 'callstack' => System::callstack(20), 'method' => DI::args()->getMethod(), 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']);
} }
header($_SERVER["SERVER_PROTOCOL"] . ' ' . $httpCode); DI::apiResponse()->setStatus($httpCode);
self::jsonExit($data, $content_type); self::jsonExit($data, $content_type);
} }
@ -342,8 +339,9 @@ class System
* @param integer $options JSON options * @param integer $options JSON options
*/ */
public static function jsonExit($x, $content_type = 'application/json', int $options = 0) { public static function jsonExit($x, $content_type = 'application/json', int $options = 0) {
header("Content-type: $content_type"); DI::apiResponse()->setType(Response::TYPE_JSON, $content_type);
echo json_encode($x, $options); DI::apiResponse()->addContent(json_encode($x, $options));
DI::page()->exit(DI::apiResponse()->generate());
exit(); exit();
} }
@ -499,7 +497,7 @@ class System
*/ */
public static function htmlUpdateExit($o) public static function htmlUpdateExit($o)
{ {
header("Content-type: text/html"); DI::apiResponse()->setType(Response::TYPE_HTML);
echo "<!DOCTYPE html><html><body>\r\n"; echo "<!DOCTYPE html><html><body>\r\n";
// We can remove this hack once Internet Explorer recognises HTML5 natively // We can remove this hack once Internet Explorer recognises HTML5 natively
echo "<section>"; echo "<section>";

View file

@ -47,7 +47,7 @@ class Error extends BaseFactory
private function logError(int $errorno, string $error) private function logError(int $errorno, string $error)
{ {
$this->logger->info('API Error', ['no' => $errorno, 'error' => $error, 'method' => $this->server['REQUEST_METHOD'] ?? '', 'command' => $this->args->getQueryString(), 'user-agent' => $this->server['HTTP_USER_AGENT'] ?? '']); $this->logger->info('API Error', ['no' => $errorno, 'error' => $error, 'method' => $this->args->getMethod(), 'command' => $this->args->getQueryString(), 'user-agent' => $this->server['HTTP_USER_AGENT'] ?? '']);
} }
public function RecordNotFound() public function RecordNotFound()

View file

@ -73,6 +73,8 @@ class Followers extends BaseApi
$params['order'] = ['cid']; $params['order'] = ['cid'];
} }
$accounts = [];
$followers = DBA::select('contact-relation', ['relation-cid'], $condition, $params); $followers = DBA::select('contact-relation', ['relation-cid'], $condition, $params);
while ($follower = DBA::fetch($followers)) { while ($follower = DBA::fetch($followers)) {
self::setBoundaries($follower['relation-cid']); self::setBoundaries($follower['relation-cid']);

View file

@ -73,6 +73,8 @@ class Following extends BaseApi
$params['order'] = ['cid']; $params['order'] = ['cid'];
} }
$accounts = [];
$followers = DBA::select('contact-relation', ['cid'], $condition, $params); $followers = DBA::select('contact-relation', ['cid'], $condition, $params);
while ($follower = DBA::fetch($followers)) { while ($follower = DBA::fetch($followers)) {
self::setBoundaries($follower['cid']); self::setBoundaries($follower['cid']);

View file

@ -82,7 +82,7 @@ class BaseApi extends BaseModule
public function run(array $request = [], bool $scopecheck = true): ResponseInterface public function run(array $request = [], bool $scopecheck = true): ResponseInterface
{ {
if ($scopecheck) { if ($scopecheck) {
switch ($this->server['REQUEST_METHOD'] ?? Router::GET) { switch ($this->args->getMethod()) {
case Router::DELETE: case Router::DELETE:
case Router::PATCH: case Router::PATCH:
case Router::POST: case Router::POST:

View file

@ -40,6 +40,10 @@ class Response implements ICanCreateResponses
*/ */
protected $type = self::TYPE_HTML; protected $type = self::TYPE_HTML;
protected $status = 200;
protected $reason = null;
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -92,6 +96,9 @@ class Response implements ICanCreateResponses
} }
switch ($type) { switch ($type) {
case static::TYPE_HTML:
$content_type = $content_type ?? 'text/html';
break;
case static::TYPE_JSON: case static::TYPE_JSON:
$content_type = $content_type ?? 'application/json'; $content_type = $content_type ?? 'application/json';
break; break;
@ -111,6 +118,15 @@ class Response implements ICanCreateResponses
$this->type = $type; $this->type = $type;
} }
/**
* {@inheritDoc}
*/
public function setStatus(int $status = 200, ?string $reason = null): void
{
$this->status = $status;
$this->reason = $reason;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -127,6 +143,6 @@ class Response implements ICanCreateResponses
// Setting the response type as an X-header for direct usage // Setting the response type as an X-header for direct usage
$this->headers[static::X_HEADER] = $this->type; $this->headers[static::X_HEADER] = $this->type;
return new \GuzzleHttp\Psr7\Response(200, $this->headers, $this->content); return new \GuzzleHttp\Psr7\Response($this->status, $this->headers, $this->content, '1.1', $this->reason);
} }
} }

View file

@ -89,7 +89,7 @@ class HTTPException
header($_SERVER["SERVER_PROTOCOL"] . ' ' . $e->getCode() . ' ' . $e->getDescription()); header($_SERVER["SERVER_PROTOCOL"] . ' ' . $e->getCode() . ' ' . $e->getDescription());
if ($e->getCode() >= 400) { if ($e->getCode() >= 400) {
Logger::debug('Exit with error', ['code' => $e->getCode(), 'description' => $e->getDescription(), 'query' => DI::args()->getQueryString(), 'callstack' => System::callstack(20), 'method' => $_SERVER['REQUEST_METHOD'], 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']); Logger::debug('Exit with error', ['code' => $e->getCode(), 'description' => $e->getDescription(), 'query' => DI::args()->getQueryString(), 'callstack' => System::callstack(20), 'method' => DI::args()->getMethod(), 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']);
} }
$tpl = Renderer::getMarkupTemplate('exception.tpl'); $tpl = Renderer::getMarkupTemplate('exception.tpl');

View file

@ -0,0 +1,46 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Module\Special;
use Friendica\App\Router;
use Friendica\BaseModule;
use Friendica\Module\Response;
/**
* Returns the allowed HTTP methods based on the route information
*
* It's a special class which shouldn't be called directly
*
* @see Router::getModuleClass()
*/
class Options extends BaseModule
{
protected function rawContent(array $request = [])
{
$allowedMethods = $this->parameters['AllowedMethods'] ?? Router::ALLOWED_METHODS;
// @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
$this->response->setHeader(implode(',', $allowedMethods), 'Allow');
$this->response->setStatus(204);
$this->response->setType(Response::TYPE_BLANK);
}
}

View file

@ -28,9 +28,7 @@ use Friendica\DI;
use Friendica\Model\APContact; use Friendica\Model\APContact;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Network\HTTPClient\Response\CurlResult;
use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Network\HTTPClient\Client\HttpClientOptions;
use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses;
/** /**
* Implements HTTP Signatures per draft-cavage-http-signatures-07. * Implements HTTP Signatures per draft-cavage-http-signatures-07.
@ -66,7 +64,7 @@ class HTTPSignature
// Decide if $data arrived via controller submission or curl. // Decide if $data arrived via controller submission or curl.
$headers = []; $headers = [];
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']).' '.$_SERVER['REQUEST_URI']; $headers['(request-target)'] = strtolower(DI::args()->getMethod()).' '.$_SERVER['REQUEST_URI'];
foreach ($_SERVER as $k => $v) { foreach ($_SERVER as $k => $v) {
if (strpos($k, 'HTTP_') === 0) { if (strpos($k, 'HTTP_') === 0) {
@ -493,7 +491,7 @@ class HTTPSignature
} }
$headers = []; $headers = [];
$headers['(request-target)'] = strtolower($http_headers['REQUEST_METHOD']) . ' ' . parse_url($http_headers['REQUEST_URI'], PHP_URL_PATH); $headers['(request-target)'] = strtolower(DI::args()->getMethod()) . ' ' . parse_url($http_headers['REQUEST_URI'], PHP_URL_PATH);
// First take every header // First take every header
foreach ($http_headers as $k => $v) { foreach ($http_headers as $k => $v) {

View file

@ -0,0 +1,62 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Util\Router;
use FastRoute\Dispatcher\GroupCountBased;
/**
* Extends the Fast-Router collector for getting the possible HTTP method options for a given URI
*/
class FriendicaGroupCountBased extends GroupCountBased
{
/**
* Returns all possible HTTP methods for a given URI
*
* @param $uri
*
* @return array
*
* @todo Distinguish between an invalid route and the asterisk (*) default route
*/
public function getOptions($uri): array
{
$varRouteData = $this->variableRouteData;
// Find allowed methods for this URI by matching against all other HTTP methods as well
$allowedMethods = [];
foreach ($this->staticRouteMap as $method => $uriMap) {
if (isset($uriMap[$uri])) {
$allowedMethods[] = $method;
}
}
foreach ($varRouteData as $method => $routeData) {
$result = $this->dispatchVariableRoute($routeData, $uri);
if ($result[0] === self::FOUND) {
$allowedMethods[] = $method;
}
}
return $allowedMethods;
}
}

View file

@ -6,6 +6,8 @@
namespace Friendica\Test; namespace Friendica\Test;
use Dice\Dice; use Dice\Dice;
use Friendica\App\Arguments;
use Friendica\App\Router;
use Friendica\Core\Config\ValueObject\Cache; use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Session; use Friendica\Core\Session;
@ -30,10 +32,19 @@ abstract class FixtureTest extends DatabaseTest
{ {
parent::setUp(); parent::setUp();
$server = $_SERVER;
$server['REQUEST_METHOD'] = Router::GET;
$this->dice = (new Dice()) $this->dice = (new Dice())
->addRules(include __DIR__ . '/../static/dependencies.config.php') ->addRules(include __DIR__ . '/../static/dependencies.config.php')
->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true]) ->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true])
->addRule(IHandleSessions::class, ['instanceOf' => Session\Type\Memory::class, 'shared' => true, 'call' => null]); ->addRule(IHandleSessions::class, ['instanceOf' => Session\Type\Memory::class, 'shared' => true, 'call' => null])
->addRule(Arguments::class, [
'instanceOf' => Arguments::class,
'call' => [
['determine', [$server, $_GET], Dice::CHAIN_CALL],
],
]);
DI::init($this->dice); DI::init($this->dice);
/** @var IManageConfigValues $config */ /** @var IManageConfigValues $config */
@ -50,4 +61,20 @@ abstract class FixtureTest extends DatabaseTest
// Load the API dataset for the whole API // Load the API dataset for the whole API
$this->loadFixture(__DIR__ . '/datasets/api.fixture.php', $dba); $this->loadFixture(__DIR__ . '/datasets/api.fixture.php', $dba);
} }
protected function useHttpMethod(string $method = Router::GET)
{
$server = $_SERVER;
$server['REQUEST_METHOD'] = $method;
$this->dice = $this->dice
->addRule(Arguments::class, [
'instanceOf' => Arguments::class,
'call' => [
['determine', [$server, $_GET], Dice::CHAIN_CALL],
],
]);
DI::init($this->dice);
}
} }

View file

@ -32,6 +32,7 @@ class ArgumentsTest extends TestCase
self::assertEquals($assert['command'], $arguments->getCommand()); self::assertEquals($assert['command'], $arguments->getCommand());
self::assertEquals($assert['argv'], $arguments->getArgv()); self::assertEquals($assert['argv'], $arguments->getArgv());
self::assertEquals($assert['argc'], $arguments->getArgc()); self::assertEquals($assert['argc'], $arguments->getArgc());
self::assertEquals($assert['method'], $arguments->getMethod());
self::assertCount($assert['argc'], $arguments->getArgv()); self::assertCount($assert['argc'], $arguments->getArgv());
} }
@ -47,6 +48,7 @@ class ArgumentsTest extends TestCase
'command' => '', 'command' => '',
'argv' => [], 'argv' => [],
'argc' => 0, 'argc' => 0,
'method' => App\Router::GET
], ],
$arguments); $arguments);
} }
@ -60,6 +62,7 @@ class ArgumentsTest extends TestCase
'command' => 'profile/test/it', 'command' => 'profile/test/it',
'argv' => ['profile', 'test', 'it'], 'argv' => ['profile', 'test', 'it'],
'argc' => 3, 'argc' => 3,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'pagename=profile/test/it&arg1=value1&arg2=value2', 'QUERY_STRING' => 'pagename=profile/test/it&arg1=value1&arg2=value2',
@ -74,6 +77,7 @@ class ArgumentsTest extends TestCase
'command' => '~test/it', 'command' => '~test/it',
'argv' => ['~test', 'it'], 'argv' => ['~test', 'it'],
'argc' => 2, 'argc' => 2,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'pagename=~test/it&arg1=value1&arg2=value2', 'QUERY_STRING' => 'pagename=~test/it&arg1=value1&arg2=value2',
@ -88,6 +92,7 @@ class ArgumentsTest extends TestCase
'command' => 'u/test/it', 'command' => 'u/test/it',
'argv' => ['u', 'test', 'it'], 'argv' => ['u', 'test', 'it'],
'argc' => 3, 'argc' => 3,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'pagename=u/test/it&arg1=value1&arg2=value2', 'QUERY_STRING' => 'pagename=u/test/it&arg1=value1&arg2=value2',
@ -102,6 +107,7 @@ class ArgumentsTest extends TestCase
'command' => 'profile/test/it', 'command' => 'profile/test/it',
'argv' => ['profile', 'test', 'it'], 'argv' => ['profile', 'test', 'it'],
'argc' => 3, 'argc' => 3,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'pagename=profile/test/it&arg1=value1&arg2=value2/', 'QUERY_STRING' => 'pagename=profile/test/it&arg1=value1&arg2=value2/',
@ -116,6 +122,7 @@ class ArgumentsTest extends TestCase
'command' => 'profile/test/it', 'command' => 'profile/test/it',
'argv' => ['profile', 'test', 'it'], 'argv' => ['profile', 'test', 'it'],
'argc' => 3, 'argc' => 3,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'wrong=profile/test/it&arg1=value1&arg2=value2/', 'QUERY_STRING' => 'wrong=profile/test/it&arg1=value1&arg2=value2/',
@ -130,6 +137,7 @@ class ArgumentsTest extends TestCase
'command' => 'notvalid/it', 'command' => 'notvalid/it',
'argv' => ['notvalid', 'it'], 'argv' => ['notvalid', 'it'],
'argc' => 2, 'argc' => 2,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'pagename=notvalid/it&arg1=value1&arg2=value2/', 'QUERY_STRING' => 'pagename=notvalid/it&arg1=value1&arg2=value2/',
@ -143,6 +151,7 @@ class ArgumentsTest extends TestCase
'command' => '', 'command' => '',
'argv' => [], 'argv' => [],
'argc' => 0, 'argc' => 0,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'arg1=value1&arg2=value2/', 'QUERY_STRING' => 'arg1=value1&arg2=value2/',
@ -156,6 +165,7 @@ class ArgumentsTest extends TestCase
'command' => 'api/call.json', 'command' => 'api/call.json',
'argv' => ['api', 'call.json'], 'argv' => ['api', 'call.json'],
'argc' => 2, 'argc' => 2,
'method' => App\Router::GET,
], ],
'server' => [ 'server' => [
'QUERY_STRING' => 'pagename=api/call.json', 'QUERY_STRING' => 'pagename=api/call.json',
@ -164,6 +174,22 @@ class ArgumentsTest extends TestCase
'pagename' => 'api/call.json' 'pagename' => 'api/call.json'
], ],
], ],
'withHTTPMethod' => [
'assert' => [
'queryString' => 'api/call.json',
'command' => 'api/call.json',
'argv' => ['api', 'call.json'],
'argc' => 2,
'method' => App\Router::POST,
],
'server' => [
'QUERY_STRING' => 'pagename=api/call.json',
'REQUEST_METHOD' => App\Router::POST,
],
'get' => [
'pagename' => 'api/call.json'
],
],
]; ];
} }

View file

@ -34,7 +34,7 @@ class SearchTest extends ApiTest
{ {
$directMessage = new DirectMessage(new NullLogger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(new NullLogger(), DI::dba(), DI::twitterUser());
$response = (new Search($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Search($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);
@ -52,7 +52,7 @@ class SearchTest extends ApiTest
$directMessage = new DirectMessage(new NullLogger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(new NullLogger(), DI::dba(), DI::twitterUser());
$response = (new Search($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Search($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'searchstring' => 'item_body' 'searchstring' => 'item_body'
]); ]);
@ -73,7 +73,7 @@ class SearchTest extends ApiTest
{ {
$directMessage = new DirectMessage(new NullLogger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(new NullLogger(), DI::dba(), DI::twitterUser());
$response = (new Search($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Search($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'searchstring' => 'test' 'searchstring' => 'test'
]); ]);

View file

@ -29,10 +29,17 @@ use Friendica\Test\src\Module\Api\ApiTest;
class DeleteTest extends ApiTest class DeleteTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
public function testEmpty() public function testEmpty()
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]))->run(); (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))->run();
} }
public function testWithoutAuthenticatedUser() public function testWithoutAuthenticatedUser()
@ -43,14 +50,14 @@ class DeleteTest extends ApiTest
public function testWrong() public function testWrong()
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]))->run(['photo_id' => 1]); (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))->run(['photo_id' => 1]);
} }
public function testValidWithPost() public function testValidWithPost()
{ {
$this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba()); $this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba());
$response = (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'photo_id' => '709057080661a283a6aa598501504178' 'photo_id' => '709057080661a283a6aa598501504178'
]); ]);
@ -65,7 +72,7 @@ class DeleteTest extends ApiTest
{ {
$this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba()); $this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba());
$response = (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'photo_id' => '709057080661a283a6aa598501504178' 'photo_id' => '709057080661a283a6aa598501504178'
]); ]);

View file

@ -29,10 +29,17 @@ use Friendica\Test\src\Module\Api\ApiTest;
class DeleteTest extends ApiTest class DeleteTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
public function testEmpty() public function testEmpty()
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -40,7 +47,7 @@ class DeleteTest extends ApiTest
public function testWrong() public function testWrong()
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'album' => 'album_name' 'album' => 'album_name'
]); ]);
@ -50,7 +57,7 @@ class DeleteTest extends ApiTest
{ {
$this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba()); $this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba());
$response = (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'album' => 'test_album'] 'album' => 'test_album']
); );

View file

@ -29,17 +29,24 @@ use Friendica\Test\src\Module\Api\ApiTest;
class UpdateTest extends ApiTest class UpdateTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
public function testEmpty() public function testEmpty()
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
public function testTooFewArgs() public function testTooFewArgs()
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'album' => 'album_name' 'album' => 'album_name'
]); ]);
@ -48,7 +55,7 @@ class UpdateTest extends ApiTest
public function testWrongUpdate() public function testWrongUpdate()
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'album' => 'album_name', 'album' => 'album_name',
'album_new' => 'album_name' 'album_new' => 'album_name'
@ -64,7 +71,7 @@ class UpdateTest extends ApiTest
{ {
$this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba()); $this->loadFixture(__DIR__ . '/../../../../../datasets/photo/photo.fixture.php', DI::dba());
$response = (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'album' => 'test_album', 'album' => 'test_album',
'album_new' => 'test_album_2' 'album_new' => 'test_album_2'

View file

@ -17,9 +17,8 @@ class ConfigTest extends ApiTest
{ {
DI::config()->set('system', 'ssl_policy', BaseURL::SSL_POLICY_FULL); DI::config()->set('system', 'ssl_policy', BaseURL::SSL_POLICY_FULL);
$response = (new Config(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Config(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);
self::assertEquals('localhost', $json->site->server); self::assertEquals('localhost', $json->site->server);

View file

@ -16,7 +16,7 @@ class VerifyCredentialsTest extends ApiTest
*/ */
public function testApiAccountVerifyCredentials() public function testApiAccountVerifyCredentials()
{ {
$response = (new VerifyCredentials(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new VerifyCredentials(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);

View file

@ -12,7 +12,7 @@ class RateLimitStatusTest extends ApiTest
{ {
public function testWithJson() public function testWithJson()
{ {
$response = (new RateLimitStatus(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new RateLimitStatus(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run(); ->run();
$result = $this->toJson($response); $result = $this->toJson($response);

View file

@ -14,7 +14,9 @@ class UpdateProfileTest extends ApiTest
*/ */
public function testApiAccountUpdateProfile() public function testApiAccountUpdateProfile()
{ {
$response = (new UpdateProfile(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST], ['extension' => 'json'])) $this->useHttpMethod(Router::POST);
$response = (new UpdateProfile(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'name' => 'new_name', 'name' => 'new_name',
'description' => 'new_description' 'description' => 'new_description'

View file

@ -14,7 +14,7 @@ class ListsTest extends ApiTest
*/ */
public function testApiStatusesFWithBlocks() public function testApiStatusesFWithBlocks()
{ {
$response = (new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);

View file

@ -21,7 +21,7 @@ class AllTest extends ApiTest
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new All($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new All($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);

View file

@ -19,7 +19,7 @@ class ConversationTest extends ApiTest
{ {
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new Conversation($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new Conversation($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'friendica_verbose' => true, 'friendica_verbose' => true,
]); ]);

View file

@ -18,7 +18,7 @@ class DestroyTest extends ApiTest
public function testApiDirectMessagesDestroy() public function testApiDirectMessagesDestroy()
{ {
$this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
(new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run(); ->run();
} }
@ -29,7 +29,7 @@ class DestroyTest extends ApiTest
*/ */
public function testApiDirectMessagesDestroyWithVerbose() public function testApiDirectMessagesDestroyWithVerbose()
{ {
$response = (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'friendica_verbose' => true, 'friendica_verbose' => true,
]); ]);
@ -65,7 +65,7 @@ class DestroyTest extends ApiTest
public function testApiDirectMessagesDestroyWithId() public function testApiDirectMessagesDestroyWithId()
{ {
$this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
(new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'id' => 1 'id' => 1
]); ]);
@ -78,7 +78,7 @@ class DestroyTest extends ApiTest
*/ */
public function testApiDirectMessagesDestroyWithIdAndVerbose() public function testApiDirectMessagesDestroyWithIdAndVerbose()
{ {
$response = (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'id' => 1, 'id' => 1,
'friendica_parenturi' => 'parent_uri', 'friendica_parenturi' => 'parent_uri',
@ -102,7 +102,7 @@ class DestroyTest extends ApiTest
$ids = DBA::selectToArray('mail', ['id']); $ids = DBA::selectToArray('mail', ['id']);
$id = $ids[0]['id']; $id = $ids[0]['id'];
$response = (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new Destroy(DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'id' => $id, 'id' => $id,
'friendica_verbose' => true, 'friendica_verbose' => true,

View file

@ -21,7 +21,7 @@ class InboxTest extends ApiTest
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new Inbox($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new Inbox($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);

View file

@ -19,7 +19,7 @@ class NewDMTest extends ApiTest
{ {
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run(); ->run();
self::assertEmpty((string)$response->getBody()); self::assertEmpty((string)$response->getBody());
@ -51,7 +51,7 @@ class NewDMTest extends ApiTest
{ {
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'text' => 'message_text', 'text' => 'message_text',
'user_id' => 43 'user_id' => 43
@ -73,7 +73,7 @@ class NewDMTest extends ApiTest
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'text' => 'message_text', 'text' => 'message_text',
'user_id' => 44 'user_id' => 44
@ -97,7 +97,7 @@ class NewDMTest extends ApiTest
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'text' => 'message_text', 'text' => 'message_text',
'user_id' => 44, 'user_id' => 44,
@ -123,7 +123,7 @@ class NewDMTest extends ApiTest
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'rss'])) $response = (new NewDM($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'rss']))
->run([ ->run([
'text' => 'message_text', 'text' => 'message_text',
'user_id' => 44, 'user_id' => 44,

View file

@ -19,7 +19,7 @@ class SentTest extends ApiTest
{ {
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new Sent($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json'])) $response = (new Sent($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']))
->run([ ->run([
'friendica_verbose' => true, 'friendica_verbose' => true,
]); ]);
@ -39,7 +39,7 @@ class SentTest extends ApiTest
{ {
$directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser()); $directMessage = new DirectMessage(DI::logger(), DI::dba(), DI::twitterUser());
$response = (new Sent($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'rss'])) $response = (new Sent($directMessage, DI::dba(), DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'rss']))
->run(); ->run();
self::assertXml((string)$response->getBody(), 'direct-messages'); self::assertXml((string)$response->getBody(), 'direct-messages');

View file

@ -11,6 +11,13 @@ use Friendica\Test\src\Module\Api\ApiTest;
class CreateTest extends ApiTest class CreateTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
/** /**
* Test the api_favorites_create_destroy() function with an invalid ID. * Test the api_favorites_create_destroy() function with an invalid ID.
* *
@ -20,7 +27,7 @@ class CreateTest extends ApiTest
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -31,7 +38,7 @@ class CreateTest extends ApiTest
*/ */
public function testApiFavoritesCreateDestroyWithCreateAction() public function testApiFavoritesCreateDestroyWithCreateAction()
{ {
$response = (new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'id' => 3 'id' => 3
]); ]);
@ -48,7 +55,7 @@ class CreateTest extends ApiTest
*/ */
public function testApiFavoritesCreateDestroyWithCreateActionAndRss() public function testApiFavoritesCreateDestroyWithCreateActionAndRss()
{ {
$response = (new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST], ['extension' => ICanCreateResponses::TYPE_RSS])) $response = (new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => ICanCreateResponses::TYPE_RSS]))
->run([ ->run([
'id' => 3 'id' => 3
]); ]);

View file

@ -10,6 +10,13 @@ use Friendica\Test\src\Module\Api\ApiTest;
class DestroyTest extends ApiTest class DestroyTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
/** /**
* Test the api_favorites_create_destroy() function with an invalid ID. * Test the api_favorites_create_destroy() function with an invalid ID.
* *
@ -19,7 +26,7 @@ class DestroyTest extends ApiTest
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -30,7 +37,7 @@ class DestroyTest extends ApiTest
*/ */
public function testApiFavoritesCreateDestroyWithDestroyAction() public function testApiFavoritesCreateDestroyWithDestroyAction()
{ {
$response = (new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'id' => 3 'id' => 3
]); ]);

View file

@ -17,7 +17,7 @@ class FavoritesTest extends ApiTest
*/ */
public function testApiFavorites() public function testApiFavorites()
{ {
$response = (new Favorites(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Favorites(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'page' => -1, 'page' => -1,
'max_id' => 10, 'max_id' => 10,
@ -37,7 +37,7 @@ class FavoritesTest extends ApiTest
*/ */
public function testApiFavoritesWithRss() public function testApiFavoritesWithRss()
{ {
$response = (new Favorites(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], [ $response = (new Favorites(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], [
'extension' => ICanCreateResponses::TYPE_RSS 'extension' => ICanCreateResponses::TYPE_RSS
]))->run(); ]))->run();

View file

@ -14,7 +14,7 @@ class ListsTest extends ApiTest
*/ */
public function testApiStatusesFWithFollowers() public function testApiStatusesFWithFollowers()
{ {
$response = (new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);

View file

@ -16,7 +16,7 @@ class ListsTest extends ApiTest
*/ */
public function testApiStatusesFWithFriends() public function testApiStatusesFWithFriends()
{ {
$response = (new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);

View file

@ -16,7 +16,7 @@ class IncomingTest extends ApiTest
*/ */
public function testApiFriendshipsIncoming() public function testApiFriendshipsIncoming()
{ {
$response = (new Incoming(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Incoming(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);

View file

@ -19,7 +19,7 @@ class StatusesTest extends ApiTest
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Statuses(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) (new Statuses(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -28,7 +28,7 @@ class StatusesTest extends ApiTest
*/ */
public function testApiListsStatusesWithListId() public function testApiListsStatusesWithListId()
{ {
$response = (new Statuses(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Statuses(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'list_id' => 1, 'list_id' => 1,
'page' => -1, 'page' => -1,
@ -48,7 +48,7 @@ class StatusesTest extends ApiTest
*/ */
public function testApiListsStatusesWithListIdAndRss() public function testApiListsStatusesWithListIdAndRss()
{ {
$response = (new Statuses(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'rss'])) $response = (new Statuses(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'rss']))
->run([ ->run([
'list_id' => 1 'list_id' => 1
]); ]);

View file

@ -13,6 +13,13 @@ use Friendica\Test\Util\AuthTestConfig;
class UploadTest extends ApiTest class UploadTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
/** /**
* Test the \Friendica\Module\Api\Twitter\Media\Upload module. * Test the \Friendica\Module\Api\Twitter\Media\Upload module.
*/ */
@ -20,7 +27,7 @@ class UploadTest extends ApiTest
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -34,7 +41,7 @@ class UploadTest extends ApiTest
$this->expectException(UnauthorizedException::class); $this->expectException(UnauthorizedException::class);
AuthTestConfig::$authenticated = false; AuthTestConfig::$authenticated = false;
(new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -53,7 +60,7 @@ class UploadTest extends ApiTest
] ]
]; ];
(new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -76,7 +83,7 @@ class UploadTest extends ApiTest
] ]
]; ];
$response = (new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$media = $this->toJson($response); $media = $this->toJson($response);

View file

@ -10,6 +10,13 @@ use Friendica\Test\src\Module\Api\ApiTest;
class DestroyTest extends ApiTest class DestroyTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
/** /**
* Test the api_statuses_destroy() function. * Test the api_statuses_destroy() function.
* *
@ -19,7 +26,7 @@ class DestroyTest extends ApiTest
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -45,7 +52,7 @@ class DestroyTest extends ApiTest
*/ */
public function testApiStatusesDestroyWithId() public function testApiStatusesDestroyWithId()
{ {
$response = (new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'id' => 1 'id' => 1
]); ]);

View file

@ -17,7 +17,7 @@ class MentionsTest extends ApiTest
*/ */
public function testApiStatusesMentions() public function testApiStatusesMentions()
{ {
$response = (new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'max_id' => 10 'max_id' => 10
]); ]);
@ -35,7 +35,7 @@ class MentionsTest extends ApiTest
*/ */
public function testApiStatusesMentionsWithNegativePage() public function testApiStatusesMentionsWithNegativePage()
{ {
$response = (new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'page' => -2 'page' => -2
]); ]);
@ -67,7 +67,7 @@ class MentionsTest extends ApiTest
*/ */
public function testApiStatusesMentionsWithRss() public function testApiStatusesMentionsWithRss()
{ {
$response = (new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => ICanCreateResponses::TYPE_RSS])) $response = (new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => ICanCreateResponses::TYPE_RSS]))
->run([ ->run([
'page' => -2 'page' => -2
]); ]);

View file

@ -17,7 +17,7 @@ class NetworkPublicTimelineTest extends ApiTest
*/ */
public function testApiStatusesNetworkpublicTimeline() public function testApiStatusesNetworkpublicTimeline()
{ {
$response = (new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'max_id' => 10 'max_id' => 10
]); ]);
@ -39,7 +39,7 @@ class NetworkPublicTimelineTest extends ApiTest
*/ */
public function testApiStatusesNetworkpublicTimelineWithNegativePage() public function testApiStatusesNetworkpublicTimelineWithNegativePage()
{ {
$response = (new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'page' => -2 'page' => -2
]); ]);
@ -75,7 +75,7 @@ class NetworkPublicTimelineTest extends ApiTest
*/ */
public function testApiStatusesNetworkpublicTimelineWithRss() public function testApiStatusesNetworkpublicTimelineWithRss()
{ {
$response = (new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], [ $response = (new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], [
'extension' => ICanCreateResponses::TYPE_RSS 'extension' => ICanCreateResponses::TYPE_RSS
]))->run([ ]))->run([
'page' => -2 'page' => -2

View file

@ -10,6 +10,13 @@ use Friendica\Test\src\Module\Api\ApiTest;
class RetweetTest extends ApiTest class RetweetTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
/** /**
* Test the api_statuses_repeat() function. * Test the api_statuses_repeat() function.
* *
@ -19,7 +26,7 @@ class RetweetTest extends ApiTest
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) (new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -45,7 +52,7 @@ class RetweetTest extends ApiTest
*/ */
public function testApiStatusesRepeatWithId() public function testApiStatusesRepeatWithId()
{ {
$response = (new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'id' => 1 'id' => 1
]); ]);
@ -62,7 +69,7 @@ class RetweetTest extends ApiTest
*/ */
public function testApiStatusesRepeatWithSharedId() public function testApiStatusesRepeatWithSharedId()
{ {
$response = (new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'id' => 5 'id' => 5
]); ]);

View file

@ -20,7 +20,7 @@ class ShowTest extends ApiTest
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -31,7 +31,7 @@ class ShowTest extends ApiTest
*/ */
public function testApiStatusesShowWithId() public function testApiStatusesShowWithId()
{ {
$response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'id' => 1 'id' => 1
]); ]);
@ -49,7 +49,7 @@ class ShowTest extends ApiTest
*/ */
public function testApiStatusesShowWithConversation() public function testApiStatusesShowWithConversation()
{ {
$response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'id' => 1, 'id' => 1,
'conversation' => 1 'conversation' => 1

View file

@ -9,6 +9,13 @@ use Friendica\Test\src\Module\Api\ApiTest;
class UpdateTest extends ApiTest class UpdateTest extends ApiTest
{ {
protected function setUp(): void
{
parent::setUp();
$this->useHttpMethod(Router::POST);
}
/** /**
* Test the api_statuses_update() function. * Test the api_statuses_update() function.
* *
@ -28,7 +35,7 @@ class UpdateTest extends ApiTest
] ]
]; ];
$response = (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'status' => 'Status content #friendica', 'status' => 'Status content #friendica',
'in_reply_to_status_id' => 0, 'in_reply_to_status_id' => 0,
@ -50,7 +57,7 @@ class UpdateTest extends ApiTest
*/ */
public function testApiStatusesUpdateWithHtml() public function testApiStatusesUpdateWithHtml()
{ {
$response = (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST])) $response = (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'htmlstatus' => '<b>Status content</b>', 'htmlstatus' => '<b>Status content</b>',
]); ]);

View file

@ -17,7 +17,7 @@ class UserTimelineTest extends ApiTest
*/ */
public function testApiStatusesUserTimeline() public function testApiStatusesUserTimeline()
{ {
$response = (new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'user_id' => 42, 'user_id' => 42,
'max_id' => 10, 'max_id' => 10,
@ -42,7 +42,7 @@ class UserTimelineTest extends ApiTest
*/ */
public function testApiStatusesUserTimelineWithNegativePage() public function testApiStatusesUserTimelineWithNegativePage()
{ {
$response = (new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'user_id' => 42, 'user_id' => 42,
'page' => -2, 'page' => -2,
@ -65,7 +65,7 @@ class UserTimelineTest extends ApiTest
*/ */
public function testApiStatusesUserTimelineWithRss() public function testApiStatusesUserTimelineWithRss()
{ {
$response = (new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], [ $response = (new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], [
'extension' => ICanCreateResponses::TYPE_RSS 'extension' => ICanCreateResponses::TYPE_RSS
]))->run(); ]))->run();

View file

@ -19,7 +19,7 @@ class LookupTest extends ApiTest
{ {
$this->expectException(NotFoundException::class); $this->expectException(NotFoundException::class);
(new Lookup(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) (new Lookup(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
@ -30,7 +30,7 @@ class LookupTest extends ApiTest
*/ */
public function testApiUsersLookupWithUserId() public function testApiUsersLookupWithUserId()
{ {
$respone = (new Lookup(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $respone = (new Lookup(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'user_id' => static::OTHER_USER['id'] 'user_id' => static::OTHER_USER['id']
]); ]);

View file

@ -18,7 +18,7 @@ class SearchTest extends ApiTest
*/ */
public function testApiUsersSearch() public function testApiUsersSearch()
{ {
$respone = (new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $respone = (new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run([ ->run([
'q' => static::OTHER_USER['name'] 'q' => static::OTHER_USER['name']
]); ]);
@ -35,7 +35,7 @@ class SearchTest extends ApiTest
*/ */
public function testApiUsersSearchWithXml() public function testApiUsersSearchWithXml()
{ {
$respone = (new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], [ $respone = (new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], [
'extension' => ICanCreateResponses::TYPE_XML 'extension' => ICanCreateResponses::TYPE_XML
]))->run([ ]))->run([
'q' => static::OTHER_USER['name'] 'q' => static::OTHER_USER['name']
@ -53,7 +53,7 @@ class SearchTest extends ApiTest
{ {
$this->expectException(BadRequestException::class); $this->expectException(BadRequestException::class);
(new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) (new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
} }
} }

View file

@ -17,7 +17,7 @@ class ShowTest extends ApiTest
*/ */
public function testApiUsersShow() public function testApiUsersShow()
{ {
$response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET])) $response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))
->run(); ->run();
$json = $this->toJson($response); $json = $this->toJson($response);
@ -37,7 +37,7 @@ class ShowTest extends ApiTest
*/ */
public function testApiUsersShowWithXml() public function testApiUsersShowWithXml()
{ {
$response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], [ $response = (new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], [
'extension' => ICanCreateResponses::TYPE_XML 'extension' => ICanCreateResponses::TYPE_XML
]))->run(); ]))->run();

View file

@ -0,0 +1,46 @@
<?php
namespace Friendica\Test\src\Module\Special;
use Friendica\App\Router;
use Friendica\Capabilities\ICanCreateResponses;
use Friendica\DI;
use Friendica\Module\Special\Options;
use Friendica\Test\FixtureTest;
class OptionsTest extends FixtureTest
{
public function testOptionsAll()
{
$this->useHttpMethod(Router::OPTIONS);
$response = (new Options(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), []))->run();
self::assertEmpty((string)$response->getBody());
self::assertEquals(204, $response->getStatusCode());
self::assertEquals('No Content', $response->getReasonPhrase());
self::assertEquals([
'Allow' => [implode(',', Router::ALLOWED_METHODS)],
ICanCreateResponses::X_HEADER => ['blank'],
], $response->getHeaders());
self::assertEquals(implode(',', Router::ALLOWED_METHODS), $response->getHeaderLine('Allow'));
}
public function testOptionsSpecific()
{
$this->useHttpMethod(Router::OPTIONS);
$response = (new Options(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], [
'AllowedMethods' => [Router::GET, Router::POST],
]))->run();
self::assertEmpty((string)$response->getBody());
self::assertEquals(204, $response->getStatusCode());
self::assertEquals('No Content', $response->getReasonPhrase());
self::assertEquals([
'Allow' => [implode(',', [Router::GET, Router::POST])],
ICanCreateResponses::X_HEADER => ['blank'],
], $response->getHeaders());
self::assertEquals(implode(',', [Router::GET, Router::POST]), $response->getHeaderLine('Allow'));
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Friendica\Test\src\Util\Router;
use FastRoute\DataGenerator\GroupCountBased;
use FastRoute\RouteCollector;
use FastRoute\RouteParser\Std;
use Friendica\Module\Special\Options;
use Friendica\Test\MockedTest;
use Friendica\Util\Router\FriendicaGroupCountBased;
class FriendicaGroupCountBasedTest extends MockedTest
{
public function testOptions()
{
$collector = new RouteCollector(new Std(), new GroupCountBased());
$collector->addRoute('GET', '/get', Options::class);
$collector->addRoute('POST', '/post', Options::class);
$collector->addRoute('GET', '/multi', Options::class);
$collector->addRoute('POST', '/multi', Options::class);
$dispatcher = new FriendicaGroupCountBased($collector->getData());
self::assertEquals(['GET'], $dispatcher->getOptions('/get'));
self::assertEquals(['POST'], $dispatcher->getOptions('/post'));
self::assertEquals(['GET', 'POST'], $dispatcher->getOptions('/multi'));
}
}