Skip to content

Commit

Permalink
Rename Exception -> HttpException and change how dispatch works
Browse files Browse the repository at this point in the history
  • Loading branch information
Robin de Graaf committed Feb 4, 2021
1 parent 9b24209 commit 1bc76bd
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 23 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Parable Http

## 0.5.0

_Changes_
- `dispatch` now terminates by default, `dispatchAndTerminate` has been removed, and `dispatchWithoutTerminate` has been added.
- `Parable\Http\Exception` has been renamed to `Parable\Http\HttpException` for clearer usage.

## 0.4.0

_Changes_
Expand Down
2 changes: 1 addition & 1 deletion src/Exception.php → src/HttpException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

namespace Parable\Http;

class Exception extends \Exception
class HttpException extends \Exception
{
}
171 changes: 171 additions & 0 deletions src/HttpStatusCode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?php declare(strict_types=1);

namespace Parable\Http;

use MyCLabs\Enum\Enum;

/**
* @method static HttpStatusCode _100
* @method static HttpStatusCode _101
* @method static HttpStatusCode _200
* @method static HttpStatusCode _201
* @method static HttpStatusCode _202
* @method static HttpStatusCode _203
* @method static HttpStatusCode _204
* @method static HttpStatusCode _205
* @method static HttpStatusCode _206
* @method static HttpStatusCode _300
* @method static HttpStatusCode _301
* @method static HttpStatusCode _302
* @method static HttpStatusCode _303
* @method static HttpStatusCode _304
* @method static HttpStatusCode _305
* @method static HttpStatusCode _307
* @method static HttpStatusCode _308
* @method static HttpStatusCode _400
* @method static HttpStatusCode _401
* @method static HttpStatusCode _402
* @method static HttpStatusCode _403
* @method static HttpStatusCode _404
* @method static HttpStatusCode _405
* @method static HttpStatusCode _406
* @method static HttpStatusCode _407
* @method static HttpStatusCode _408
* @method static HttpStatusCode _409
* @method static HttpStatusCode _410
* @method static HttpStatusCode _411
* @method static HttpStatusCode _412
* @method static HttpStatusCode _413
* @method static HttpStatusCode _414
* @method static HttpStatusCode _415
* @method static HttpStatusCode _416
* @method static HttpStatusCode _417
* @method static HttpStatusCode _418
* @method static HttpStatusCode _421
* @method static HttpStatusCode _426
* @method static HttpStatusCode _428
* @method static HttpStatusCode _429
* @method static HttpStatusCode _431
* @method static HttpStatusCode _451
* @method static HttpStatusCode _500
* @method static HttpStatusCode _501
* @method static HttpStatusCode _502
* @method static HttpStatusCode _503
* @method static HttpStatusCode _504
* @method static HttpStatusCode _505
* @method static HttpStatusCode _506
* @method static HttpStatusCode _507
* @method static HttpStatusCode _511
*/
class HttpStatusCode extends Enum
{
private const _100 = 100;
private const _101 = 101;
private const _200 = 200;
private const _201 = 201;
private const _202 = 202;
private const _203 = 203;
private const _204 = 204;
private const _205 = 205;
private const _206 = 206;
private const _300 = 300;
private const _301 = 301;
private const _302 = 302;
private const _303 = 303;
private const _304 = 304;
private const _305 = 305;
private const _307 = 307;
private const _308 = 308;
private const _400 = 400;
private const _401 = 401;
private const _402 = 402;
private const _403 = 403;
private const _404 = 404;
private const _405 = 405;
private const _406 = 406;
private const _407 = 407;
private const _408 = 408;
private const _409 = 409;
private const _410 = 410;
private const _411 = 411;
private const _412 = 412;
private const _413 = 413;
private const _414 = 414;
private const _415 = 415;
private const _416 = 416;
private const _417 = 417;
private const _418 = 418;
private const _421 = 421;
private const _426 = 426;
private const _428 = 428;
private const _429 = 429;
private const _431 = 431;
private const _451 = 451;
private const _500 = 500;
private const _501 = 501;
private const _502 = 502;
private const _503 = 503;
private const _504 = 504;
private const _505 = 505;
private const _506 = 506;
private const _507 = 507;
private const _511 = 511;

public function getText(): string
{
return match ($this->getValue()) {
static::_100 => "Continue",
static::_101 => "Switching Protocols",
static::_200 => "OK",
static::_201 => "Created",
static::_202 => "Accepted",
static::_203 => "Non-Authoritative Information",
static::_204 => "No Content",
static::_205 => "Reset Content",
static::_206 => "Partial Content",
static::_300 => "Multiple Choice",
static::_301 => "Moved Permanently",
static::_302 => "Found",
static::_303 => "See Other",
static::_304 => "Not Modified",
static::_305 => "Use Proxy",
static::_307 => "Temporary Redirect",
static::_308 => "Permanent Redirect",
static::_400 => "Bad Request",
static::_401 => "Unauthorized",
static::_402 => "Payment Required",
static::_403 => "Forbidden",
static::_404 => "Not Found",
static::_405 => "Method Not Allowed",
static::_406 => "Not Acceptable",
static::_407 => "Proxy Authentication Required",
static::_408 => "Request Timeout",
static::_409 => "Conflict",
static::_410 => "Gone",
static::_411 => "Length Required",
static::_412 => "Precondition Failed",
static::_413 => "Payload Too Large",
static::_414 => "URI Too Long",
static::_415 => "Unsupported Media Type",
static::_416 => "Requested Range Not Satisfiable",
static::_417 => "Expectation Failed",
static::_418 => "I'm a teapot",
static::_421 => "Misdirected Request",
static::_426 => "Upgrade Required",
static::_428 => "Precondition Required",
static::_429 => "Too Many Requests",
static::_431 => "Request Header Fields Too Large",
static::_451 => "Unavailable For Legal Reasons",
static::_500 => "Internal Server Error",
static::_501 => "Not Implemented",
static::_502 => "Bad Gateway",
static::_503 => "Service Unavailable",
static::_504 => "Gateway Timeout",
static::_505 => "HTTP Version Not Supported",
static::_506 => "Variant Also Negotiates",
static::_507 => "Variant Also Negotiates",
static::_511 => "Network Authentication Required",
default => throw new HttpException('Unknown status code: ' . $this->getValue()),
};
}
}
2 changes: 1 addition & 1 deletion src/RequestFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static function createFromServer(): Request
$protocol = self::getProtocolFromServerArray($_SERVER);

if ($uri === null) {
throw new Exception('Could not build uri from $_SERVER array.');
throw new HttpException('Could not build uri from $_SERVER array.');
}

return new Request($method, $uri->getUriString(), $headers, $protocol);
Expand Down
16 changes: 8 additions & 8 deletions src/ResponseDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ class ResponseDispatcher
{
use SupportsOutputBuffers;

public function dispatch(Response $response): void
public function dispatch(Response $response, int $exitCode = 0): void
{
$this->dispatchWithoutTerminate($response);
$this->terminate($exitCode);
}

public function dispatchWithoutTerminate(Response $response): void
{
if (HeaderSender::alreadySent()) {
throw new Exception('Cannot dispatch response if headers already sent.');
throw new HttpException('Cannot dispatch response if headers already sent.');
}

HeaderSender::send(sprintf(
Expand All @@ -34,12 +40,6 @@ public function dispatch(Response $response): void
echo $bufferedContent . $response->getBody();
}

public function dispatchAndTerminate(Response $response, int $exitCode = 0): void
{
$this->dispatch($response);
$this->terminate($exitCode);
}

/**
* @codeCoverageIgnore
*/
Expand Down
4 changes: 2 additions & 2 deletions tests/RequestFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

namespace Parable\Http\Tests;

use Parable\Http\Exception;
use Parable\Http\HttpException;
use Parable\Http\RequestFactory;
use PHPUnit\Framework\TestCase;

class RequestFactoryTest extends TestCase
{
public function testCreateFromServerFailsIfAllDataIsMissing(): void
{
$this->expectException(Exception::class);
$this->expectException(HttpException::class);
$this->expectExceptionMessage('Could not build uri from $_SERVER array.');

RequestFactory::createFromServer();
Expand Down
19 changes: 8 additions & 11 deletions tests/ResponseDispatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Parable\Http\Tests;

use Parable\Http\ResponseDispatcher;
use Parable\Http\Exception;
use Parable\Http\HttpException;
use Parable\Http\HeaderSender;
use Parable\Http\Response;
use PHPUnit\Framework\TestCase;
Expand All @@ -26,12 +26,12 @@ public function setUp(): void

public function testDispatchThrowsExceptionOnHeadersSent(): void
{
$this->expectException(Exception::class);
$this->expectException(HttpException::class);
$this->expectExceptionMessage('Cannot dispatch response if headers already sent.');

$response = new Response(200, 'body');

$this->dispatcher->dispatch($response);
$this->dispatcher->dispatchWithoutTerminate($response);
}

public function testDispatchWorksIfNoHeadersSent(): void
Expand All @@ -45,7 +45,7 @@ public function testDispatchWorksIfNoHeadersSent(): void

$response = new Response(200, 'body');

$this->dispatcher->dispatchAndTerminate($response);
$this->dispatcher->dispatch($response);

$headers = HeaderSender::list();

Expand All @@ -70,28 +70,25 @@ public function testDispatchDoesNotTerminateWhenToldNotTo(): void

$response = new Response(200, 'body');

$this->dispatcher->dispatch($response);
$this->dispatcher->dispatchWithoutTerminate($response);

self::assertNull($this->lastExitCode);

// We need to clean the output from the dispatched Response
ob_get_clean();
}

public function testDispatchAndTerminateIgnoresShouldTerminateSetting(): void
public function testDispatchTerminates(): void
{
ob_start();

// Setting the HeaderSender to test mode will not send headers but store them instead
HeaderSender::setTestMode(true);

self::assertNull($this->lastExitCode);

$response = new Response(200, 'body');

$this->dispatcher->dispatchAndTerminate($response);
$this->dispatcher->dispatch($response, 4);

self::assertSame(0, $this->lastExitCode);
self::assertSame(4, $this->lastExitCode);

// We need to clean the output from the dispatched Response
ob_get_clean();
Expand Down

0 comments on commit 1bc76bd

Please sign in to comment.