use Exception;
use Friendica\App\Arguments;
use Friendica\App\BaseURL;
+use Friendica\Capabilities\ICanCreateResponses;
use Friendica\Core\Config\Factory\Config;
use Friendica\Module\Maintenance;
use Friendica\Security\Authentication;
use Friendica\Util\HTTPSignature;
use Friendica\Util\Profiler;
use Friendica\Util\Strings;
+use GuzzleHttp\Psr7\Response;
use Psr\Log\LoggerInterface;
/**
// Let the module run it's internal process (init, get, post, ...)
$response = $module->run($_POST, $_REQUEST);
- if ($response->getType() === $response::TYPE_HTML) {
+ if ($response->getHeaderLine('X-RESPONSE-TYPE') === ICanCreateResponses::TYPE_HTML) {
$page->run($this, $this->baseURL, $this->args, $this->mode, $response, $this->l10n, $this->profiler, $this->config, $pconfig);
} else {
$page->exit($response);
use DOMDocument;
use DOMXPath;
use Friendica\App;
-use Friendica\Capabilities\IRespondToRequests;
use Friendica\Content\Nav;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
use Friendica\Util\Network;
use Friendica\Util\Strings;
use Friendica\Util\Profiler;
+use Psr\Http\Message\ResponseInterface;
/**
* Contains the page specific environment variables for the current Page
* - module content
* - hooks for content
*
- * @param IRespondToRequests $response The Module response class
+ * @param ResponseInterface $response The Module response class
* @param Mode $mode The Friendica execution mode
*
* @throws HTTPException\InternalServerErrorException
*/
- private function initContent(IRespondToRequests $response, Mode $mode)
+ private function initContent(ResponseInterface $response, Mode $mode)
{
// initialise content region
if ($mode->isNormal()) {
Hook::callAll('page_content_top', $this->page['content']);
}
- $this->page['content'] .= $response->getContent();
+ $this->page['content'] .= (string)$response->getBody();
}
/**
/**
* Directly exit with the current response (include setting all headers)
*
- * @param IRespondToRequests $response
+ * @param ResponseInterface $response
*/
- public function exit(IRespondToRequests $response)
+ public function exit(ResponseInterface $response)
{
foreach ($response->getHeaders() as $key => $header) {
+ if (is_array($header)) {
+ $header_str = implode(',', $header);
+ }
if (empty($key)) {
- header($header);
+ header($header_str);
} else {
- header("$key: $header");
+ header("$key: $header_str");
}
}
- echo $response->getContent();
+ echo $response->getBody();
}
/**
* @param BaseURL $baseURL The Friendica Base URL
* @param Arguments $args The Friendica App arguments
* @param Mode $mode The current node mode
- * @param IRespondToRequests $response The Response of the module class, including type, content & headers
+ * @param ResponseInterface $response The Response of the module class, including type, content & headers
* @param L10n $l10n The l10n language class
* @param IManageConfigValues $config The Configuration of this node
* @param IManagePersonalConfigValues $pconfig The personal/user configuration
*
* @throws HTTPException\InternalServerErrorException|HTTPException\ServiceUnavailableException
*/
- public function run(App $app, BaseURL $baseURL, Arguments $args, Mode $mode, IRespondToRequests $response, L10n $l10n, Profiler $profiler, IManageConfigValues $config, IManagePersonalConfigValues $pconfig)
+ public function run(App $app, BaseURL $baseURL, Arguments $args, Mode $mode, ResponseInterface $response, L10n $l10n, Profiler $profiler, IManageConfigValues $config, IManagePersonalConfigValues $pconfig)
{
$moduleName = $args->getModuleName();
use Friendica\App\Router;
use Friendica\Capabilities\ICanHandleRequests;
use Friendica\Capabilities\ICanCreateResponses;
-use Friendica\Capabilities\IRespondToRequests;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Module\Special\HTTPException as ModuleHTTPException;
use Friendica\Network\HTTPException;
use Friendica\Util\Profiler;
+use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
/**
/**
* {@inheritDoc}
*/
- public function run(array $post = [], array $request = []): IRespondToRequests
+ public function run(array $post = [], array $request = []): ResponseInterface
{
// @see https://github.com/tootsuite/mastodon/blob/c3aef491d66aec743a3a53e934a494f653745b61/config/initializers/cors.rb
if (substr($request['pagename'] ?? '', 0, 12) == '.well-known/') {
break;
}
- return $this->response;
+ return $this->response->generate();
}
/*
namespace Friendica\Capabilities;
use Friendica\Network\HTTPException\InternalServerErrorException;
+use Psr\Http\Message\ResponseInterface;
-interface ICanCreateResponses extends IRespondToRequests
+interface ICanCreateResponses
{
+ const TYPE_HTML = 'html';
+ const TYPE_XML = 'xml';
+ const TYPE_JSON = 'json';
+ const TYPE_ATOM = 'atom';
+ const TYPE_RSS = 'rss';
+
+ const ALLOWED_TYPES = [
+ self::TYPE_HTML,
+ self::TYPE_XML,
+ self::TYPE_JSON,
+ self::TYPE_ATOM,
+ self::TYPE_RSS
+ ];
+
/**
* Adds a header entry to the module response
*
* @throws InternalServerErrorException
*/
public function setType(string $type, ?string $content_type = null): void;
+
+ /**
+ * Creates a PSR-7 compliant interface
+ * @see https://www.php-fig.org/psr/psr-7/
+ *
+ * @return ResponseInterface
+ */
+ public function generate(): ResponseInterface;
}
namespace Friendica\Capabilities;
use Friendica\Network\HTTPException;
+use Psr\Http\Message\ResponseInterface;
/**
* This interface provides the capability to handle requests from clients and returns the desired outcome
* @param array $post The $_POST content (in case of POST)
* @param array $request The $_REQUEST content (in case of GET, POST)
*
- * @return IRespondToRequests responding to the request handling
+ * @return ResponseInterface responding to the request handling
*
* @throws HTTPException\InternalServerErrorException
*/
- public function run(array $post = [], array $request = []): IRespondToRequests;
+ public function run(array $post = [], array $request = []): ResponseInterface;
}
+++ /dev/null
-<?php
-
-namespace Friendica\Capabilities;
-
-interface IRespondToRequests
-{
- const TYPE_HTML = 'html';
- const TYPE_XML = 'xml';
- const TYPE_JSON = 'json';
- const TYPE_ATOM = 'atom';
- const TYPE_RSS = 'rss';
-
- const ALLOWED_TYPES = [
- self::TYPE_HTML,
- self::TYPE_XML,
- self::TYPE_JSON,
- self::TYPE_ATOM,
- self::TYPE_RSS
- ];
-
- /**
- * Returns all set headers during the module execution
- *
- * @return string[]
- */
- public function getHeaders(): array;
-
- /**
- * Returns the output of the module (mixed content possible)
- *
- * @return mixed
- */
- public function getContent();
-
- /**
- * Returns the response type
- *
- * @return string
- */
- public function getType(): string;
-}
namespace Friendica\Module\HTTPException;
use Friendica\BaseModule;
-use Friendica\Capabilities\IRespondToRequests;
use Friendica\DI;
use Friendica\Network\HTTPException;
+use Psr\Http\Message\ResponseInterface;
class PageNotFound extends BaseModule
{
throw new HTTPException\NotFoundException(DI::l10n()->t('Page not found.'));
}
- public function run(array $post = [], array $request = []): IRespondToRequests
+ public function run(array $post = [], array $request = []): ResponseInterface
{
/* The URL provided does not resolve to a valid module.
*
use Friendica\App;
use Friendica\BaseModule;
-use Friendica\Capabilities\IRespondToRequests;
+use Friendica\Capabilities\ICanCreateResponses;
use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n;
$nodeinfo['metadata']['explicitContent'] = $this->config->get('system', 'explicit_content', false) == true;
- $this->response->setType(IRespondToRequests::TYPE_JSON);
+ $this->response->setType(ICanCreateResponses::TYPE_JSON);
$this->response->addContent(json_encode($nodeinfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}
use Friendica\App;
use Friendica\BaseModule;
-use Friendica\Capabilities\IRespondToRequests;
+use Friendica\Capabilities\ICanCreateResponses;
use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n;
$nodeinfo['metadata']['explicitContent'] = $this->config->get('system', 'explicit_content', false) == true;
- $this->response->setType(IRespondToRequests::TYPE_JSON, 'application/json; charset=utf-8');
+ $this->response->setType(ICanCreateResponses::TYPE_JSON, 'application/json; charset=utf-8');
$this->response->addContent(json_encode($nodeinfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}
use Friendica\App;
use Friendica\BaseModule;
-use Friendica\Capabilities\IRespondToRequests;
+use Friendica\Capabilities\ICanCreateResponses;
use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n;
-use Friendica\Core\System;
use Friendica\Model\Nodeinfo;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
$nodeinfo['services']['inbound'][] = 'imap';
}
- $this->response->setType(IRespondToRequests::TYPE_JSON, 'application/json; charset=utf-8');
+ $this->response->setType(ICanCreateResponses::TYPE_JSON, 'application/json; charset=utf-8');
$this->response->addContent(json_encode($nodeinfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}
namespace Friendica\Module;
use Friendica\Capabilities\ICanCreateResponses;
-use Friendica\Capabilities\IRespondToRequests;
use Friendica\Network\HTTPException\InternalServerErrorException;
+use Psr\Http\Message\ResponseInterface;
class Response implements ICanCreateResponses
{
/**
* @var string
*/
- protected $type = IRespondToRequests::TYPE_HTML;
+ protected $type = ICanCreateResponses::TYPE_HTML;
/**
* {@inheritDoc}
*/
public function setType(string $type, ?string $content_type = null): void
{
- if (!in_array($type, IRespondToRequests::ALLOWED_TYPES)) {
+ if (!in_array($type, ICanCreateResponses::ALLOWED_TYPES)) {
throw new InternalServerErrorException('wrong type');
}
{
return $this->type;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generate(): ResponseInterface
+ {
+ $headers = [];
+
+ foreach ($this->headers as $key => $header) {
+ if (empty($key)) {
+ $headers[] = $header;
+ } else {
+ $headers[] = "$key: $header";
+ }
+ }
+
+ // Setting the response type as an X-header for direct usage
+ $headers['X-RESPONSE-TYPE'] = $this->type;
+
+ return new \GuzzleHttp\Psr7\Response(200, $this->headers, $this->content);
+ }
}
$notification = new Notification(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'xml']);
$response = $notification->run();
- self::assertXmlStringEqualsXmlString($assertXml, $response->getContent());
+ self::assertXmlStringEqualsXmlString($assertXml, (string)$response->getBody());
}
public function testWithJsonResult()
$notification = new Notification(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
$response = $notification->run();
- self::assertJson($response->getContent());
+ self::assertJson($response->getBody());
}
}
$version = new Version(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
$response = $version->run();
- self::assertEquals('"0.9.7"', $response->getContent());
+ self::assertEquals('"0.9.7"', $response->getBody());
}
}
$test = new Test(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
$response = $test->run();
- self::assertEquals('"ok"', $response->getContent());
+ self::assertEquals('"ok"', $response->getBody());
}
public function testXml()
$test = new Test(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'xml']);
$response = $test->run();
- self::assertxml($response->getContent(), 'ok');
+ self::assertxml($response->getBody(), 'ok');
}
}
$rateLimitStatus = new RateLimitStatus(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
$response = $rateLimitStatus->run();
- $result = json_decode($response->getContent());
+ $result = json_decode($response->getBody());
self::assertEquals(150, $result->remaining_hits);
self::assertEquals(150, $result->hourly_limit);
$rateLimitStatus = new RateLimitStatus(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'xml']);
$response = $rateLimitStatus->run();
- self::assertXml($response->getContent(), 'hash');
+ self::assertXml($response->getBody(), 'hash');
}
}
$savedSearch = new SavedSearches(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
$response = $savedSearch->run();
- $result = json_decode($response->getContent());
+ $result = json_decode($response->getBody());
self::assertEquals(1, $result[0]->id);
self::assertEquals(1, $result[0]->id_str);
namespace Friendica\Test\src\Module;
-use Friendica\Capabilities\IRespondToRequests;
use Friendica\DI;
use Friendica\Module\NodeInfo110;
use Friendica\Module\NodeInfo120;
$nodeinfo = new NodeInfo110(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), $response, DI::config(), []);
$response = $nodeinfo->run();
- self::assertEquals(IRespondToRequests::TYPE_JSON, $response->getType());
- self::assertJson($response->getContent());
- self::assertEquals(['Content-type' => 'application/json'], $response->getHeaders());
+ self::assertJson($response->getBody());
+ self::assertEquals(['Content-type' => ['application/json']], $response->getHeaders());
- $json = json_decode($response->getContent());
+ $json = json_decode($response->getBody());
self::assertEquals('1.0', $json->version);
$nodeinfo = new NodeInfo120(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), $response, DI::config(), []);
$response = $nodeinfo->run();
- self::assertEquals(IRespondToRequests::TYPE_JSON, $response->getType());
- self::assertJson($response->getContent());
- self::assertEquals(['Content-type' => 'application/json; charset=utf-8'], $response->getHeaders());
+ self::assertJson($response->getBody());
+ self::assertEquals(['Content-type' => ['application/json; charset=utf-8']], $response->getHeaders());
- $json = json_decode($response->getContent());
+ $json = json_decode($response->getBody());
self::assertEquals('2.0', $json->version);
$nodeinfo = new NodeInfo210(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), $response, DI::config(), []);
$response = $nodeinfo->run();
- self::assertEquals(IRespondToRequests::TYPE_JSON, $response->getType());
- self::assertJson($response->getContent());
- self::assertEquals(['Content-type' => 'application/json; charset=utf-8'], $response->getHeaders());
+ self::assertJson($response->getBody());
+ self::assertEquals(['Content-type' => ['application/json; charset=utf-8']], $response->getHeaders());
- $json = json_decode($response->getContent());
+ $json = json_decode($response->getBody());
self::assertEquals('1.0', $json->version);