mirror of
https://github.com/DirectoryLister/DirectoryLister.git
synced 2025-08-30 17:20:12 +02:00
Refactored backend to use query strings instead of URL rewriting
This commit is contained in:
@@ -12,7 +12,7 @@ server {
|
||||
location = /robots.txt { access_log off; log_not_found off; }
|
||||
|
||||
location / {
|
||||
try_files $uri /index.php$is_args$args;
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location ~ \.php {
|
||||
|
@@ -7,6 +7,7 @@
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Handle the front controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [QSA,L]
|
||||
</IfModule>
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Bootstrap;
|
||||
|
||||
use App\Middleware;
|
||||
use App\Providers;
|
||||
use DI\Bridge\Slim\Bridge;
|
||||
use DI\Container;
|
||||
@@ -22,7 +21,7 @@ class AppManager
|
||||
|
||||
/** @const Constant description */
|
||||
protected const MIDDLEWARES = [
|
||||
Middleware\StripBasePathMiddleware::class,
|
||||
// ...
|
||||
];
|
||||
|
||||
/** @var Container The applicaiton container */
|
||||
|
@@ -1,101 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use DI\Container;
|
||||
use PHLAK\Config\Config;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Exception\DirectoryNotFoundException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
class DirectoryController
|
||||
{
|
||||
/** @var Config App configuration component */
|
||||
protected $config;
|
||||
|
||||
/** @var Container Application container */
|
||||
protected $container;
|
||||
|
||||
/** @var Twig Twig templating component */
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* Create a new DirectoryController object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Slim\Views\Twig $view
|
||||
*/
|
||||
public function __construct(Container $container, Config $config, Twig $view)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $config;
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the DirectoryController.
|
||||
*
|
||||
* @param \Symfony\Component\Finder\Finder $files
|
||||
* @param \Slim\Psr7\Response $response
|
||||
* @param string $path
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke(
|
||||
Finder $files,
|
||||
Request $request,
|
||||
Response $response,
|
||||
string $path = '.'
|
||||
) {
|
||||
$search = $request->getQueryParams()['search'] ?? null;
|
||||
|
||||
try {
|
||||
$files = $files->in($path);
|
||||
} catch (DirectoryNotFoundException $exception) {
|
||||
return $this->view->render($response->withStatus(404), '404.twig');
|
||||
}
|
||||
|
||||
return $this->view->render($response, 'index.twig', [
|
||||
'files' => $search ? $files->name(
|
||||
sprintf('/(?:.*)%s(?:.*)/i', preg_quote($search, '/'))
|
||||
) : $files->depth(0),
|
||||
'path' => $path,
|
||||
'readme' => $this->readme($path),
|
||||
'search' => $search,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the README file for a given path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return \Symfony\Component\Finder\SplFileInfo|null
|
||||
*/
|
||||
protected function readme($path): ?SplFileInfo
|
||||
{
|
||||
if (! $this->config->get('app.display_readmes', true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$readmes = Finder::create()->in($path)->depth(0)->name('/^README(?:\..+)?$/i');
|
||||
$readmes->filter(function (SplFileInfo $file) {
|
||||
return (bool) preg_match('/text\/.+/', mime_content_type($file->getPathname()));
|
||||
});
|
||||
$readmes->sort(function (SplFileInfo $file1, SplFileInfo $file2) {
|
||||
return $file1->getExtension() <=> $file2->getExtension();
|
||||
});
|
||||
|
||||
if (! $readmes->hasResults()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$readmeArray = iterator_to_array($readmes);
|
||||
|
||||
return array_shift($readmeArray);
|
||||
}
|
||||
}
|
46
app/src/Controllers/IndexController.php
Normal file
46
app/src/Controllers/IndexController.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Handlers;
|
||||
use DI\Container;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
|
||||
class IndexController
|
||||
{
|
||||
/** @var Container Application container */
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Create a new IndexController object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the IndexController.
|
||||
*
|
||||
* @param \Slim\Psr7\Request $request
|
||||
* @param \Slim\Psr7\Response $response
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response)
|
||||
{
|
||||
switch (true) {
|
||||
case array_key_exists('info', $request->getQueryParams()):
|
||||
return $this->container->call(Handlers\FileInfoHandler::class, [$request, $response]);
|
||||
|
||||
case array_key_exists('search', $request->getQueryParams()):
|
||||
return $this->container->call(Handlers\SearchHandler::class, [$request, $response]);
|
||||
|
||||
default:
|
||||
return $this->container->call(Handlers\DirectoryHandler::class, [$request, $response]);
|
||||
}
|
||||
}
|
||||
}
|
90
app/src/Handlers/DirectoryHandler.php
Normal file
90
app/src/Handlers/DirectoryHandler.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers;
|
||||
|
||||
use PHLAK\Config\Config;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Exception\DirectoryNotFoundException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
class DirectoryHandler
|
||||
{
|
||||
/** @var Config App configuration component */
|
||||
protected $config;
|
||||
|
||||
/** @var Finder File finder component */
|
||||
protected $finder;
|
||||
|
||||
/** @var Twig Twig templating component */
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* Create a new IndexController object.
|
||||
*
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Symfony\Component\Finder\Finder $finder
|
||||
* @param \Slim\Views\Twig $view
|
||||
*/
|
||||
public function __construct(Config $config, Finder $finder, Twig $view)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->finder = $finder;
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the IndexController.
|
||||
*
|
||||
* @param \Slim\Psr7\Request $request
|
||||
* @param \Slim\Psr7\Response $response
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response)
|
||||
{
|
||||
$path = $request->getQueryParams()['dir'] ?? '.';
|
||||
|
||||
try {
|
||||
$files = $this->finder->in($path)->depth(0);
|
||||
} catch (DirectoryNotFoundException $exception) {
|
||||
return $this->view->render($response->withStatus(404), '404.twig');
|
||||
}
|
||||
|
||||
return $this->view->render($response, 'index.twig', [
|
||||
'files' => $files,
|
||||
'path' => $path,
|
||||
'readme' => $this->readme($files),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the README file within a finder object.
|
||||
*
|
||||
* @param \Symfony\Component\Finder\Finder $files
|
||||
*
|
||||
* @return \Symfony\Component\Finder\SplFileInfo|null
|
||||
*/
|
||||
protected function readme(Finder $files): ?SplFileInfo
|
||||
{
|
||||
if (! $this->config->get('app.display_readmes', true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$readmes = (clone $files)->name('/^README(?:\..+)?$/i');
|
||||
|
||||
$readmes->filter(function (SplFileInfo $file) {
|
||||
return (bool) preg_match('/text\/.+/', mime_content_type($file->getPathname()));
|
||||
})->sort(function (SplFileInfo $file1, SplFileInfo $file2) {
|
||||
return $file1->getExtension() <=> $file2->getExtension();
|
||||
});
|
||||
|
||||
if (! $readmes->hasResults()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $readmes->getIterator()->current();
|
||||
}
|
||||
}
|
@@ -1,13 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
namespace App\Handlers;
|
||||
|
||||
use DI\Container;
|
||||
use PHLAK\Config\Config;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use SplFileInfo;
|
||||
|
||||
class FileInfoController
|
||||
class FileInfoHandler
|
||||
{
|
||||
/** @var Container The application container */
|
||||
protected $container;
|
||||
@@ -16,7 +17,7 @@ class FileInfoController
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Create a new FileInfoController object.
|
||||
* Create a new FileInfoHandler object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
* @param \PHLAK\Config\Config $config
|
||||
@@ -28,13 +29,15 @@ class FileInfoController
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the FileInfoController.
|
||||
* Invoke the FileInfoHandler.
|
||||
*
|
||||
* @param \Slim\Psr7\Request $request
|
||||
* @param \Slim\Psr7\Response $response
|
||||
* @param string $path
|
||||
*/
|
||||
public function __invoke(Response $response, string $path = '.')
|
||||
public function __invoke(Request $request, Response $response)
|
||||
{
|
||||
$path = $request->getQueryParams()['info'];
|
||||
|
||||
$file = new SplFileInfo(
|
||||
realpath($this->container->get('base_path') . '/' . $path)
|
||||
);
|
51
app/src/Handlers/SearchHandler.php
Normal file
51
app/src/Handlers/SearchHandler.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers;
|
||||
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class SearchHandler
|
||||
{
|
||||
/** @var Finder File finder component */
|
||||
protected $finder;
|
||||
|
||||
/** @var Twig Twig templating component */
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* Create a new SearchHandler object.
|
||||
*
|
||||
* @param \Symfony\Component\Finder\Finder $finder
|
||||
* @param \Slim\Views\Twig $view
|
||||
*/
|
||||
public function __construct(Finder $finder, Twig $view)
|
||||
{
|
||||
$this->finder = $finder;
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the SearchHandler.
|
||||
*
|
||||
* @param \Slim\Psr7\Request $request
|
||||
* @param \Slim\Psr7\Response $response
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response)
|
||||
{
|
||||
$search = $request->getQueryParams()['search'];
|
||||
|
||||
$files = $this->finder->in('.')->name(
|
||||
sprintf('/(?:.*)%s(?:.*)/i', preg_quote($search, '/'))
|
||||
);
|
||||
|
||||
return $this->view->render($response, 'index.twig', [
|
||||
'files' => $files,
|
||||
'search' => $search,
|
||||
]);
|
||||
}
|
||||
}
|
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Middleware;
|
||||
|
||||
use DI\Container;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class StripBasePathMiddleware
|
||||
{
|
||||
/** @var Container The application container */
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Create a new CanonicalizePathMiddleware object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize the received path variable.
|
||||
*
|
||||
* @param \Slim\Psr7\Request $request
|
||||
* @param \Slim\Psr7\Response $response
|
||||
* @param callable $next
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
$path = $request->getUri()->getPath();
|
||||
|
||||
$request = $request->withUri(
|
||||
$request->getUri()->withPath($this->stripBasePath($path))
|
||||
);
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip the base URL path from a path string.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function stripBasePath(string $path): string
|
||||
{
|
||||
$pattern = sprintf('/^%s/', preg_quote(dirname($_SERVER['SCRIPT_NAME']), '/'));
|
||||
|
||||
return '/' . ltrim(preg_replace($pattern, '', $path), '/');
|
||||
}
|
||||
}
|
@@ -21,8 +21,7 @@ $container->set('base_path', __DIR__);
|
||||
$app = $container->call(AppManager::class);
|
||||
|
||||
// Register routes
|
||||
$app->get('/file-info/[{path:.*}]', Controllers\FileInfoController::class);
|
||||
$app->get('/[{path:.*}]', Controllers\DirectoryController::class);
|
||||
$app->get('/[{path:.*}]', Controllers\IndexController::class);
|
||||
|
||||
// Engage!
|
||||
$app->run();
|
||||
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use App\Controllers\FileInfoController;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Psr7\Response;
|
||||
use Tests\TestCase;
|
||||
|
||||
class FileInfoControllerTest extends TestCase
|
||||
{
|
||||
public function test_it_can_return_a_successful_response(): void
|
||||
{
|
||||
$controller = new FileInfoController($this->container, $this->config);
|
||||
|
||||
$response = $controller(new Response(), 'README.md');
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function test_it_can_return_a_not_found_response(): void
|
||||
{
|
||||
$controller = new FileInfoController($this->container, $this->config);
|
||||
|
||||
$response = $controller(new Response(), 'not_a_file.test');
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function test_it_returns_an_error_when_file_size_is_too_large(): void
|
||||
{
|
||||
$this->config->set('app.max_hash_size', 10);
|
||||
$controller = new FileInfoController($this->container, $this->config);
|
||||
|
||||
$response = $controller(new Response(), 'README.md');
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
}
|
||||
}
|
74
tests/Controllers/IndexControllerTest.php
Normal file
74
tests/Controllers/IndexControllerTest.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use App\Controllers\IndexController;
|
||||
use App\Handlers;
|
||||
use DI\Container;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Tests\TestCase;
|
||||
|
||||
class IndexControllerTest extends TestCase
|
||||
{
|
||||
public function test_it_handles_a_file_info_request(): void
|
||||
{
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['info' => 'file.test']);
|
||||
|
||||
$container = $this->createMock(Container::class);
|
||||
$container->expects($this->once())->method('call')->with(
|
||||
Handlers\FileInfoHandler::class,
|
||||
[$request, $response = new Response]
|
||||
);
|
||||
|
||||
$controller = new IndexController($container);
|
||||
|
||||
$controller($request, $response);
|
||||
}
|
||||
|
||||
public function test_it_handles_a_search_request(): void
|
||||
{
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['search' => 'file.test']);
|
||||
|
||||
$container = $this->createMock(Container::class);
|
||||
$container->expects($this->once())->method('call')->with(
|
||||
Handlers\SearchHandler::class,
|
||||
[$request, $response = new Response]
|
||||
);
|
||||
|
||||
$controller = new IndexController($container);
|
||||
|
||||
$controller($request, $response);
|
||||
}
|
||||
|
||||
public function test_it_handles_a_directory_request(): void
|
||||
{
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['dir' => 'some/directory']);
|
||||
|
||||
$container = $this->createMock(Container::class);
|
||||
$container->expects($this->once())->method('call')->with(
|
||||
Handlers\DirectoryHandler::class,
|
||||
[$request, $response = new Response]
|
||||
);
|
||||
|
||||
$controller = new IndexController($container);
|
||||
|
||||
$controller($request, $response);
|
||||
}
|
||||
|
||||
public function test_it_handles_a_directory_request_by_default(): void
|
||||
{
|
||||
$container = $this->createMock(Container::class);
|
||||
$container->expects($this->once())->method('call')->with(
|
||||
Handlers\DirectoryHandler::class,
|
||||
[$request = $this->createMock(Request::class), $response = new Response]
|
||||
);
|
||||
|
||||
$controller = new IndexController($container);
|
||||
|
||||
$controller($request, $response);
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use App\Controllers\DirectoryController;
|
||||
use App\Handlers\DirectoryHandler;
|
||||
use App\Providers\TwigProvider;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Psr7\Request;
|
||||
@@ -11,7 +11,7 @@ use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DirectoryControllerTest extends TestCase
|
||||
class DirectoryHandlerTest extends TestCase
|
||||
{
|
||||
/** @dataProvider configOptions */
|
||||
public function test_it_returns_a_successful_response(
|
||||
@@ -25,18 +25,13 @@ class DirectoryControllerTest extends TestCase
|
||||
|
||||
$this->container->call(TwigProvider::class);
|
||||
|
||||
$controller = new DirectoryController(
|
||||
$this->container,
|
||||
$controller = new DirectoryHandler(
|
||||
$this->config,
|
||||
new Finder,
|
||||
$this->container->get(Twig::class)
|
||||
);
|
||||
|
||||
chdir($this->filePath('.'));
|
||||
$response = $controller(
|
||||
new Finder(),
|
||||
$this->createMock(Request::class),
|
||||
new Response()
|
||||
);
|
||||
$response = $controller($this->createMock(Request::class), new Response);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
@@ -54,19 +49,17 @@ class DirectoryControllerTest extends TestCase
|
||||
|
||||
$this->container->call(TwigProvider::class);
|
||||
|
||||
$controller = new DirectoryController(
|
||||
$this->container,
|
||||
$controller = new DirectoryHandler(
|
||||
$this->config,
|
||||
new Finder,
|
||||
$this->container->get(Twig::class)
|
||||
);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['dir' => 'subdir']);
|
||||
|
||||
chdir($this->filePath('.'));
|
||||
$response = $controller(
|
||||
new Finder(),
|
||||
$this->createMock(Request::class),
|
||||
new Response(),
|
||||
'subdir'
|
||||
);
|
||||
$response = $controller($request, new Response);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
@@ -76,48 +69,19 @@ class DirectoryControllerTest extends TestCase
|
||||
{
|
||||
$this->container->call(TwigProvider::class);
|
||||
|
||||
$controller = new DirectoryController(
|
||||
$this->container,
|
||||
$this->config,
|
||||
$this->container->get(Twig::class)
|
||||
);
|
||||
|
||||
chdir($this->filePath('.'));
|
||||
$response = $controller(
|
||||
new Finder(),
|
||||
$this->createMock(Request::class),
|
||||
new Response(),
|
||||
'404'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function test_it_returns_a_successful_response_for_a_search_request(): void
|
||||
{
|
||||
$this->container->call(TwigProvider::class);
|
||||
|
||||
$controller = new DirectoryController(
|
||||
$this->container,
|
||||
$controller = new DirectoryHandler(
|
||||
$this->config,
|
||||
new Finder,
|
||||
$this->container->get(Twig::class)
|
||||
);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn([
|
||||
'search' => 'charlie'
|
||||
]);
|
||||
$request->method('getQueryParams')->willReturn(['dir' => '404']);
|
||||
|
||||
chdir($this->filePath('.'));
|
||||
$response = $controller(
|
||||
new Finder(),
|
||||
$request,
|
||||
new Response()
|
||||
);
|
||||
$response = $controller($request, new Response);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
59
tests/Handlers/FileInfoHandlerTest.php
Normal file
59
tests/Handlers/FileInfoHandlerTest.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Handlers;
|
||||
|
||||
use App\Handlers\FileInfoHandler;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Tests\TestCase;
|
||||
|
||||
class FileInfoHandlerTest extends TestCase
|
||||
{
|
||||
public function test_it_can_return_a_successful_response(): void
|
||||
{
|
||||
$handler = new FileInfoHandler($this->container, $this->config);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['info' => 'README.md']);
|
||||
|
||||
$response = $handler($request, new Response);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertEquals(json_encode([
|
||||
'hashes' => [
|
||||
'md5' => '6e35c5c3bca40dfb96cbb449fd06df38',
|
||||
'sha1' => '7ea619032a992824fac30026d3df919939c7ebfb',
|
||||
'sha256' => '40adf7348820699ed3e72dc950ccd8d8d538065a91eba3c76263c44b1d12df9c',
|
||||
]
|
||||
]), (string) $response->getBody());
|
||||
}
|
||||
|
||||
public function test_it_can_return_a_not_found_response(): void
|
||||
{
|
||||
$handler = new FileInfoHandler($this->container, $this->config);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['info' => 'not_a_file.test']);
|
||||
|
||||
$response = $handler($request, new Response);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function test_it_returns_an_error_when_file_size_is_too_large(): void
|
||||
{
|
||||
$this->config->set('app.max_hash_size', 10);
|
||||
$handler = new FileInfoHandler($this->container, $this->config);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['info' => 'README.md']);
|
||||
|
||||
$response = $handler($request, new Response);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
}
|
||||
}
|
30
tests/Handlers/SearchHandlerTest.php
Normal file
30
tests/Handlers/SearchHandlerTest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Handlers;
|
||||
|
||||
use App\Handlers\SearchHandler;
|
||||
use App\Providers\TwigProvider;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SearchHandlerTest extends TestCase
|
||||
{
|
||||
public function test_it_returns_a_successful_response_for_a_search_request(): void
|
||||
{
|
||||
$this->container->call(TwigProvider::class);
|
||||
|
||||
$handler = new SearchHandler(new Finder, $this->container->get(Twig::class));
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['search' => 'charlie']);
|
||||
|
||||
$response = $handler($request, new Response);
|
||||
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Middleware;
|
||||
|
||||
use App\Middleware\StripBasePathMiddleware;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\App;
|
||||
use Slim\Psr7\Headers;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Stream;
|
||||
use Slim\Psr7\Uri;
|
||||
use Tests\TestCase;
|
||||
|
||||
class StripBasePathMiddlewareTest extends TestCase
|
||||
{
|
||||
public function test_the_path_is_unchanged_for_a_request_in_the_webroot(): void
|
||||
{
|
||||
$middleware = new StripBasePathMiddleware($this->container);
|
||||
|
||||
$uri = new Uri('http', 'localhost', null, '/foo/bar');
|
||||
$request = new Request('GET', $uri, new Headers, [], [], new Stream(fopen('php://memory', 'w+')));
|
||||
|
||||
$handler = $this->createMock(App::class);
|
||||
$handler->expects($this->once())->method('handle')->with(
|
||||
$this->callback(function (ServerRequestInterface $request): bool {
|
||||
return $request->getUri()->getPath() == '/foo/bar';
|
||||
})
|
||||
);
|
||||
|
||||
$middleware($request, $handler);
|
||||
}
|
||||
|
||||
public function test_it_strips_the_base_path_for_a_request_in_a_subdirectory(): void
|
||||
{
|
||||
$_SERVER['SCRIPT_NAME'] = '/some/dir/index.php';
|
||||
|
||||
$middleware = new StripBasePathMiddleware($this->container);
|
||||
|
||||
$uri = new Uri('http', 'localhost', null, '/some/dir/foo/bar');
|
||||
$request = new Request('GET', $uri, new Headers, [], [], new Stream(fopen('php://memory', 'w+')));
|
||||
|
||||
$handler = $this->createMock(App::class);
|
||||
$handler->expects($this->once())->method('handle')->with(
|
||||
$this->callback(function (ServerRequestInterface $request): bool {
|
||||
return $request->getUri()->getPath() == '/foo/bar';
|
||||
})
|
||||
);
|
||||
|
||||
$middleware($request, $handler);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user