mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-27 08:18:24 +03:00
Merge branch 'develop' of github.com:shlinkio/shlink into develop
This commit is contained in:
commit
18abe9d0f9
80 changed files with 572 additions and 753 deletions
|
@ -1,5 +1,11 @@
|
|||
## CHANGELOG
|
||||
|
||||
### 1.4.0
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
* [89: Update to expressive 2](https://github.com/shlinkio/shlink/issues/89)
|
||||
|
||||
### 1.3.1
|
||||
|
||||
**Tasks**
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
{
|
||||
"name": "shlinkio/shlink",
|
||||
"type": "project",
|
||||
"homepage": "http://shlink.io",
|
||||
"homepage": "https://shlink.io",
|
||||
"description": "A self-hosted and PHP-based URL shortener application with CLI and REST interfaces",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alejandro Celaya Alastrué",
|
||||
"homepage": "http://www.alejandrocelaya.com",
|
||||
"homepage": "https://www.alejandrocelaya.com",
|
||||
"email": "alejandro@alejandrocelaya.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0",
|
||||
"zendframework/zend-expressive": "^1.0",
|
||||
"zendframework/zend-expressive-fastroute": "^1.3",
|
||||
"zendframework/zend-expressive-twigrenderer": "^1.0",
|
||||
"zendframework/zend-stdlib": "^2.7",
|
||||
"zendframework/zend-expressive": "^2.0",
|
||||
"zendframework/zend-expressive-fastroute": "^2.0",
|
||||
"zendframework/zend-expressive-twigrenderer": "^1.4",
|
||||
"zendframework/zend-stdlib": "^3.0",
|
||||
"zendframework/zend-servicemanager": "^3.0",
|
||||
"zendframework/zend-paginator": "^2.6",
|
||||
"zendframework/zend-config": "^2.6",
|
||||
"zendframework/zend-config": "^3.0",
|
||||
"zendframework/zend-i18n": "^2.7",
|
||||
"mtymek/expressive-config-manager": "^0.4",
|
||||
"acelaya/zsm-annotated-services": "^0.2.0",
|
||||
"acelaya/ze-content-based-error-handler": "^1.0",
|
||||
"zendframework/zend-config-aggregator": "^0.1",
|
||||
"acelaya/zsm-annotated-services": "^1.0",
|
||||
"acelaya/ze-content-based-error-handler": "^2.0",
|
||||
"doctrine/orm": "^2.5",
|
||||
"guzzlehttp/guzzle": "^6.2",
|
||||
"symfony/console": "^3.0",
|
||||
|
@ -37,13 +37,12 @@
|
|||
"doctrine/migrations": "^1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.0",
|
||||
"phpunit/phpunit": "^5.7 || ^6.0",
|
||||
"squizlabs/php_codesniffer": "^2.3",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"filp/whoops": "^2.0",
|
||||
"symfony/var-dumper": "^3.0",
|
||||
"vlucas/phpdotenv": "^2.2",
|
||||
"phly/changelog-generator": "^2.1"
|
||||
"vlucas/phpdotenv": "^2.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -4,6 +4,7 @@ use Zend\Expressive\Container;
|
|||
use Zend\Expressive\Router;
|
||||
use Zend\Expressive\Template;
|
||||
use Zend\Expressive\Twig;
|
||||
use Zend\Stratigility\Middleware\ErrorHandler;
|
||||
|
||||
return [
|
||||
|
||||
|
@ -13,6 +14,7 @@ return [
|
|||
Template\TemplateRendererInterface::class => Twig\TwigRendererFactory::class,
|
||||
\Twig_Environment::class => Twig\TwigEnvironmentFactory::class,
|
||||
Router\RouterInterface::class => Router\FastRouteRouterFactory::class,
|
||||
ErrorHandler::class => Container\ErrorHandlerFactory::class,
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
use Acelaya\ExpressiveErrorHandler\ErrorHandler\ContentBasedErrorHandler;
|
||||
use Zend\Expressive\Container\WhoopsErrorHandlerFactory;
|
||||
use Zend\Expressive\Container\WhoopsErrorResponseGeneratorFactory;
|
||||
|
||||
return [
|
||||
'dependencies' => [
|
||||
|
@ -21,7 +20,7 @@ return [
|
|||
'error_handler' => [
|
||||
'plugins' => [
|
||||
'factories' => [
|
||||
ContentBasedErrorHandler::DEFAULT_CONTENT => WhoopsErrorHandlerFactory::class,
|
||||
'text/html' => WhoopsErrorResponseGeneratorFactory::class,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
|
@ -1,9 +1,30 @@
|
|||
<?php
|
||||
use Shlinkio\Shlink\Common\Middleware\LocaleMiddleware;
|
||||
use Shlinkio\Shlink\Rest\Middleware\BodyParserMiddleware;
|
||||
use Shlinkio\Shlink\Rest\Middleware\CheckAuthenticationMiddleware;
|
||||
use Shlinkio\Shlink\Rest\Middleware\CrossDomainMiddleware;
|
||||
use Shlinkio\Shlink\Rest\Middleware\PathVersionMiddleware;
|
||||
use Zend\Expressive\Container\ApplicationFactory;
|
||||
use Zend\Stratigility\Middleware\ErrorHandler;
|
||||
|
||||
return [
|
||||
|
||||
'middleware_pipeline' => [
|
||||
'pre-routing' => [
|
||||
'middleware' => [
|
||||
ErrorHandler::class,
|
||||
LocaleMiddleware::class,
|
||||
],
|
||||
'priority' => 11,
|
||||
],
|
||||
'pre-routing-rest' => [
|
||||
'path' => '/rest',
|
||||
'middleware' => [
|
||||
PathVersionMiddleware::class,
|
||||
],
|
||||
'priority' => 11,
|
||||
],
|
||||
|
||||
'routing' => [
|
||||
'middleware' => [
|
||||
ApplicationFactory::ROUTING_MIDDLEWARE,
|
||||
|
@ -11,6 +32,16 @@ return [
|
|||
'priority' => 10,
|
||||
],
|
||||
|
||||
'rest' => [
|
||||
'path' => '/rest',
|
||||
'middleware' => [
|
||||
CrossDomainMiddleware::class,
|
||||
BodyParserMiddleware::class,
|
||||
CheckAuthenticationMiddleware::class,
|
||||
],
|
||||
'priority' => 5,
|
||||
],
|
||||
|
||||
'post-routing' => [
|
||||
'middleware' => [
|
||||
ApplicationFactory::DISPATCH_MIDDLEWARE,
|
||||
|
|
|
@ -4,7 +4,7 @@ use Shlinkio\Shlink\CLI;
|
|||
use Shlinkio\Shlink\Common;
|
||||
use Shlinkio\Shlink\Core;
|
||||
use Shlinkio\Shlink\Rest;
|
||||
use Zend\Expressive\ConfigManager;
|
||||
use Zend\ConfigAggregator;
|
||||
|
||||
/**
|
||||
* Configuration files are loaded in a specific order. First ``global.php``, then ``*.global.php``.
|
||||
|
@ -15,11 +15,11 @@ use Zend\Expressive\ConfigManager;
|
|||
* Obviously, if you use closures in your config you can't cache it.
|
||||
*/
|
||||
|
||||
return (new ConfigManager\ConfigManager([
|
||||
return (new ConfigAggregator\ConfigAggregator([
|
||||
ExpressiveErrorHandler\ConfigProvider::class,
|
||||
Common\ConfigProvider::class,
|
||||
Core\ConfigProvider::class,
|
||||
CLI\ConfigProvider::class,
|
||||
Rest\ConfigProvider::class,
|
||||
new ConfigManager\ZendConfigProvider('config/{autoload/{{,*.}global,{,*.}local},params/generated_config}.php'),
|
||||
new ConfigAggregator\ZendConfigProvider('config/{autoload/{{,*.}global,{,*.}local},params/generated_config}.php'),
|
||||
], 'data/cache/app_config.php'))->getMergedConfig();
|
||||
|
|
0
data/proxies/.gitignore
vendored
Normal file → Executable file
0
data/proxies/.gitignore
vendored
Normal file → Executable file
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Api;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Api\DisableKeyCommand;
|
||||
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Api;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Api\GenerateKeyCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Api;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Api\ListKeysCommand;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Config;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\CLI\Command\Config\GenerateCharsetCommand;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Install;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Install\InstallCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Shortcode;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Shortcode\GeneratePreviewCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Shortcode;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Shortcode\GenerateShortcodeCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Shortcode;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Shortcode\GetVisitsCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Shortcode;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Shortcode\ListShortcodesCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Shortcode;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Shortcode\ResolveUrlCommand;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\Visit;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\Visit\ProcessVisitsCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\CLI\ConfigProvider;
|
||||
|
||||
class ConfigProviderTest extends TestCase
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\CLI\Factory;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\CLI\Factory\ApplicationFactory;
|
||||
use Shlinkio\Shlink\Core\Options\AppOptions;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
use Shlinkio\Shlink\Common\Middleware;
|
||||
|
||||
return [
|
||||
|
||||
'middleware_pipeline' => [
|
||||
'pre-routing' => [
|
||||
'middleware' => [
|
||||
Middleware\LocaleMiddleware::class,
|
||||
],
|
||||
'priority' => 5,
|
||||
],
|
||||
],
|
||||
|
||||
];
|
|
@ -2,10 +2,11 @@
|
|||
namespace Shlinkio\Shlink\Common\Middleware;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class LocaleMiddleware implements MiddlewareInterface
|
||||
{
|
||||
|
@ -25,40 +26,26 @@ class LocaleMiddleware implements MiddlewareInterface
|
|||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
if (! $request->hasHeader('Accept-Language')) {
|
||||
return $out($request, $response);
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
$locale = $request->getHeaderLine('Accept-Language');
|
||||
$this->translator->setLocale($this->normalizeLocale($locale));
|
||||
return $out($request, $response);
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\ConfigProvider;
|
||||
|
||||
class ConfigProviderTest extends TestCase
|
||||
|
@ -23,7 +23,6 @@ class ConfigProviderTest extends TestCase
|
|||
{
|
||||
$config = $this->configProvider->__invoke();
|
||||
|
||||
$this->assertArrayHasKey('middleware_pipeline', $config);
|
||||
$this->assertArrayHasKey('dependencies', $config);
|
||||
$this->assertArrayHasKey('twig', $config);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use Doctrine\Common\Cache\ArrayCache;
|
|||
use Doctrine\Common\Cache\FilesystemCache;
|
||||
use Doctrine\Common\Cache\MemcachedCache;
|
||||
use Doctrine\Common\Cache\RedisCache;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Factory\CacheFactory;
|
||||
use Shlinkio\Shlink\Core\Options\AppOptions;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace ShlinkioTest\Shlink\Common\Factory;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Factory\EntityManagerFactory;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace ShlinkioTest\Shlink\Common\Factory;
|
||||
|
||||
use Monolog\Logger;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Common\Factory\LoggerFactory;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common\Factory;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Factory\TranslatorFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common\Image;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Image\ImageBuilder;
|
||||
use Shlinkio\Shlink\Common\Image\ImageBuilderFactory;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace ShlinkioTest\Shlink\Common\Image;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Image\ImageFactory;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common\Middleware;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Middleware\LocaleMiddleware;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
||||
|
@ -30,9 +30,7 @@ class LocaleMiddlewareTest extends TestCase
|
|||
public function whenNoHeaderIsPresentLocaleIsNotChanged()
|
||||
{
|
||||
$this->assertEquals('ru', $this->translator->getLocale());
|
||||
$this->middleware->__invoke(ServerRequestFactory::fromGlobals(), new Response(), function ($req, $resp) {
|
||||
return $resp;
|
||||
});
|
||||
$this->middleware->process(ServerRequestFactory::fromGlobals(), TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals('ru', $this->translator->getLocale());
|
||||
}
|
||||
|
||||
|
@ -43,9 +41,7 @@ class LocaleMiddlewareTest extends TestCase
|
|||
{
|
||||
$this->assertEquals('ru', $this->translator->getLocale());
|
||||
$request = ServerRequestFactory::fromGlobals()->withHeader('Accept-Language', 'es');
|
||||
$this->middleware->__invoke($request, new Response(), function ($req, $resp) {
|
||||
return $resp;
|
||||
});
|
||||
$this->middleware->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals('es', $this->translator->getLocale());
|
||||
}
|
||||
|
||||
|
@ -54,18 +50,16 @@ class LocaleMiddlewareTest extends TestCase
|
|||
*/
|
||||
public function localeGetsNormalized()
|
||||
{
|
||||
$delegate = TestUtils::createDelegateMock();
|
||||
|
||||
$this->assertEquals('ru', $this->translator->getLocale());
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withHeader('Accept-Language', 'es_ES');
|
||||
$this->middleware->__invoke($request, new Response(), function ($req, $resp) {
|
||||
return $resp;
|
||||
});
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
$this->assertEquals('es', $this->translator->getLocale());
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withHeader('Accept-Language', 'en-US');
|
||||
$this->middleware->__invoke($request, new Response(), function ($req, $resp) {
|
||||
return $resp;
|
||||
});
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
$this->assertEquals('en', $this->translator->getLocale());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common\Paginator;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Paginator\Adapter\PaginableRepositoryAdapter;
|
||||
use Shlinkio\Shlink\Common\Repository\PaginableRepositoryInterface;
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace ShlinkioTest\Shlink\Common\Service;
|
|||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\TransferException;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Service\IpLocationResolver;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace ShlinkioTest\Shlink\Common\Service;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Image\ImageBuilder;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common\Twig\Extension;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Twig\Extension\TranslatorExtension;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common\Util;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Util\DateRange;
|
||||
|
||||
class DateRangeTest extends TestCase
|
||||
|
|
35
module/Common/test/Util/TestUtils.php
Normal file
35
module/Common/test/Util/TestUtils.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Common\Util;
|
||||
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophet;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\Response;
|
||||
|
||||
class TestUtils
|
||||
{
|
||||
private static $prophet;
|
||||
|
||||
public static function createDelegateMock(ResponseInterface $response = null, RequestInterface $request = null)
|
||||
{
|
||||
$argument = $request ?: Argument::any();
|
||||
$delegate = static::getProphet()->prophesize(DelegateInterface::class);
|
||||
$delegate->process($argument)->willReturn($response ?: new Response());
|
||||
|
||||
return $delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Prophet
|
||||
*/
|
||||
private static function getProphet()
|
||||
{
|
||||
if (static::$prophet === null) {
|
||||
static::$prophet = new Prophet();
|
||||
}
|
||||
|
||||
return static::$prophet;
|
||||
}
|
||||
}
|
|
@ -2,16 +2,16 @@
|
|||
namespace Shlinkio\Shlink\Core\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Shlinkio\Shlink\Common\Exception\PreviewGenerationException;
|
||||
use Shlinkio\Shlink\Common\Service\PreviewGenerator;
|
||||
use Shlinkio\Shlink\Common\Service\PreviewGeneratorInterface;
|
||||
use Shlinkio\Shlink\Common\Util\ResponseUtilsTrait;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class PreviewAction implements MiddlewareInterface
|
||||
{
|
||||
|
@ -40,46 +40,28 @@ class PreviewAction implements MiddlewareInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$shortCode = $request->getAttribute('shortCode');
|
||||
|
||||
try {
|
||||
$url = $this->urlShortener->shortCodeToUrl($shortCode);
|
||||
if (! isset($url)) {
|
||||
return $out($request, $response->withStatus(404), 'Not found');
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
$imagePath = $this->previewGenerator->generatePreview($url);
|
||||
return $this->generateImageResponse($imagePath);
|
||||
} catch (InvalidShortCodeException $e) {
|
||||
return $out($request, $response->withStatus(404), 'Not found');
|
||||
} catch (PreviewGenerationException $e) {
|
||||
return $out($request, $response->withStatus(500), 'Preview generation error');
|
||||
return $delegate->process($request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ namespace Shlinkio\Shlink\Core\Action;
|
|||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Endroid\QrCode\QrCode;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -12,7 +14,6 @@ use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
|||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
|
||||
use Zend\Expressive\Router\RouterInterface;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class QrCodeAction implements MiddlewareInterface
|
||||
{
|
||||
|
@ -48,42 +49,26 @@ class QrCodeAction implements MiddlewareInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
// Make sure the short URL exists for this short code
|
||||
$shortCode = $request->getAttribute('shortCode');
|
||||
try {
|
||||
$shortUrl = $this->urlShortener->shortCodeToUrl($shortCode);
|
||||
if (! isset($shortUrl)) {
|
||||
return $out($request, $response->withStatus(404), 'Not Found');
|
||||
if ($shortUrl === null) {
|
||||
return $delegate->process($request);
|
||||
}
|
||||
} catch (InvalidShortCodeException $e) {
|
||||
$this->logger->warning('Tried to create a QR code with an invalid short code' . PHP_EOL . $e);
|
||||
return $out($request, $response->withStatus(404), 'Not Found');
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
$path = $this->router->generateUri('long-url-redirect', ['shortCode' => $shortCode]);
|
||||
|
@ -101,13 +86,11 @@ class QrCodeAction implements MiddlewareInterface
|
|||
*/
|
||||
protected function getSizeParam(Request $request)
|
||||
{
|
||||
$size = intval($request->getAttribute('size', 300));
|
||||
$size = (int) $request->getAttribute('size', 300);
|
||||
if ($size < 50) {
|
||||
return 50;
|
||||
} elseif ($size > 1000) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
return $size;
|
||||
return $size > 1000 ? 1000 : $size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
namespace Shlinkio\Shlink\Core\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -11,7 +13,6 @@ use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
|
|||
use Shlinkio\Shlink\Core\Service\VisitsTracker;
|
||||
use Shlinkio\Shlink\Core\Service\VisitsTrackerInterface;
|
||||
use Zend\Diactoros\Response\RedirectResponse;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class RedirectAction implements MiddlewareInterface
|
||||
{
|
||||
|
@ -47,31 +48,15 @@ class RedirectAction implements MiddlewareInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$shortCode = $request->getAttribute('shortCode', '');
|
||||
|
||||
|
@ -80,8 +65,8 @@ class RedirectAction implements MiddlewareInterface
|
|||
|
||||
// If provided shortCode does not belong to a valid long URL, dispatch next middleware, which will trigger
|
||||
// a not-found error
|
||||
if (! isset($longUrl)) {
|
||||
return $this->notFoundResponse($request, $response, $out);
|
||||
if ($longUrl === null) {
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
// Track visit to this short code
|
||||
|
@ -93,18 +78,7 @@ class RedirectAction implements MiddlewareInterface
|
|||
} catch (\Exception $e) {
|
||||
// In case of error, dispatch 404 error
|
||||
$this->logger->error('Error redirecting to long URL.' . PHP_EOL . $e);
|
||||
return $this->notFoundResponse($request, $response, $out);
|
||||
return $delegate->process($request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable $out
|
||||
* @return Response
|
||||
*/
|
||||
protected function notFoundResponse(Request $request, Response $response, callable $out)
|
||||
{
|
||||
return $out($request, $response->withStatus(404), 'Not Found');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ namespace Shlinkio\Shlink\Core\Middleware;
|
|||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
use Zend\Diactoros\Response as DiactResp;
|
||||
|
||||
class QrCodeCacheMiddleware implements MiddlewareInterface
|
||||
{
|
||||
|
@ -26,44 +28,29 @@ class QrCodeCacheMiddleware implements MiddlewareInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$cacheKey = $request->getUri()->getPath();
|
||||
|
||||
// If this QR code is already cached, just return it
|
||||
if ($this->cache->contains($cacheKey)) {
|
||||
$qrData = $this->cache->fetch($cacheKey);
|
||||
$response = new DiactResp();
|
||||
$response->getBody()->write($qrData['body']);
|
||||
return $response->withHeader('Content-Type', $qrData['content-type']);
|
||||
}
|
||||
|
||||
// If not, call the next middleware and cache it
|
||||
/** @var Response $resp */
|
||||
$resp = $out($request, $response);
|
||||
$resp = $delegate->process($request);
|
||||
$this->cache->save($cacheKey, [
|
||||
'body' => $resp->getBody()->__toString(),
|
||||
'content-type' => $resp->getHeaderLine('Content-Type'),
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Core\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Exception\PreviewGenerationException;
|
||||
use Shlinkio\Shlink\Common\Service\PreviewGenerator;
|
||||
use Shlinkio\Shlink\Core\Action\PreviewAction;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
|
||||
class PreviewActionTest extends TestCase
|
||||
|
@ -36,20 +37,17 @@ class PreviewActionTest extends TestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function invalidShortCodeFallbacksToNextMiddlewareWithStatusNotFound()
|
||||
public function invalidShortCodeFallsBackToNextMiddleware()
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn(null)->shouldBeCalledTimes(1);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
$delegate->process(Argument::cetera())->shouldBeCalledTimes(1);
|
||||
|
||||
$resp = $this->action->__invoke(
|
||||
$this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response(),
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
$delegate->reveal()
|
||||
);
|
||||
|
||||
$this->assertEquals(404, $resp->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,9 +61,9 @@ class PreviewActionTest extends TestCase
|
|||
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($url)->shouldBeCalledTimes(1);
|
||||
$this->previewGenerator->generatePreview($url)->willReturn($path)->shouldBeCalledTimes(1);
|
||||
|
||||
$resp = $this->action->__invoke(
|
||||
$resp = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
|
||||
$this->assertEquals(filesize($path), $resp->getHeaderLine('Content-length'));
|
||||
|
@ -75,40 +73,18 @@ class PreviewActionTest extends TestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function invalidShortcodeExceptionReturnsNotFound()
|
||||
public function invalidShortCodeExceptionFallsBackToNextMiddleware()
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(InvalidShortCodeException::class)
|
||||
->shouldBeCalledTimes(1);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
|
||||
$resp = $this->action->__invoke(
|
||||
$this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response(),
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
$delegate->reveal()
|
||||
);
|
||||
|
||||
$this->assertEquals(404, $resp->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function previewExceptionReturnsNotFound()
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(PreviewGenerationException::class)
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$resp = $this->action->__invoke(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response(),
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
);
|
||||
|
||||
$this->assertEquals(500, $resp->getStatusCode());
|
||||
$delegate->process(Argument::any())->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Core\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Response\QrCodeResponse;
|
||||
|
@ -9,7 +10,6 @@ use Shlinkio\Shlink\Core\Action\QrCodeAction;
|
|||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\Expressive\Router\RouterInterface;
|
||||
|
||||
|
@ -37,19 +37,18 @@ class QrCodeActionTest extends TestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function aNonexistentShortCodeWillReturnNotFoundResponse()
|
||||
public function aNotFoundShortCodeWillDelegateIntoNextMiddleware()
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn(null)->shouldBeCalledTimes(1);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
|
||||
$resp = $this->action->__invoke(
|
||||
$this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response(),
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
$delegate->reveal()
|
||||
);
|
||||
$this->assertEquals(404, $resp->getStatusCode());
|
||||
|
||||
$delegate->process(Argument::any())->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,15 +59,14 @@ class QrCodeActionTest extends TestCase
|
|||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(InvalidShortCodeException::class)
|
||||
->shouldBeCalledTimes(1);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
|
||||
$resp = $this->action->__invoke(
|
||||
$this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response(),
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
$delegate->reveal()
|
||||
);
|
||||
$this->assertEquals(404, $resp->getStatusCode());
|
||||
|
||||
$delegate->process(Argument::any())->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,16 +76,15 @@ class QrCodeActionTest extends TestCase
|
|||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn(new ShortUrl())->shouldBeCalledTimes(1);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
|
||||
$resp = $this->action->__invoke(
|
||||
$resp = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response(),
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
$delegate->reveal()
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(QrCodeResponse::class, $resp);
|
||||
$this->assertEquals(200, $resp->getStatusCode());
|
||||
$delegate->process(Argument::any())->shouldHaveBeenCalledTimes(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Core\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Shlinkio\Shlink\Core\Action\RedirectAction;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Shlinkio\Shlink\Core\Service\VisitsTracker;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
|
||||
|
@ -42,7 +42,7 @@ class RedirectActionTest extends TestCase
|
|||
->shouldBeCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
|
||||
$this->assertInstanceOf(Response\RedirectResponse::class, $response);
|
||||
$this->assertEquals(302, $response->getStatusCode());
|
||||
|
@ -53,52 +53,32 @@ class RedirectActionTest extends TestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function nextErrorMiddlewareIsInvokedIfLongUrlIsNotFound()
|
||||
public function nextMiddlewareIsInvokedIfLongUrlIsNotFound()
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn(null)
|
||||
->shouldBeCalledTimes(1);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
|
||||
$originalResponse = new Response();
|
||||
$test = $this;
|
||||
$this->action->__invoke($request, $originalResponse, function (
|
||||
ServerRequestInterface $req,
|
||||
ResponseInterface $resp,
|
||||
$error
|
||||
) use (
|
||||
$test,
|
||||
$request
|
||||
) {
|
||||
$test->assertSame($request, $req);
|
||||
$test->assertEquals(404, $resp->getStatusCode());
|
||||
$test->assertEquals('Not Found', $error);
|
||||
});
|
||||
$this->action->process($request, $delegate->reveal());
|
||||
|
||||
$delegate->process($request)->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function nextErrorMiddlewareIsInvokedIfAnExceptionIsThrown()
|
||||
public function nextMiddlewareIsInvokedIfAnExceptionIsThrown()
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(\Exception::class)
|
||||
->shouldBeCalledTimes(1);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
|
||||
$originalResponse = new Response();
|
||||
$test = $this;
|
||||
$this->action->__invoke($request, $originalResponse, function (
|
||||
ServerRequestInterface $req,
|
||||
ResponseInterface $resp,
|
||||
$error
|
||||
) use (
|
||||
$test,
|
||||
$request
|
||||
) {
|
||||
$test->assertSame($request, $req);
|
||||
$test->assertEquals(404, $resp->getStatusCode());
|
||||
$test->assertEquals('Not Found', $error);
|
||||
});
|
||||
$this->action->process($request, $delegate->reveal());
|
||||
|
||||
$delegate->process($request)->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Core;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Core\ConfigProvider;
|
||||
|
||||
class ConfigProviderTest extends TestCase
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Core\Entity;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Core\Entity\Tag;
|
||||
|
||||
class TagTest extends TestCase
|
||||
|
|
|
@ -3,7 +3,9 @@ namespace ShlinkioTest\Shlink\Core\Middleware;
|
|||
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Shlinkio\Shlink\Core\Middleware\QrCodeCacheMiddleware;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
|
@ -29,18 +31,16 @@ class QrCodeCacheMiddlewareTest extends TestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function noCachedPathFallbacksToNextMiddleware()
|
||||
public function noCachedPathFallsBackToNextMiddleware()
|
||||
{
|
||||
$isCalled = false;
|
||||
$this->middleware->__invoke(
|
||||
ServerRequestFactory::fromGlobals(),
|
||||
new Response(),
|
||||
function ($req, $resp) use (&$isCalled) {
|
||||
$isCalled = true;
|
||||
return $resp;
|
||||
}
|
||||
);
|
||||
$this->assertTrue($isCalled);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
$delegate->process(Argument::any())->willReturn(new Response())->shouldBeCalledTimes(1);
|
||||
|
||||
$this->middleware->process(ServerRequestFactory::fromGlobals()->withUri(
|
||||
new Uri('/foo/bar')
|
||||
), $delegate->reveal());
|
||||
|
||||
$this->assertTrue($this->cache->contains('/foo/bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,19 +51,17 @@ class QrCodeCacheMiddlewareTest extends TestCase
|
|||
$isCalled = false;
|
||||
$uri = (new Uri())->withPath('/foo');
|
||||
$this->cache->save('/foo', ['body' => 'the body', 'content-type' => 'image/png']);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
|
||||
$resp = $this->middleware->__invoke(
|
||||
$resp = $this->middleware->process(
|
||||
ServerRequestFactory::fromGlobals()->withUri($uri),
|
||||
new Response(),
|
||||
function ($req, $resp) use (&$isCalled) {
|
||||
$isCalled = true;
|
||||
return $resp;
|
||||
}
|
||||
$delegate->reveal()
|
||||
);
|
||||
|
||||
$this->assertFalse($isCalled);
|
||||
$resp->getBody()->rewind();
|
||||
$this->assertEquals('the body', $resp->getBody()->getContents());
|
||||
$this->assertEquals('image/png', $resp->getHeaderLine('Content-Type'));
|
||||
$delegate->process(Argument::any())->shouldHaveBeenCalledTimes(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Core\Options;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Core\Options\AppOptions;
|
||||
use Shlinkio\Shlink\Core\Options\AppOptionsFactory;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace ShlinkioTest\Shlink\Core\Service;
|
|||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
|
|
|
@ -10,7 +10,7 @@ use Doctrine\ORM\ORMException;
|
|||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace ShlinkioTest\Shlink\Core\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Entity\Visit;
|
||||
use Shlinkio\Shlink\Core\Repository\VisitRepository;
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace ShlinkioTest\Shlink\Core\Service;
|
|||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?php
|
||||
use Shlinkio\Shlink\Rest\ErrorHandler\JsonErrorHandler;
|
||||
use Shlinkio\Shlink\Rest\ErrorHandler\JsonErrorResponseGenerator;
|
||||
|
||||
return [
|
||||
|
||||
'error_handler' => [
|
||||
'plugins' => [
|
||||
'invokables' => [
|
||||
'application/json' => JsonErrorHandler::class,
|
||||
'application/json' => JsonErrorResponseGenerator::class,
|
||||
],
|
||||
'aliases' => [
|
||||
'application/x-json' => 'application/json',
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
use Shlinkio\Shlink\Rest\Middleware;
|
||||
|
||||
return [
|
||||
|
||||
'middleware_pipeline' => [
|
||||
'pre-routing' => [
|
||||
'path' => '/rest',
|
||||
'middleware' => [
|
||||
Middleware\PathVersionMiddleware::class,
|
||||
],
|
||||
'priority' => 11,
|
||||
],
|
||||
|
||||
'rest' => [
|
||||
'path' => '/rest',
|
||||
'middleware' => [
|
||||
Middleware\CrossDomainMiddleware::class,
|
||||
Middleware\BodyParserMiddleware::class,
|
||||
Middleware\CheckAuthenticationMiddleware::class,
|
||||
],
|
||||
'priority' => 5,
|
||||
],
|
||||
],
|
||||
];
|
|
@ -1,13 +1,17 @@
|
|||
<?php
|
||||
namespace Shlinkio\Shlink\Rest\Action;
|
||||
|
||||
use Fig\Http\Message\RequestMethodInterface;
|
||||
use Fig\Http\Message\StatusCodeInterface;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
|
||||
abstract class AbstractRestAction implements MiddlewareInterface
|
||||
abstract class AbstractRestAction implements MiddlewareInterface, RequestMethodInterface, StatusCodeInterface
|
||||
{
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
|
@ -20,44 +24,27 @@ abstract class AbstractRestAction implements MiddlewareInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
if ($request->getMethod() === 'OPTIONS') {
|
||||
return $response;
|
||||
if ($request->getMethod() === self::METHOD_OPTIONS) {
|
||||
return new EmptyResponse();
|
||||
}
|
||||
|
||||
return $this->dispatch($request, $response, $out);
|
||||
return $this->dispatch($request, $delegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable|null $out
|
||||
* @param DelegateInterface $delegate
|
||||
* @return null|Response
|
||||
*/
|
||||
abstract protected function dispatch(Request $request, Response $response, callable $out = null);
|
||||
abstract protected function dispatch(Request $request, DelegateInterface $delegate);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
namespace Shlinkio\Shlink\Rest\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Firebase\JWT\JWT;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Rest\Authentication\JWTService;
|
||||
use Shlinkio\Shlink\Rest\Authentication\JWTServiceInterface;
|
||||
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
|
||||
|
@ -33,14 +34,17 @@ class AuthenticateAction extends AbstractRestAction
|
|||
* @param ApiKeyServiceInterface|ApiKeyService $apiKeyService
|
||||
* @param JWTServiceInterface|JWTService $jwtService
|
||||
* @param TranslatorInterface $translator
|
||||
* @param LoggerInterface|null $logger
|
||||
*
|
||||
* @Inject({ApiKeyService::class, JWTService::class, "translator"})
|
||||
* @Inject({ApiKeyService::class, JWTService::class, "translator", "Logger_Shlink"})
|
||||
*/
|
||||
public function __construct(
|
||||
ApiKeyServiceInterface $apiKeyService,
|
||||
JWTServiceInterface $jwtService,
|
||||
TranslatorInterface $translator
|
||||
TranslatorInterface $translator,
|
||||
LoggerInterface $logger = null
|
||||
) {
|
||||
parent::__construct($logger);
|
||||
$this->translator = $translator;
|
||||
$this->apiKeyService = $apiKeyService;
|
||||
$this->jwtService = $jwtService;
|
||||
|
@ -48,11 +52,10 @@ class AuthenticateAction extends AbstractRestAction
|
|||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable|null $out
|
||||
* @param DelegateInterface $delegate
|
||||
* @return null|Response
|
||||
*/
|
||||
public function dispatch(Request $request, Response $response, callable $out = null)
|
||||
public function dispatch(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$authData = $request->getParsedBody();
|
||||
if (! isset($authData['apiKey'])) {
|
||||
|
@ -61,7 +64,7 @@ class AuthenticateAction extends AbstractRestAction
|
|||
'message' => $this->translator->translate(
|
||||
'You have to provide a valid API key under the "apiKey" param name.'
|
||||
),
|
||||
], 400);
|
||||
], self::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
// Authenticate using provided API key
|
||||
|
@ -70,7 +73,7 @@ class AuthenticateAction extends AbstractRestAction
|
|||
return new JsonResponse([
|
||||
'error' => RestUtils::INVALID_API_KEY_ERROR,
|
||||
'message' => $this->translator->translate('Provided API key does not exist or is invalid.'),
|
||||
], 401);
|
||||
], self::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
// Generate a JSON Web Token that will be used for authorization in next requests
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace Shlinkio\Shlink\Rest\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -52,18 +53,17 @@ class CreateShortcodeAction extends AbstractRestAction
|
|||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable|null $out
|
||||
* @param DelegateInterface $delegate
|
||||
* @return null|Response
|
||||
*/
|
||||
public function dispatch(Request $request, Response $response, callable $out = null)
|
||||
public function dispatch(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$postData = $request->getParsedBody();
|
||||
if (! isset($postData['longUrl'])) {
|
||||
return new JsonResponse([
|
||||
'error' => RestUtils::INVALID_ARGUMENT_ERROR,
|
||||
'message' => $this->translator->translate('A URL was not provided'),
|
||||
], 400);
|
||||
], self::STATUS_BAD_REQUEST);
|
||||
}
|
||||
$longUrl = $postData['longUrl'];
|
||||
$tags = isset($postData['tags']) && is_array($postData['tags']) ? $postData['tags'] : [];
|
||||
|
@ -87,13 +87,13 @@ class CreateShortcodeAction extends AbstractRestAction
|
|||
$this->translator->translate('Provided URL %s is invalid. Try with a different one.'),
|
||||
$longUrl
|
||||
),
|
||||
], 400);
|
||||
], self::STATUS_BAD_REQUEST);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Unexpected error creating shortcode.' . PHP_EOL . $e);
|
||||
return new JsonResponse([
|
||||
'error' => RestUtils::UNKNOWN_ERROR,
|
||||
'message' => $this->translator->translate('Unexpected error occurred'),
|
||||
], 500);
|
||||
], self::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace Shlinkio\Shlink\Rest\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -43,11 +44,10 @@ class EditTagsAction extends AbstractRestAction
|
|||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable|null $out
|
||||
* @param DelegateInterface $delegate
|
||||
* @return null|Response
|
||||
*/
|
||||
protected function dispatch(Request $request, Response $response, callable $out = null)
|
||||
protected function dispatch(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$shortCode = $request->getAttribute('shortCode');
|
||||
$bodyParams = $request->getParsedBody();
|
||||
|
@ -56,7 +56,7 @@ class EditTagsAction extends AbstractRestAction
|
|||
return new JsonResponse([
|
||||
'error' => RestUtils::INVALID_ARGUMENT_ERROR,
|
||||
'message' => $this->translator->translate('A list of tags was not provided'),
|
||||
], 400);
|
||||
], self::STATUS_BAD_REQUEST);
|
||||
}
|
||||
$tags = $bodyParams['tags'];
|
||||
|
||||
|
@ -67,7 +67,7 @@ class EditTagsAction extends AbstractRestAction
|
|||
return new JsonResponse([
|
||||
'error' => RestUtils::getRestErrorCodeFromException($e),
|
||||
'message' => sprintf($this->translator->translate('No URL found for short code "%s"'), $shortCode),
|
||||
], 404);
|
||||
], self::STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace Shlinkio\Shlink\Rest\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -44,11 +45,10 @@ class GetVisitsAction extends AbstractRestAction
|
|||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable|null $out
|
||||
* @param DelegateInterface $delegate
|
||||
* @return null|Response
|
||||
*/
|
||||
public function dispatch(Request $request, Response $response, callable $out = null)
|
||||
public function dispatch(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$shortCode = $request->getAttribute('shortCode');
|
||||
$startDate = $this->getDateQueryParam($request, 'startDate');
|
||||
|
@ -70,13 +70,13 @@ class GetVisitsAction extends AbstractRestAction
|
|||
$this->translator->translate('Provided short code %s does not exist'),
|
||||
$shortCode
|
||||
),
|
||||
], 404);
|
||||
], self::STATUS_NOT_FOUND);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Unexpected error while parsing short code'. PHP_EOL . $e);
|
||||
return new JsonResponse([
|
||||
'error' => RestUtils::UNKNOWN_ERROR,
|
||||
'message' => $this->translator->translate('Unexpected error occurred'),
|
||||
], 500);
|
||||
], self::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace Shlinkio\Shlink\Rest\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -46,11 +47,10 @@ class ListShortcodesAction extends AbstractRestAction
|
|||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable|null $out
|
||||
* @param DelegateInterface $delegate
|
||||
* @return null|Response
|
||||
*/
|
||||
public function dispatch(Request $request, Response $response, callable $out = null)
|
||||
public function dispatch(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
try {
|
||||
$params = $this->queryToListParams($request->getQueryParams());
|
||||
|
@ -61,7 +61,7 @@ class ListShortcodesAction extends AbstractRestAction
|
|||
return new JsonResponse([
|
||||
'error' => RestUtils::UNKNOWN_ERROR,
|
||||
'message' => $this->translator->translate('Unexpected error occurred'),
|
||||
], 500);
|
||||
], self::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace Shlinkio\Shlink\Rest\Action;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -43,11 +44,10 @@ class ResolveUrlAction extends AbstractRestAction
|
|||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param callable|null $out
|
||||
* @param DelegateInterface $delegate
|
||||
* @return null|Response
|
||||
*/
|
||||
public function dispatch(Request $request, Response $response, callable $out = null)
|
||||
public function dispatch(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$shortCode = $request->getAttribute('shortCode');
|
||||
|
||||
|
@ -57,7 +57,7 @@ class ResolveUrlAction extends AbstractRestAction
|
|||
return new JsonResponse([
|
||||
'error' => RestUtils::INVALID_ARGUMENT_ERROR,
|
||||
'message' => sprintf($this->translator->translate('No URL found for short code "%s"'), $shortCode),
|
||||
], 404);
|
||||
], self::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
return new JsonResponse([
|
||||
|
@ -71,13 +71,13 @@ class ResolveUrlAction extends AbstractRestAction
|
|||
$this->translator->translate('Provided short code "%s" has an invalid format'),
|
||||
$shortCode
|
||||
),
|
||||
], 400);
|
||||
], self::STATUS_BAD_REQUEST);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Unexpected error while resolving the URL behind a short code.' . PHP_EOL . $e);
|
||||
return new JsonResponse([
|
||||
'error' => RestUtils::UNKNOWN_ERROR,
|
||||
'message' => $this->translator->translate('Unexpected error occurred'),
|
||||
], 500);
|
||||
], self::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,28 @@
|
|||
<?php
|
||||
namespace Shlinkio\Shlink\Rest\ErrorHandler;
|
||||
|
||||
use Acelaya\ExpressiveErrorHandler\ErrorHandler\ErrorHandlerInterface;
|
||||
use Acelaya\ExpressiveErrorHandler\ErrorHandler\ErrorResponseGeneratorInterface;
|
||||
use Fig\Http\Message\StatusCodeInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Zend\Expressive\Router\RouteResult;
|
||||
|
||||
class JsonErrorHandler implements ErrorHandlerInterface
|
||||
class JsonErrorResponseGenerator implements ErrorResponseGeneratorInterface, StatusCodeInterface
|
||||
{
|
||||
/**
|
||||
* Final handler for an application.
|
||||
*
|
||||
* @param \Throwable|\Exception $e
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|mixed $err
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, $err = null)
|
||||
public function __invoke($e, Request $request, Response $response)
|
||||
{
|
||||
$hasRoute = $request->getAttribute(RouteResult::class) !== null;
|
||||
$isNotFound = ! $hasRoute && ! isset($err);
|
||||
if ($isNotFound) {
|
||||
$responsePhrase = 'Not found';
|
||||
$status = 404;
|
||||
} else {
|
||||
$status = $response->getStatusCode();
|
||||
$responsePhrase = $status < 400 ? 'Internal Server Error' : $response->getReasonPhrase();
|
||||
$status = $status < 400 ? 500 : $status;
|
||||
}
|
||||
$status = $response->getStatusCode();
|
||||
$responsePhrase = $status < 400 ? 'Internal Server Error' : $response->getReasonPhrase();
|
||||
$status = $status < 400 ? self::STATUS_INTERNAL_SERVER_ERROR : $status;
|
||||
|
||||
return new JsonResponse([
|
||||
'error' => $this->responsePhraseToCode($responsePhrase),
|
|
@ -1,55 +1,45 @@
|
|||
<?php
|
||||
namespace Shlinkio\Shlink\Rest\Middleware;
|
||||
|
||||
use Fig\Http\Message\RequestMethodInterface;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Shlinkio\Shlink\Common\Exception\RuntimeException;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class BodyParserMiddleware implements MiddlewareInterface
|
||||
class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterface
|
||||
{
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$method = $request->getMethod();
|
||||
$currentParams = $request->getParsedBody();
|
||||
|
||||
// In requests that do not allow body or if the body has already been parsed, continue to next middleware
|
||||
if (in_array($method, ['GET', 'HEAD', 'OPTIONS']) || ! empty($currentParams)) {
|
||||
return $out($request, $response);
|
||||
if (! empty($currentParams) || in_array($method, [
|
||||
self::METHOD_GET,
|
||||
self::METHOD_HEAD,
|
||||
self::METHOD_OPTIONS
|
||||
], true)) {
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
// If the accepted content is JSON, try to parse the body from JSON
|
||||
$contentType = $this->getRequestContentType($request);
|
||||
if (in_array($contentType, ['application/json', 'text/json', 'application/x-json'])) {
|
||||
return $out($this->parseFromJson($request), $response);
|
||||
if (in_array($contentType, ['application/json', 'text/json', 'application/x-json'], true)) {
|
||||
return $delegate->process($this->parseFromJson($request));
|
||||
}
|
||||
|
||||
return $out($this->parseFromUrlEncoded($request), $response);
|
||||
return $delegate->process($this->parseFromUrlEncoded($request));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
namespace Shlinkio\Shlink\Rest\Middleware;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
|
||||
use Fig\Http\Message\StatusCodeInterface;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -14,9 +17,8 @@ use Zend\Diactoros\Response\JsonResponse;
|
|||
use Zend\Expressive\Router\RouteResult;
|
||||
use Zend\I18n\Translator\TranslatorInterface;
|
||||
use Zend\Stdlib\ErrorHandler;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class CheckAuthenticationMiddleware implements MiddlewareInterface
|
||||
class CheckAuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterface
|
||||
{
|
||||
const AUTHORIZATION_HEADER = 'Authorization';
|
||||
|
||||
|
@ -52,31 +54,15 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
// If current route is the authenticate route or an OPTIONS request, continue to the next middleware
|
||||
/** @var RouteResult $routeResult */
|
||||
|
@ -86,7 +72,7 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
|
|||
|| $routeResult->getMatchedRouteName() === 'rest-authenticate'
|
||||
|| $request->getMethod() === 'OPTIONS'
|
||||
) {
|
||||
return $out($request, $response);
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
// Check that the auth header was provided, and that it belongs to a non-expired token
|
||||
|
@ -103,7 +89,7 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
|
|||
'message' => sprintf($this->translator->translate(
|
||||
'You need to provide the Bearer type in the %s header.'
|
||||
), self::AUTHORIZATION_HEADER),
|
||||
], 401);
|
||||
], self::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
// Make sure the authorization type is Bearer
|
||||
|
@ -114,7 +100,7 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
|
|||
'message' => sprintf($this->translator->translate(
|
||||
'Provided authorization type %s is not supported. Use Bearer instead.'
|
||||
), $authType),
|
||||
], 401);
|
||||
], self::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -126,20 +112,13 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
|
|||
|
||||
// Update the token expiration and continue to next middleware
|
||||
$jwt = $this->jwtService->refresh($jwt);
|
||||
/** @var Response $response */
|
||||
$response = $out($request, $response);
|
||||
$response = $delegate->process($request);
|
||||
|
||||
// Return the response with the updated token on it
|
||||
return $response->withHeader(self::AUTHORIZATION_HEADER, 'Bearer ' . $jwt);
|
||||
} catch (AuthenticationException $e) {
|
||||
$this->logger->warning('Tried to access API with an invalid JWT.' . PHP_EOL . $e);
|
||||
return $this->createTokenErrorResponse();
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->warning('Unexpected error occurred.' . PHP_EOL . $e);
|
||||
return $this->createTokenErrorResponse();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->warning('Unexpected error occurred.' . PHP_EOL . $e);
|
||||
return $this->createTokenErrorResponse();
|
||||
} finally {
|
||||
ErrorHandler::clean();
|
||||
}
|
||||
|
@ -156,6 +135,6 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
|
|||
),
|
||||
self::AUTHORIZATION_HEADER
|
||||
),
|
||||
], 401);
|
||||
], self::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +1,26 @@
|
|||
<?php
|
||||
namespace Shlinkio\Shlink\Rest\Middleware;
|
||||
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class CrossDomainMiddleware implements MiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* Process an incoming request and/or response.
|
||||
*
|
||||
* Accepts a server-side request and a response instance, and does
|
||||
* something with them.
|
||||
*
|
||||
* If the response is not complete and/or further processing would not
|
||||
* interfere with the work done in the middleware, or if the middleware
|
||||
* wants to delegate to another process, it can use the `$out` callable
|
||||
* if present.
|
||||
*
|
||||
* If the middleware does not return a value, execution of the current
|
||||
* request is considered complete, and the response instance provided will
|
||||
* be considered the response to return.
|
||||
*
|
||||
* Alternately, the middleware may return a response instance.
|
||||
*
|
||||
* Often, middleware will `return $out();`, with the assumption that a
|
||||
* later middleware will return a response.
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|callable $out
|
||||
* @return null|Response
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
/** @var Response $response */
|
||||
$response = $out($request, $response);
|
||||
$response = $delegate->process($request);
|
||||
if (! $request->hasHeader('Origin')) {
|
||||
return $response;
|
||||
}
|
||||
|
@ -49,9 +34,9 @@ class CrossDomainMiddleware implements MiddlewareInterface
|
|||
|
||||
// Add OPTIONS-specific headers
|
||||
foreach ([
|
||||
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS', // TODO Should be based on path
|
||||
'Access-Control-Max-Age' => '1000',
|
||||
'Access-Control-Allow-Headers' => $request->getHeaderLine('Access-Control-Request-Headers'),
|
||||
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS', // TODO Should be based on path
|
||||
'Access-Control-Max-Age' => '1000',
|
||||
'Access-Control-Allow-Headers' => $request->getHeaderLine('Access-Control-Request-Headers'),
|
||||
] as $key => $value) {
|
||||
$response = $response->withHeader($key, $value);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Rest\Action\AuthenticateAction;
|
||||
use Shlinkio\Shlink\Rest\Authentication\JWTService;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
||||
|
@ -42,7 +42,7 @@ class AuthenticateActionTest extends TestCase
|
|||
*/
|
||||
public function notProvidingAuthDataReturnsError()
|
||||
{
|
||||
$resp = $this->action->__invoke(ServerRequestFactory::fromGlobals(), new Response());
|
||||
$resp = $this->action->process(ServerRequestFactory::fromGlobals(), TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(400, $resp->getStatusCode());
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class AuthenticateActionTest extends TestCase
|
|||
$request = ServerRequestFactory::fromGlobals()->withParsedBody([
|
||||
'apiKey' => 'foo',
|
||||
]);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$response->getBody()->rewind();
|
||||
|
@ -75,7 +75,7 @@ class AuthenticateActionTest extends TestCase
|
|||
$request = ServerRequestFactory::fromGlobals()->withParsedBody([
|
||||
'apiKey' => 'foo',
|
||||
]);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(401, $response->getStatusCode());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Shlinkio\Shlink\Rest\Action\CreateShortcodeAction;
|
||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\Diactoros\Uri;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
@ -38,7 +38,10 @@ class CreateShortcodeActionTest extends TestCase
|
|||
*/
|
||||
public function missingLongUrlParamReturnsError()
|
||||
{
|
||||
$response = $this->action->__invoke(ServerRequestFactory::fromGlobals(), new Response());
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals(),
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
}
|
||||
|
||||
|
@ -54,7 +57,7 @@ class CreateShortcodeActionTest extends TestCase
|
|||
$request = ServerRequestFactory::fromGlobals()->withParsedBody([
|
||||
'longUrl' => 'http://www.domain.com/foo/bar',
|
||||
]);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), 'http://foo.com/abc123') > 0);
|
||||
}
|
||||
|
@ -71,7 +74,7 @@ class CreateShortcodeActionTest extends TestCase
|
|||
$request = ServerRequestFactory::fromGlobals()->withParsedBody([
|
||||
'longUrl' => 'http://www.domain.com/foo/bar',
|
||||
]);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::INVALID_URL_ERROR) > 0);
|
||||
}
|
||||
|
@ -88,7 +91,7 @@ class CreateShortcodeActionTest extends TestCase
|
|||
$request = ServerRequestFactory::fromGlobals()->withParsedBody([
|
||||
'longUrl' => 'http://www.domain.com/foo/bar',
|
||||
]);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::UNKNOWN_ERROR) > 0);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
use Shlinkio\Shlink\Core\Service\ShortUrlService;
|
||||
use Shlinkio\Shlink\Rest\Action\EditTagsAction;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
||||
|
@ -33,9 +33,9 @@ class EditTagsActionTest extends TestCase
|
|||
*/
|
||||
public function notProvidingTagsReturnsError()
|
||||
{
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', 'abc123'),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
}
|
||||
|
@ -49,10 +49,10 @@ class EditTagsActionTest extends TestCase
|
|||
$this->shortUrlService->setTagsByShortCode($shortCode, [])->willThrow(InvalidShortCodeException::class)
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', 'abc123')
|
||||
->withParsedBody(['tags' => []]),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ class EditTagsActionTest extends TestCase
|
|||
$this->shortUrlService->setTagsByShortCode($shortCode, [])->willReturn(new ShortUrl())
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', 'abc123')
|
||||
->withParsedBody(['tags' => []]),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
|
||||
use Shlinkio\Shlink\Common\Util\DateRange;
|
||||
use Shlinkio\Shlink\Core\Service\VisitsTracker;
|
||||
use Shlinkio\Shlink\Rest\Action\GetVisitsAction;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
||||
|
@ -38,9 +38,9 @@ class GetVisitsActionTest extends TestCase
|
|||
$this->visitsTracker->info($shortCode, Argument::type(DateRange::class))->willReturn([])
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
@ -55,9 +55,9 @@ class GetVisitsActionTest extends TestCase
|
|||
InvalidArgumentException::class
|
||||
)->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
@ -72,9 +72,9 @@ class GetVisitsActionTest extends TestCase
|
|||
\Exception::class
|
||||
)->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
}
|
||||
|
@ -89,10 +89,10 @@ class GetVisitsActionTest extends TestCase
|
|||
->willReturn([])
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode)
|
||||
->withQueryParams(['endDate' => '2016-01-01 00:00:00']),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Service\ShortUrlService;
|
||||
use Shlinkio\Shlink\Rest\Action\ListShortcodesAction;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
use Zend\Paginator\Adapter\ArrayAdapter;
|
||||
use Zend\Paginator\Paginator;
|
||||
|
||||
class ListShortcodesActionTest extends TestCase
|
||||
class ListShortCodesActionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ListShortcodesAction
|
||||
|
@ -37,11 +37,11 @@ class ListShortcodesActionTest extends TestCase
|
|||
$this->service->listShortUrls($page, null, [], null)->willReturn(new Paginator(new ArrayAdapter()))
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withQueryParams([
|
||||
'page' => $page,
|
||||
]),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ class ListShortcodesActionTest extends TestCase
|
|||
$this->service->listShortUrls($page, null, [], null)->willThrow(\Exception::class)
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->action->__invoke(
|
||||
$response = $this->action->process(
|
||||
ServerRequestFactory::fromGlobals()->withQueryParams([
|
||||
'page' => $page,
|
||||
]),
|
||||
new Response()
|
||||
TestUtils::createDelegateMock()->reveal()
|
||||
);
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Action;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Shlinkio\Shlink\Rest\Action\ResolveUrlAction;
|
||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
||||
use Zend\Diactoros\Response;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
||||
|
@ -38,7 +38,7 @@ class ResolveUrlActionTest extends TestCase
|
|||
->shouldBeCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::INVALID_ARGUMENT_ERROR) > 0);
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class ResolveUrlActionTest extends TestCase
|
|||
->shouldBeCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), 'http://domain.com/foo/bar') > 0);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ class ResolveUrlActionTest extends TestCase
|
|||
->shouldBeCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::INVALID_SHORTCODE_ERROR) > 0);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class ResolveUrlActionTest extends TestCase
|
|||
->shouldBeCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
|
||||
$response = $this->action->__invoke($request, new Response());
|
||||
$response = $this->action->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::UNKNOWN_ERROR) > 0);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace ShlinkioTest\Shlink\Rest\Authentication;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Core\Options\AppOptions;
|
||||
use Shlinkio\Shlink\Rest\Authentication\JWTService;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Rest\ConfigProvider;
|
||||
|
||||
class ConfigProviderTest extends TestCase
|
||||
|
@ -24,7 +24,6 @@ class ConfigProviderTest extends TestCase
|
|||
$config = $this->configProvider->__invoke();
|
||||
|
||||
$this->assertArrayHasKey('error_handler', $config);
|
||||
$this->assertArrayHasKey('middleware_pipeline', $config);
|
||||
$this->assertArrayHasKey('routes', $config);
|
||||
$this->assertArrayHasKey('dependencies', $config);
|
||||
$this->assertArrayHasKey('translator', $config);
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\ErrorHandler;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Shlinkio\Shlink\Rest\ErrorHandler\JsonErrorHandler;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\Expressive\Router\RouteResult;
|
||||
|
||||
class JsonErrorHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var JsonErrorHandler
|
||||
*/
|
||||
protected $errorHandler;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->errorHandler = new JsonErrorHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function noMatchedRouteReturnsNotFoundResponse()
|
||||
{
|
||||
$response = $this->errorHandler->__invoke(ServerRequestFactory::fromGlobals(), new Response());
|
||||
$this->assertInstanceOf(Response\JsonResponse::class, $response);
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function matchedRouteWithErrorReturnsMethodNotAllowedResponse()
|
||||
{
|
||||
$response = $this->errorHandler->__invoke(
|
||||
ServerRequestFactory::fromGlobals(),
|
||||
(new Response())->withStatus(405),
|
||||
405
|
||||
);
|
||||
$this->assertInstanceOf(Response\JsonResponse::class, $response);
|
||||
$this->assertEquals(405, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function responseWithErrorKeepsStatus()
|
||||
{
|
||||
$response = $this->errorHandler->__invoke(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('foo', 'bar', [])
|
||||
),
|
||||
(new Response())->withStatus(401),
|
||||
401
|
||||
);
|
||||
$this->assertInstanceOf(Response\JsonResponse::class, $response);
|
||||
$this->assertEquals(401, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function responseWithoutErrorReturnsStatus500()
|
||||
{
|
||||
$response = $this->errorHandler->__invoke(
|
||||
ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('foo', 'bar', [])
|
||||
),
|
||||
(new Response())->withStatus(200),
|
||||
'Some error'
|
||||
);
|
||||
$this->assertInstanceOf(Response\JsonResponse::class, $response);
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\ErrorHandler;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Rest\ErrorHandler\JsonErrorResponseGenerator;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
|
||||
class JsonErrorResponseGeneratorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var JsonErrorResponseGenerator
|
||||
*/
|
||||
protected $errorHandler;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->errorHandler = new JsonErrorResponseGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function noErrorStatusReturnsInternalServerError()
|
||||
{
|
||||
$response = $this->errorHandler->__invoke(null, ServerRequestFactory::fromGlobals(), new Response());
|
||||
$this->assertInstanceOf(Response\JsonResponse::class, $response);
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function errorStatusReturnsThatStatus()
|
||||
{
|
||||
$response = $this->errorHandler->__invoke(
|
||||
null,
|
||||
ServerRequestFactory::fromGlobals(),
|
||||
(new Response())->withStatus(405)
|
||||
);
|
||||
$this->assertInstanceOf(Response\JsonResponse::class, $response);
|
||||
$this->assertEquals(405, $response->getStatusCode());
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Middleware;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\MethodProphecy;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Shlinkio\Shlink\Rest\Middleware\BodyParserMiddleware;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
|
@ -26,16 +29,13 @@ class BodyParserMiddlewareTest extends TestCase
|
|||
public function requestsFromOtherMethodsJustFallbackToNextMiddleware()
|
||||
{
|
||||
$request = ServerRequestFactory::fromGlobals()->withMethod('GET');
|
||||
$test = $this;
|
||||
$this->middleware->__invoke($request, new Response(), function ($req, $resp) use ($test, $request) {
|
||||
$test->assertSame($request, $req);
|
||||
});
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process($request)->willReturn(new Response());
|
||||
|
||||
$request = $request->withMethod('POST');
|
||||
$test = $this;
|
||||
$this->middleware->__invoke($request, new Response(), function ($req, $resp) use ($test, $request) {
|
||||
$test->assertSame($request, $req);
|
||||
});
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,19 +43,31 @@ class BodyParserMiddlewareTest extends TestCase
|
|||
*/
|
||||
public function jsonRequestsAreJsonDecoded()
|
||||
{
|
||||
$test = $this;
|
||||
$body = new Stream('php://temp', 'wr');
|
||||
$body->write('{"foo": "bar", "bar": ["one", 5]}');
|
||||
$request = ServerRequestFactory::fromGlobals()->withMethod('PUT')
|
||||
->withBody($body)
|
||||
->withHeader('content-type', 'application/json');
|
||||
$test = $this;
|
||||
$this->middleware->__invoke($request, new Response(), function (Request $req, $resp) use ($test, $request) {
|
||||
$test->assertNotSame($request, $req);
|
||||
$test->assertEquals([
|
||||
'foo' => 'bar',
|
||||
'bar' => ['one', 5],
|
||||
], $req->getParsedBody());
|
||||
});
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process(Argument::type(ServerRequestInterface::class))->will(
|
||||
function (array $args) use ($test) {
|
||||
/** @var ServerRequestInterface $req */
|
||||
$req = array_shift($args);
|
||||
|
||||
$test->assertEquals([
|
||||
'foo' => 'bar',
|
||||
'bar' => ['one', 5],
|
||||
], $req->getParsedBody());
|
||||
|
||||
return new Response();
|
||||
}
|
||||
);
|
||||
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,17 +75,29 @@ class BodyParserMiddlewareTest extends TestCase
|
|||
*/
|
||||
public function regularRequestsAreUrlDecoded()
|
||||
{
|
||||
$test = $this;
|
||||
$body = new Stream('php://temp', 'wr');
|
||||
$body->write('foo=bar&bar[]=one&bar[]=5');
|
||||
$request = ServerRequestFactory::fromGlobals()->withMethod('PUT')
|
||||
->withBody($body);
|
||||
$test = $this;
|
||||
$this->middleware->__invoke($request, new Response(), function (Request $req, $resp) use ($test, $request) {
|
||||
$test->assertNotSame($request, $req);
|
||||
$test->assertEquals([
|
||||
'foo' => 'bar',
|
||||
'bar' => ['one', 5],
|
||||
], $req->getParsedBody());
|
||||
});
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process(Argument::type(ServerRequestInterface::class))->will(
|
||||
function (array $args) use ($test) {
|
||||
/** @var ServerRequestInterface $req */
|
||||
$req = array_shift($args);
|
||||
|
||||
$test->assertEquals([
|
||||
'foo' => 'bar',
|
||||
'bar' => ['one', 5],
|
||||
], $req->getParsedBody());
|
||||
|
||||
return new Response();
|
||||
}
|
||||
);
|
||||
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Middleware;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\MethodProphecy;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Rest\Authentication\JWTService;
|
||||
use Shlinkio\Shlink\Rest\Middleware\CheckAuthenticationMiddleware;
|
||||
use ShlinkioTest\Shlink\Common\Util\TestUtils;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\Expressive\Router\Route;
|
||||
use Zend\Expressive\Router\RouteResult;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
||||
|
@ -33,49 +37,42 @@ class CheckAuthenticationMiddlewareTest extends TestCase
|
|||
public function someWhiteListedSituationsFallbackToNextMiddleware()
|
||||
{
|
||||
$request = ServerRequestFactory::fromGlobals();
|
||||
$response = new Response();
|
||||
$isCalled = false;
|
||||
$this->assertFalse($isCalled);
|
||||
$this->middleware->__invoke($request, $response, function ($req, $resp) use (&$isCalled) {
|
||||
$isCalled = true;
|
||||
});
|
||||
$this->assertTrue($isCalled);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process($request)->willReturn(new Response());
|
||||
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteFailure(['GET'])
|
||||
);
|
||||
$response = new Response();
|
||||
$isCalled = false;
|
||||
$this->assertFalse($isCalled);
|
||||
$this->middleware->__invoke($request, $response, function ($req, $resp) use (&$isCalled) {
|
||||
$isCalled = true;
|
||||
});
|
||||
$this->assertTrue($isCalled);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process($request)->willReturn(new Response());
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('rest-authenticate', 'foo', [])
|
||||
RouteResult::fromRoute(new Route('foo', '', Route::HTTP_METHOD_ANY, 'rest-authenticate'), [])
|
||||
);
|
||||
$response = new Response();
|
||||
$isCalled = false;
|
||||
$this->assertFalse($isCalled);
|
||||
$this->middleware->__invoke($request, $response, function ($req, $resp) use (&$isCalled) {
|
||||
$isCalled = true;
|
||||
});
|
||||
$this->assertTrue($isCalled);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process($request)->willReturn(new Response());
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('bar', 'foo', [])
|
||||
RouteResult::fromRoute(new Route('bar', 'foo'), [])
|
||||
)->withMethod('OPTIONS');
|
||||
$response = new Response();
|
||||
$isCalled = false;
|
||||
$this->assertFalse($isCalled);
|
||||
$this->middleware->__invoke($request, $response, function ($req, $resp) use (&$isCalled) {
|
||||
$isCalled = true;
|
||||
});
|
||||
$this->assertTrue($isCalled);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process($request)->willReturn(new Response());
|
||||
$this->middleware->process($request, $delegate->reveal());
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,9 +82,9 @@ class CheckAuthenticationMiddlewareTest extends TestCase
|
|||
{
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('bar', 'foo', [])
|
||||
RouteResult::fromRoute(new Route('bar', 'foo'), [])
|
||||
);
|
||||
$response = $this->middleware->__invoke($request, new Response());
|
||||
$response = $this->middleware->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(401, $response->getStatusCode());
|
||||
}
|
||||
|
||||
|
@ -99,10 +96,11 @@ class CheckAuthenticationMiddlewareTest extends TestCase
|
|||
$authToken = 'ABC-abc';
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('bar', 'foo', [])
|
||||
RouteResult::fromRoute(new Route('bar', 'foo'), [])
|
||||
)->withHeader(CheckAuthenticationMiddleware::AUTHORIZATION_HEADER, $authToken);
|
||||
|
||||
$response = $this->middleware->__invoke($request, new Response());
|
||||
$response = $this->middleware->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
|
||||
$this->assertEquals(401, $response->getStatusCode());
|
||||
$this->assertTrue(strpos($response->getBody()->getContents(), 'You need to provide the Bearer type') > 0);
|
||||
}
|
||||
|
@ -115,10 +113,11 @@ class CheckAuthenticationMiddlewareTest extends TestCase
|
|||
$authToken = 'ABC-abc';
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('bar', 'foo', [])
|
||||
RouteResult::fromRoute(new Route('bar', 'foo'), [])
|
||||
)->withHeader(CheckAuthenticationMiddleware::AUTHORIZATION_HEADER, 'Basic ' . $authToken);
|
||||
|
||||
$response = $this->middleware->__invoke($request, new Response());
|
||||
$response = $this->middleware->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
|
||||
$this->assertEquals(401, $response->getStatusCode());
|
||||
$this->assertTrue(
|
||||
strpos($response->getBody()->getContents(), 'Provided authorization type Basic is not supported') > 0
|
||||
|
@ -133,33 +132,33 @@ class CheckAuthenticationMiddlewareTest extends TestCase
|
|||
$authToken = 'ABC-abc';
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('bar', 'foo', [])
|
||||
RouteResult::fromRoute(new Route('bar', 'foo'), [])
|
||||
)->withHeader(CheckAuthenticationMiddleware::AUTHORIZATION_HEADER, 'Bearer ' . $authToken);
|
||||
$this->jwtService->verify($authToken)->willReturn(false)->shouldBeCalledTimes(1);
|
||||
|
||||
$response = $this->middleware->__invoke($request, new Response());
|
||||
$response = $this->middleware->process($request, TestUtils::createDelegateMock()->reveal());
|
||||
$this->assertEquals(401, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function provideCorrectTokenUpdatesExpirationAndFallbacksToNextMiddleware()
|
||||
public function provideCorrectTokenUpdatesExpirationAndFallsBackToNextMiddleware()
|
||||
{
|
||||
$authToken = 'ABC-abc';
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(
|
||||
RouteResult::class,
|
||||
RouteResult::fromRouteMatch('bar', 'foo', [])
|
||||
RouteResult::fromRoute(new Route('bar', 'foo'), [])
|
||||
)->withHeader(CheckAuthenticationMiddleware::AUTHORIZATION_HEADER, 'bearer ' . $authToken);
|
||||
$this->jwtService->verify($authToken)->willReturn(true)->shouldBeCalledTimes(1);
|
||||
$this->jwtService->refresh($authToken)->willReturn($authToken)->shouldBeCalledTimes(1);
|
||||
|
||||
$isCalled = false;
|
||||
$this->assertFalse($isCalled);
|
||||
$this->middleware->__invoke($request, new Response(), function ($req, $resp) use (&$isCalled) {
|
||||
$isCalled = true;
|
||||
return $resp;
|
||||
});
|
||||
$this->assertTrue($isCalled);
|
||||
$delegate = $this->prophesize(DelegateInterface::class);
|
||||
/** @var MethodProphecy $process */
|
||||
$process = $delegate->process($request)->willReturn(new Response());
|
||||
$resp = $this->middleware->process($request, $delegate->reveal());
|
||||
|
||||
$process->shouldHaveBeenCalledTimes(1);
|
||||
$this->assertArrayHasKey(CheckAuthenticationMiddleware::AUTHORIZATION_HEADER, $resp->getHeaders());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Middleware;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Rest\Middleware\CrossDomainMiddleware;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
|
@ -12,10 +15,15 @@ class CrossDomainMiddlewareTest extends TestCase
|
|||
* @var CrossDomainMiddleware
|
||||
*/
|
||||
protected $middleware;
|
||||
/**
|
||||
* @var ObjectProphecy
|
||||
*/
|
||||
protected $delegate;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->middleware = new CrossDomainMiddleware();
|
||||
$this->delegate = $this->prophesize(DelegateInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,13 +32,9 @@ class CrossDomainMiddlewareTest extends TestCase
|
|||
public function nonCrossDomainRequestsAreNotAffected()
|
||||
{
|
||||
$originalResponse = new Response();
|
||||
$response = $this->middleware->__invoke(
|
||||
ServerRequestFactory::fromGlobals(),
|
||||
$originalResponse,
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
);
|
||||
$this->delegate->process(Argument::any())->willReturn($originalResponse)->shouldbeCalledTimes(1);
|
||||
|
||||
$response = $this->middleware->process(ServerRequestFactory::fromGlobals(), $this->delegate->reveal());
|
||||
$this->assertSame($originalResponse, $response);
|
||||
|
||||
$headers = $response->getHeaders();
|
||||
|
@ -44,12 +48,11 @@ class CrossDomainMiddlewareTest extends TestCase
|
|||
public function anyRequestIncludesTheAllowAccessHeader()
|
||||
{
|
||||
$originalResponse = new Response();
|
||||
$response = $this->middleware->__invoke(
|
||||
$this->delegate->process(Argument::any())->willReturn($originalResponse)->shouldbeCalledTimes(1);
|
||||
|
||||
$response = $this->middleware->process(
|
||||
ServerRequestFactory::fromGlobals()->withHeader('Origin', 'local'),
|
||||
$originalResponse,
|
||||
function ($req, $resp) {
|
||||
return $resp;
|
||||
}
|
||||
$this->delegate->reveal()
|
||||
);
|
||||
$this->assertNotSame($originalResponse, $response);
|
||||
|
||||
|
@ -64,11 +67,10 @@ class CrossDomainMiddlewareTest extends TestCase
|
|||
public function optionsRequestIncludesMoreHeaders()
|
||||
{
|
||||
$originalResponse = new Response();
|
||||
$request = ServerRequestFactory::fromGlobals(['REQUEST_METHOD' => 'OPTIONS'])->withHeader('Origin', 'local');
|
||||
$request = ServerRequestFactory::fromGlobals()->withMethod('OPTIONS')->withHeader('Origin', 'local');
|
||||
$this->delegate->process(Argument::any())->willReturn($originalResponse)->shouldbeCalledTimes(1);
|
||||
|
||||
$response = $this->middleware->__invoke($request, $originalResponse, function ($req, $resp) {
|
||||
return $resp;
|
||||
});
|
||||
$response = $this->middleware->process($request, $this->delegate->reveal());
|
||||
$this->assertNotSame($originalResponse, $response);
|
||||
|
||||
$headers = $response->getHeaders();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Middleware;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Shlinkio\Shlink\Rest\Middleware\PathVersionMiddleware;
|
||||
use Zend\Diactoros\Response;
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace ShlinkioTest\Shlink\Rest\Service;
|
|||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace ShlinkioTest\Shlink\Rest\Util;
|
||||
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
|
||||
use Shlinkio\Shlink\Common\Exception\WrongIpException;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
|
|
Loading…
Reference in a new issue