diff --git a/module/Core/src/Exception/InvalidUrlException.php b/module/Core/src/Exception/InvalidUrlException.php index 5cd79af5..32758b4e 100644 --- a/module/Core/src/Exception/InvalidUrlException.php +++ b/module/Core/src/Exception/InvalidUrlException.php @@ -4,15 +4,30 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Exception; +use Fig\Http\Message\StatusCodeInterface; use Throwable; +use Zend\ProblemDetails\Exception\CommonProblemDetailsExceptionTrait; +use Zend\ProblemDetails\Exception\ProblemDetailsExceptionInterface; use function sprintf; -class InvalidUrlException extends RuntimeException +class InvalidUrlException extends DomainException implements ProblemDetailsExceptionInterface { + use CommonProblemDetailsExceptionTrait; + + private const TITLE = 'Invalid URL'; + public const TYPE = 'INVALID_URL'; + public static function fromUrl(string $url, ?Throwable $previous = null): self { - $code = $previous !== null ? $previous->getCode() : -1; - return new static(sprintf('Provided URL "%s" is not an existing and valid URL', $url), $code, $previous); + $status = StatusCodeInterface::STATUS_BAD_REQUEST; + $e = new self(sprintf('Provided URL %s is invalid. Try with a different one.', $url), $status, $previous); + + $e->detail = $e->getMessage(); + $e->title = self::TITLE; + $e->type = self::TYPE; + $e->status = $status; + + return $e; } } diff --git a/module/Core/test/Exception/InvalidUrlExceptionTest.php b/module/Core/test/Exception/InvalidUrlExceptionTest.php index a5d19341..1b7de449 100644 --- a/module/Core/test/Exception/InvalidUrlExceptionTest.php +++ b/module/Core/test/Exception/InvalidUrlExceptionTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; use Exception; +use Fig\Http\Message\StatusCodeInterface; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Throwable; @@ -19,8 +20,8 @@ class InvalidUrlExceptionTest extends TestCase { $e = InvalidUrlException::fromUrl('http://the_url.com', $prev); - $this->assertEquals('Provided URL "http://the_url.com" is not an existing and valid URL', $e->getMessage()); - $this->assertEquals($prev !== null ? $prev->getCode() : -1, $e->getCode()); + $this->assertEquals('Provided URL http://the_url.com is invalid. Try with a different one.', $e->getMessage()); + $this->assertEquals(StatusCodeInterface::STATUS_BAD_REQUEST, $e->getCode()); $this->assertEquals($prev, $e->getPrevious()); } diff --git a/module/Rest/src/Action/ShortUrl/AbstractCreateShortUrlAction.php b/module/Rest/src/Action/ShortUrl/AbstractCreateShortUrlAction.php index bc0d50ef..d627b427 100644 --- a/module/Rest/src/Action/ShortUrl/AbstractCreateShortUrlAction.php +++ b/module/Rest/src/Action/ShortUrl/AbstractCreateShortUrlAction.php @@ -7,7 +7,6 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Log\LoggerInterface; -use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException; use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Model\CreateShortUrlData; @@ -60,12 +59,6 @@ abstract class AbstractCreateShortUrlAction extends AbstractRestAction $transformer = new ShortUrlDataTransformer($this->domainConfig); return new JsonResponse($transformer->transform($shortUrl)); - } catch (InvalidUrlException $e) { - $this->logger->warning('Provided Invalid URL. {e}', ['e' => $e]); - return new JsonResponse([ - 'error' => RestUtils::getRestErrorCodeFromException($e), - 'message' => sprintf('Provided URL %s is invalid. Try with a different one.', $longUrl), - ], self::STATUS_BAD_REQUEST); } catch (NonUniqueSlugException $e) { $customSlug = $shortUrlMeta->getCustomSlug(); $this->logger->warning('Provided non-unique slug. {e}', ['e' => $e]); diff --git a/module/Rest/src/Util/RestUtils.php b/module/Rest/src/Util/RestUtils.php index 13488b01..279d7fca 100644 --- a/module/Rest/src/Util/RestUtils.php +++ b/module/Rest/src/Util/RestUtils.php @@ -16,7 +16,8 @@ class RestUtils public const INVALID_SHORTCODE_ERROR = ShortUrlNotFoundException::TYPE; // FIXME Should be INVALID_SHORT_URL_DELETION public const INVALID_SHORTCODE_DELETION_ERROR = 'INVALID_SHORTCODE_DELETION'; - public const INVALID_URL_ERROR = 'INVALID_URL'; + /** @deprecated */ + public const INVALID_URL_ERROR = Core\InvalidUrlException::TYPE; public const INVALID_ARGUMENT_ERROR = 'INVALID_ARGUMENT'; public const INVALID_SLUG_ERROR = 'INVALID_SLUG'; public const INVALID_CREDENTIALS_ERROR = 'INVALID_CREDENTIALS'; diff --git a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php index 732cbc25..1cc5c889 100644 --- a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php @@ -8,7 +8,6 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Entity\ShortUrl; -use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException; use Shlinkio\Shlink\Core\Model\ShortUrlMeta; use Shlinkio\Shlink\Core\Service\UrlShortener; @@ -61,21 +60,6 @@ class CreateShortUrlActionTest extends TestCase $this->assertTrue(strpos($response->getBody()->getContents(), $shortUrl->toString(self::DOMAIN_CONFIG)) > 0); } - /** @test */ - public function anInvalidUrlReturnsError(): void - { - $this->urlShortener->urlToShortCode(Argument::type(Uri::class), Argument::type('array'), Argument::cetera()) - ->willThrow(InvalidUrlException::class) - ->shouldBeCalledOnce(); - - $request = (new ServerRequest())->withParsedBody([ - 'longUrl' => 'http://www.domain.com/foo/bar', - ]); - $response = $this->action->handle($request); - $this->assertEquals(400, $response->getStatusCode()); - $this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::INVALID_URL_ERROR) > 0); - } - /** * @test * @dataProvider provideInvalidDomains