Skip to content

Commit

Permalink
Disallow extra fields in config to protect from typos (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
PetrHeinz authored Feb 4, 2022
1 parent ee29d3c commit 79f9638
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/Route/InvalidRouteDefinitionException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php declare(strict_types = 1);

namespace BrandEmbassy\Slim\Route;

use RuntimeException;
use function implode;
use function sprintf;

final class InvalidRouteDefinitionException extends RuntimeException
{
/**
* @param string[] $path
*/
public function __construct(array $path, string $hint)
{
parent::__construct(
sprintf('Unexpected route definition key in "%s", did you mean "%s"?', implode('', $path), $hint)
);
}
}
8 changes: 8 additions & 0 deletions src/Route/RouteDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ final class RouteDefinition
public const IGNORE_VERSION_MIDDLEWARE_GROUP = 'ignoreVersionMiddlewareGroup';
public const NAME = 'name';

public const ALL_DEFINED_KEYS = [
self::SERVICE,
self::MIDDLEWARES,
self::MIDDLEWARE_GROUPS,
self::IGNORE_VERSION_MIDDLEWARE_GROUP,
self::NAME,
];

/**
* @var string
*/
Expand Down
24 changes: 24 additions & 0 deletions src/Route/RouteRegister.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
use BrandEmbassy\Slim\Middleware\BeforeRouteMiddlewares;
use BrandEmbassy\Slim\Middleware\MiddlewareGroups;
use Slim\Interfaces\RouterInterface;
use function array_keys;
use function array_merge_recursive;
use function levenshtein;

final class RouteRegister
{
Expand Down Expand Up @@ -66,6 +68,8 @@ public function register(string $apiNamespace, string $routePattern, array $rout
continue;
}

$this->detectTyposInRouteConfiguration([$apiNamespace, $routePattern, $method], $routeDefinitionData);

$routeDefinition = $this->routeDefinitionFactory->create($method, $routeDefinitionData);

$routeName = $routeDefinition->getName() ?? $resolveRoutePath;
Expand Down Expand Up @@ -121,4 +125,24 @@ private function getEmptyRouteDefinitionData(): array
RouteDefinition::NAME => null,
];
}


/**
* @param string[] $path
* @param mixed[] $routeDefinitionData
*/
private function detectTyposInRouteConfiguration(array $path, array $routeDefinitionData): void
{
$usedKeys = array_keys($routeDefinitionData);
foreach ($usedKeys as $usedKey) {
foreach (RouteDefinition::ALL_DEFINED_KEYS as $definedKey) {
$levenshteinDistance = levenshtein($usedKey, $definedKey);
if ($levenshteinDistance > 0 && $levenshteinDistance < 2) {
$path[] = $usedKey;

throw new InvalidRouteDefinitionException($path, $definedKey);
}
}
}
}
}
10 changes: 10 additions & 0 deletions tests/SlimApplicationFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,14 @@ private function prepareEnvironment(string $requestMethod, string $requestUrlPat
$_SERVER[$name] = $value;
}
}


public function testRouteConfigWillFailWhenMisconfigured(): void
{
$this->expectExceptionMessage(
'Unexpected route definition key in "app › /hello-world › get › middleware", did you mean "middlewares"?'
);

SlimAppTester::createSlimApp(__DIR__ . '/typo-in-config.neon');
}
}
21 changes: 21 additions & 0 deletions tests/typo-in-config.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
extensions:
slimApi: \BrandEmbassy\Slim\DI\SlimApiExtension


services:
- BrandEmbassyTest\Slim\Sample\BeforeRouteMiddleware
- BrandEmbassyTest\Slim\Sample\HelloWorldRoute

slimApi:
apiPrefix: '/tests'
slimConfiguration:
settings:
removeDefaultHandlers: true

routes:
"app":
"/hello-world":
get:
service: BrandEmbassyTest\Slim\Sample\HelloWorldRoute
middleware:
- BrandEmbassyTest\Slim\Sample\BeforeRouteMiddleware

0 comments on commit 79f9638

Please sign in to comment.