Обратная маршрутизация в люмен - PullRequest
0 голосов
/ 29 мая 2019

Как разработчик REST API, мне нужно протестировать мое приложение.Недавно я перешел к спецификации OpenAPI, и я действительно хочу проверить свои ответы API на это.Мое приложение основано на Lumen.

Хотя маршруты без параметров пути не вызывают проблем, я сталкиваюсь с проблемой «обратной маршрутизации».Например, в моих функциональных тестах я тестирую маршрут: GET / themes / {themeId} / questions, который должен возвращать questions, связанный с theme числом themeId.

.фактический URI может быть что-то вроде /themes/17/questions.Проблема в том, что мне нужно найти точный шаблон с {params}, чтобы проверить мой API на соответствие спецификации.Чтобы было ясно, мне нужен способ:

/themes/17/questions => /themes/{themeId}/questions

Я уже нашел какое-то решение, но я абсолютно не удовлетворен, и это кажется очень грязным:

/**
 * Get the OpenAPI URI based on the actual request URI.
 *
 * @param string $method The HTTP method (GET, POST, PUT, PATCH, DELETE etc.)
 * @param string $actualUri The actual request URI
 *
 * @return string
 */
public function getOpenAPIUri(string $method, $actualUri)
{
    $currentRouter = $this->dispatch($method, $actualUri); // Calls the Lumen dispatcher

    $filteredRoutes = Collection::make($this->app->router->getRoutes())
        // Reject routes which do not match the method
        ->reject(function ($routeData, $routeKey) use ($method) {
            return !Str::startsWith($routeKey, strtoupper($method));
        })
        // Reject routes which do not match the controller/action
        ->reject(function ($routeData) use ($currentRouter) {
            if (!isset($routeData["action"]["uses"])) {
                return true;
            }

            return $currentRouter[1]["uses"] !== $routeData["action"]["uses"];
        })
        // Reject routes which have not the same amount of parts (splitted by "/")
        ->reject(function ($routeData) use ($actualUri) {
            $actualParts = explode("/", trim($actualUri, "/"));
            $routeParts = explode("/", trim($routeData["uri"], "/"));
            return count($actualParts) !== count($routeParts);
        })
        // Reject routes which does not have the same arguments
        ->reject(function ($routeData, $routeKey) use ($currentRouter) {
            $pattern = "/{([a-zA-Z]+):[a-zA-Z0-9\/\\\+\-_\[\]\*\{\}\|\.\^]+}/";
            $strippedUri = preg_replace($pattern, '{$1}', $routeKey);

            $paramKeys = Collection::make(array_keys($currentRouter[2]))->map(function ($param) {
                return "{{$param}}";
            });

            return !Str::contains($strippedUri, $paramKeys->toArray());
        });

    if ($filteredRoutes->isEmpty()) {
        return $actualUri;
    } else {
        $match = $filteredRoutes->first();

        return $match["uri"];
    }
}

Любое предложение будет с благодарностью!

...