Add explicit status setting for PSR/ResponseInterface & add tests for OPTIONS endpoint

This commit is contained in:
Philipp Holzer 2022-01-02 21:28:28 +01:00
parent 3092e74a3a
commit eaad220738
Signed by: nupplaPhil
GPG key ID: 24A7501396EB5432
6 changed files with 60 additions and 4 deletions

View file

@ -710,7 +710,8 @@ class App
$timestamp = microtime(true);
$response = $module->run($input);
$this->profiler->set(microtime(true) - $timestamp, 'content');
if ($response->getHeaderLine(ICanCreateResponses::X_HEADER) === ICanCreateResponses::TYPE_HTML) {
if ($response->getHeaderLine(ICanCreateResponses::X_HEADER) === ICanCreateResponses::TYPE_HTML &&
$response->getStatusCode() == 200) {
$page->run($this, $this->baseURL, $this->args, $this->mode, $response, $this->l10n, $this->profiler, $this->config, $pconfig);
} else {
$page->exit($response);

View file

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

View file

@ -70,6 +70,16 @@ interface ICanCreateResponses
*/
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
* @see https://www.php-fig.org/psr/psr-7/

View file

@ -40,6 +40,10 @@ class Response implements ICanCreateResponses
*/
protected $type = self::TYPE_HTML;
protected $status = 200;
protected $reason = null;
/**
* {@inheritDoc}
*/
@ -111,6 +115,15 @@ class Response implements ICanCreateResponses
$this->type = $type;
}
/**
* {@inheritDoc}
*/
public function setStatus(int $status = 200, ?string $reason = null): void
{
$this->status = $status;
$this->reason = $reason;
}
/**
* {@inheritDoc}
*/
@ -127,6 +140,6 @@ class Response implements ICanCreateResponses
// Setting the response type as an X-header for direct usage
$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, $this->reason);
}
}

View file

@ -10,7 +10,7 @@ class Options extends BaseModule
protected function options(array $request = [])
{
// @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
$this->response->setHeader('Allow', implode(',', Router::ALLOWED_METHODS));
$this->response->setHeader(($this->server['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' 204 No Content');
$this->response->setHeader(implode(',', Router::ALLOWED_METHODS), 'Allow');
$this->response->setStatus(204);
}
}

View file

@ -0,0 +1,26 @@
<?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 testOptions()
{
$response = (new Options(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::OPTIONS]))->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 => ['html'],
], $response->getHeaders());
self::assertEquals(implode(',', Router::ALLOWED_METHODS), $response->getHeaderLine('Allow'));
}
}