generated from farzai/package-skeleton-php
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from farzai/add-response-builder
Add response builder
- Loading branch information
Showing
10 changed files
with
411 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
namespace Farzai\Transport\Exceptions; | ||
|
||
use Psr\Http\Client\ClientExceptionInterface; | ||
|
||
class ClientException extends \RuntimeException implements ClientExceptionInterface | ||
{ | ||
// | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
<?php | ||
|
||
namespace Farzai\Transport; | ||
|
||
use Psr\Http\Message\ResponseInterface as PsrResponseInterface; | ||
|
||
class ResponseBuilder | ||
{ | ||
protected int $statusCode = 200; | ||
|
||
/** | ||
* @var array<string, array<string>> | ||
*/ | ||
protected array $headers = []; | ||
|
||
/** | ||
* @var mixed | ||
*/ | ||
protected $body; | ||
|
||
protected string $version = '1.1'; | ||
|
||
protected ?string $reason = null; | ||
|
||
/** | ||
* Create a new response builder instance. | ||
*/ | ||
public static function create(): ResponseBuilder | ||
{ | ||
return new static(); | ||
} | ||
|
||
/** | ||
* Set the response status code. | ||
*/ | ||
public function statusCode(int $statusCode): self | ||
{ | ||
$this->statusCode = $statusCode; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Set the response headers. | ||
* | ||
* @param array<string, array<string>> $headers | ||
*/ | ||
public function withHeaders(array $headers): self | ||
{ | ||
foreach ($headers as $name => $value) { | ||
$this->withHeader($name, is_array($value) ? $value : [$value]); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Add a header to the response. | ||
* | ||
* @param mixed $value | ||
*/ | ||
public function withHeader(string $name, $value): self | ||
{ | ||
if (! isset($this->headers[$name])) { | ||
$this->headers[$name] = []; | ||
} | ||
|
||
$this->headers[$name] = array_merge( | ||
$this->headers[$name], | ||
(array) $value | ||
); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Set the response body. | ||
* | ||
* @param mixed $body | ||
*/ | ||
public function withBody($body): self | ||
{ | ||
$this->body = $body; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Set the response version. | ||
*/ | ||
public function withVersion(string $version): self | ||
{ | ||
$this->version = $version; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Set the response reason. | ||
*/ | ||
public function withReason(string $reason): self | ||
{ | ||
$this->reason = $reason; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Build the response. | ||
*/ | ||
public function build(): PsrResponseInterface | ||
{ | ||
return ResponseFactory::create( | ||
$this->statusCode, | ||
$this->headers, | ||
$this->body, | ||
$this->version, | ||
$this->reason | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
namespace Farzai\Transport; | ||
|
||
use GuzzleHttp\Psr7\Response; | ||
use Psr\Http\Message\ResponseInterface as PsrResponseInterface; | ||
|
||
class ResponseFactory | ||
{ | ||
/** | ||
* Create a new response instance. | ||
*/ | ||
public static function create( | ||
int $statusCode, | ||
array $headers = [], | ||
$body = null, | ||
string $version = '1.1', | ||
?string $reason = null | ||
): PsrResponseInterface { | ||
return new Response($statusCode, $headers, $body, $version, $reason); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<?php | ||
|
||
namespace Farzai\Transport\Tests\HttpClient; | ||
|
||
use PHPUnit\Framework\TestCase as PHPUnitTestCase; | ||
use Psr\Http\Client\ClientInterface as PsrClientInterface; | ||
use Psr\Http\Message\RequestInterface as PsrRequestInterface; | ||
use Psr\Http\Message\ResponseInterface as PsrResponseInterface; | ||
use Psr\Http\Message\StreamInterface as PsrStreamInterface; | ||
|
||
class MockHttpClient extends PHPUnitTestCase implements PsrClientInterface | ||
{ | ||
/** | ||
* The sequence of responses. | ||
* | ||
* @var array<int, PsrResponseInterface> | ||
*/ | ||
private array $sequence = []; | ||
|
||
/** | ||
* Create a new mock http client instance. | ||
*/ | ||
public static function new(): self | ||
{ | ||
return new static('mock-http-client'); | ||
} | ||
|
||
/** | ||
* Add a sequence of responses. | ||
* | ||
* @param PsrResponseInterface|callable<PsrResponseInterface> ...$responses | ||
*/ | ||
public function addSequence( | ||
PsrResponseInterface|callable ...$responses | ||
): self { | ||
foreach ($responses as $response) { | ||
if (is_callable($response)) { | ||
$response = $response($this); | ||
} | ||
|
||
$this->sequence[] = $response; | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Send a PSR-7 request and return a PSR-7 response. | ||
*/ | ||
public function sendRequest( | ||
PsrRequestInterface $request | ||
): PsrResponseInterface { | ||
return array_shift($this->sequence); | ||
} | ||
|
||
/** | ||
* Create a stream with the given contents. | ||
*/ | ||
public function createStream(string $contents): PsrStreamInterface | ||
{ | ||
$stream = $this->createMock(PsrStreamInterface::class); | ||
$stream->method('getContents')->willReturn($contents); | ||
|
||
return $stream; | ||
} | ||
|
||
/** | ||
* Create a response with the given status code and contents. | ||
*/ | ||
public function createResponse( | ||
int $statusCode, | ||
string $contents, | ||
array $headers = [] | ||
): PsrResponseInterface { | ||
$stream = $this->createStream($contents); | ||
|
||
$response = $this->createMock(PsrResponseInterface::class); | ||
$response->method('getStatusCode')->willReturn($statusCode); | ||
$response->method('getBody')->willReturn($stream); | ||
$response->method('getHeaders')->willReturn($headers); | ||
|
||
return $response; | ||
} | ||
|
||
/** | ||
* Create a response with the given status code and contents. | ||
*/ | ||
public static function response( | ||
int $statusCode, | ||
array|string $contents, | ||
array $headers = [] | ||
): PsrResponseInterface { | ||
$client = static::new(); | ||
|
||
if (is_array($contents)) { | ||
$contents = json_encode($contents); | ||
} | ||
|
||
return $client->createResponse($statusCode, $contents, $headers); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
use Farzai\Transport\Exceptions\ResponseExceptionFactory; | ||
use Farzai\Transport\Response; | ||
use GuzzleHttp\Exception\BadResponseException; | ||
use GuzzleHttp\Exception\ServerException; | ||
use Psr\Http\Message\RequestInterface as PsrRequestInterface; | ||
use Psr\Http\Message\ResponseInterface as PsrResponseInterface; | ||
use Psr\Http\Message\StreamInterface as PsrStreamInterface; | ||
|
||
it('should throw bad request', function () { | ||
$stream = $this->createMock(PsrStreamInterface::class); | ||
$stream->method('getContents')->willReturn('{"message":"Bad Request"}'); | ||
|
||
$response = $this->createMock(PsrResponseInterface::class); | ||
$response->method('getStatusCode')->willReturn(400); | ||
$response->method('getBody')->willReturn($stream); | ||
$response | ||
->method('getHeaders') | ||
->willReturn(['Content-Type' => ['application/json']]); | ||
|
||
$psrRequest = $this->createMock(PsrRequestInterface::class); | ||
|
||
$exception = ResponseExceptionFactory::create( | ||
new Response($psrRequest, $response) | ||
); | ||
|
||
expect($exception)->toBeInstanceOf(BadResponseException::class); | ||
expect($exception->getMessage())->toBe('Bad Request'); | ||
expect($exception->getCode())->toBe(400); | ||
}); | ||
|
||
it('should throw server error', function () { | ||
$stream = $this->createMock(PsrStreamInterface::class); | ||
$stream->method('getContents')->willReturn('{"message":"Internal Server Error"}'); | ||
|
||
$response = $this->createMock(PsrResponseInterface::class); | ||
$response->method('getStatusCode')->willReturn(500); | ||
$response->method('getBody')->willReturn($stream); | ||
$response | ||
->method('getHeaders') | ||
->willReturn(['Content-Type' => ['application/json']]); | ||
|
||
$psrRequest = $this->createMock(PsrRequestInterface::class); | ||
|
||
$exception = ResponseExceptionFactory::create( | ||
new Response($psrRequest, $response) | ||
); | ||
|
||
expect($exception)->toBeInstanceOf(ServerException::class); | ||
expect($exception->getMessage())->toBe('Internal Server Error'); | ||
expect($exception->getCode())->toBe(500); | ||
}); |
Oops, something went wrong.