diff --git a/src/Symfony/Component/HttpClient/CHANGELOG.md b/src/Symfony/Component/HttpClient/CHANGELOG.md index 40dc2ec5d5445..1036ba1ee5af8 100644 --- a/src/Symfony/Component/HttpClient/CHANGELOG.md +++ b/src/Symfony/Component/HttpClient/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.4 +--- + + * Add `ResponseStatusCodeTrait` that allows to check for common HTTP status codes + 7.3 --- diff --git a/src/Symfony/Component/HttpClient/Response/CommonResponseTrait.php b/src/Symfony/Component/HttpClient/Response/CommonResponseTrait.php index fa9df336074c9..f0c4ecc9976a4 100644 --- a/src/Symfony/Component/HttpClient/Response/CommonResponseTrait.php +++ b/src/Symfony/Component/HttpClient/Response/CommonResponseTrait.php @@ -26,6 +26,8 @@ */ trait CommonResponseTrait { + use ResponseStatusCodeTrait; + /** * @var callable|null A callback that tells whether we're waiting for response headers */ diff --git a/src/Symfony/Component/HttpClient/Response/ResponseStatusCodeTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseStatusCodeTrait.php new file mode 100644 index 0000000000000..f3852d45941bf --- /dev/null +++ b/src/Symfony/Component/HttpClient/Response/ResponseStatusCodeTrait.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpClient\Response; + +/** + * Checking HTTP response status codes explicitly. + * + * @author Jimmy Martin + */ +trait ResponseStatusCodeTrait +{ + public function isOk(): bool + { + return 200 === $this->getHttpCode(); + } + + public function isCreated(): bool + { + return 201 === $this->getHttpCode(); + } + + public function isAccepted(): bool + { + return 202 === $this->getHttpCode(); + } + + public function isNoContent(int $statusCode = 204): bool + { + return $statusCode === $this->getHttpCode() && '' === $this->getContent(false); + } + + public function isMovedPermanently(): bool + { + return 301 === $this->getHttpCode(); + } + + public function isFound(): bool + { + return 302 === $this->getHttpCode(); + } + + public function isNotModified(): bool + { + return 304 === $this->getHttpCode(); + } + + public function isBadRequest(): bool + { + return 400 === $this->getHttpCode(); + } + + public function isUnauthorized(): bool + { + return 401 === $this->getHttpCode(); + } + + public function isPaymentRequired(): bool + { + return 402 === $this->getHttpCode(); + } + + public function isForbidden(): bool + { + return 403 === $this->getHttpCode(); + } + + public function isNotFound(): bool + { + return 404 === $this->getHttpCode(); + } + + public function isMethodNotAllowed(): bool + { + return 405 === $this->getHttpCode(); + } + + public function isNotAcceptable(): bool + { + return 406 === $this->getHttpCode(); + } + + public function isRequestTimeout(): bool + { + return 408 === $this->getHttpCode(); + } + + public function isConflict(): bool + { + return 409 === $this->getHttpCode(); + } + + public function isGone(): bool + { + return 410 === $this->getHttpCode(); + } + + public function isUnprocessableEntity(): bool + { + return 422 === $this->getHttpCode(); + } + + public function isTooManyRequests(): bool + { + return 429 === $this->getHttpCode(); + } + + private function getHttpCode(): mixed + { + return $this->getInfo('http_code'); + } +} diff --git a/src/Symfony/Component/HttpClient/Tests/Response/ResponseStatusCodeTraitTest.php b/src/Symfony/Component/HttpClient/Tests/Response/ResponseStatusCodeTraitTest.php new file mode 100644 index 0000000000000..534dabda47ae7 --- /dev/null +++ b/src/Symfony/Component/HttpClient/Tests/Response/ResponseStatusCodeTraitTest.php @@ -0,0 +1,167 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpClient\Tests\Response; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\Response\MockResponse; + +class ResponseStatusCodeTraitTest extends TestCase +{ + public function testIsOk() + { + $response = self::createResponse(200); + $this->assertTrue($response->isOk()); + } + + public function testIsCreated() + { + $response = self::createResponse(201); + $this->assertTrue($response->isCreated()); + } + + public function testIsAccepted() + { + $response = self::createResponse(202); + $this->assertTrue($response->isAccepted()); + } + + public function testIsNoContent() + { + $response = self::createEmptyContentResponse(); + $this->assertTrue($response->isNoContent()); + + $response = self::createEmptyContentResponse(204, json_encode(['foo' => 'bar', 'bar' => 'baz'])); + $this->assertFalse($response->isNoContent()); + + $fakeStatusCode = 999; + $response = self::createEmptyContentResponse($fakeStatusCode); + $this->assertTrue($response->isNoContent($fakeStatusCode)); + + $response = self::createEmptyContentResponse($fakeStatusCode); + // we don't pass any status code, so the default status code (204) is used + $this->assertFalse($response->isNoContent()); + } + + public function testIsMovedPermanently() + { + $response = self::createResponse(301); + $this->assertTrue($response->isMovedPermanently()); + } + + public function testIsFound() + { + $response = self::createResponse(302); + $this->assertTrue($response->isFound()); + } + + public function testIsNotModified() + { + $response = self::createResponse(304); + $this->assertTrue($response->isNotModified()); + } + + public function testIsBadRequest() + { + $response = self::createResponse(400); + $this->assertTrue($response->isBadRequest()); + } + + public function testIsUnauthorized() + { + $response = self::createResponse(401); + $this->assertTrue($response->isUnauthorized()); + } + + public function testIsPaymentRequired() + { + $response = self::createResponse(402); + $this->assertTrue($response->isPaymentRequired()); + } + + public function testIsForbidden() + { + $response = self::createResponse(403); + $this->assertTrue($response->isForbidden()); + } + + public function testIsNotFound() + { + $response = self::createResponse(404); + $this->assertTrue($response->isNotFound()); + } + + public function testIsMethodNotAllowed() + { + $response = self::createResponse(405); + $this->assertTrue($response->isMethodNotAllowed()); + } + + public function testIsNotAcceptable() + { + $response = self::createResponse(406); + $this->assertTrue($response->isNotAcceptable()); + } + + public function testIsRequestTimeout() + { + $response = self::createResponse(408); + $this->assertTrue($response->isRequestTimeout()); + } + + public function testIsConflict() + { + $response = self::createResponse(409); + $this->assertTrue($response->isConflict()); + } + + public function testIsGone() + { + $response = self::createResponse(410); + $this->assertTrue($response->isGone()); + } + + public function testIsUnprocessableEntity() + { + $response = self::createResponse(422); + $this->assertTrue($response->isUnprocessableEntity()); + } + + public function testIsTooManyRequests() + { + $response = self::createResponse(429); + $this->assertTrue($response->isTooManyRequests()); + } + + private static function createResponse(int $statusCode, array $content = ['foo' => 'bar']): MockResponse + { + $responseMock = new MockResponse(json_encode($content), [ + 'http_code' => $statusCode, + ]); + + $response = MockResponse::fromRequest('GET', 'https://example.com/some-endpoint', [], $responseMock); + $response->toArray(false); + + return $response; + } + + private static function createEmptyContentResponse(int $statusCode = 204, string $content = ''): MockResponse + { + $responseMock = new MockResponse($content, [ + 'http_code' => $statusCode, + ]); + + $response = MockResponse::fromRequest('GET', 'https://example.com/some-endpoint', [], $responseMock); + $response->getContent(false); + + return $response; + } +}