dongrang2140 2019-05-29 03:03
浏览 22

流明中的反向路由

As REST API developer, in need to test my application. I recently moved to the OpenAPI specification, and I really want to test my API responses against it. My application is based on Lumen.

While routes with no path parameters cause no problem, I'm facing a "reverse routing" problem. For example, in my functional tests, I'm testing the route: GET /themes/{themeId}/questions, which should return the questions related to the theme number themeId.

The actual URI may be something like /themes/17/questions. The problem is that I need to find the exact pattern with {params} in order to test my API against the specification. To be clear, I need a way to :

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

I already found some kind of solution, but I'm absolutely not satisfied and it feels really messy:

/**
 * 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"];
    }
}

Any suggestion would be greatly appreciated!

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
    • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
    • ¥16 mybatis的代理对象无法通过@Autowired装填
    • ¥15 可见光定位matlab仿真
    • ¥15 arduino 四自由度机械臂
    • ¥15 wordpress 产品图片 GIF 没法显示
    • ¥15 求三国群英传pl国战时间的修改方法
    • ¥15 matlab代码代写,需写出详细代码,代价私
    • ¥15 ROS系统搭建请教(跨境电商用途)
    • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。