diff --git a/.github/changelog.yml b/.github/changelog.yml new file mode 100644 index 0000000..06048e3 --- /dev/null +++ b/.github/changelog.yml @@ -0,0 +1,36 @@ +title: '## Change Log' +# style allow: simple, markdown(mkdown), ghr(gh-release) +style: gh-release +# group names +names: [Refactor, Fixed, Feature, Update, Other] +#repo_url: https://github.com/gookit/gcli + +filters: + # message length should >= 12 + - name: msg_len + min_len: 12 + # message words should >= 3 + - name: words_len + min_len: 3 + - name: keyword + keyword: format code + exclude: true + - name: keywords + keywords: format code, action test + exclude: true + +# group match rules +# not matched will use 'Other' group. +rules: + - name: Refactor + start_withs: [refactor, break] + contains: ['refactor:', 'break:'] + - name: Fixed + start_withs: [fix] + contains: ['fix:'] + - name: Feature + start_withs: [feat, new] + contains: ['feat:', 'new:'] + - name: Update + start_withs: [up] + contains: ['update:', 'up:'] diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..fc10f0b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: composer + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "daily" diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..8fc15f1 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,59 @@ +name: Unit-tests + +on: + pull_request: + push: + paths: + - '**.php' + - 'composer.json' + - '**.yml' + +jobs: + test: + name: Test on php ${{ matrix.php}} + runs-on: ubuntu-latest + timeout-minutes: 10 + strategy: + fail-fast: true + matrix: + php: [8.2, 8.1, 8.3, 8.4] # + + steps: + - name: Checkout + uses: actions/checkout@v6 + + # usage refer https://github.com/shivammathur/setup-php + - name: Setup PHP + timeout-minutes: 5 + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php}} + tools: pecl, php-cs-fixer, phpunit + extensions: mbstring, dom, fileinfo, openssl # , swoole-4.4.19 #optional, setup extensions + ini-values: post_max_size=56M, short_open_tag=On #optional, setup php.ini configuration + coverage: xdebug #optional, setup coverage driver: xdebug, none + + - name: Install dependencies + run: composer install --no-progress --no-suggest + + - name: Run test suite + run: | + phpunit --coverage-clover ./test/clover.xml + +# - name: Coveralls Parallel +# uses: coverallsapp/github-action@master +# with: +# github-token: ${{ secrets.github_token }} +# flag-name: run-${{ matrix.php }} +# path-to-lcov: ./test/clover.xml +# parallel: true + +# finish: +# needs: test +# runs-on: ubuntu-latest +# steps: +# - name: Coveralls Finished +# uses: coverallsapp/github-action@master +# with: +# github-token: ${{ secrets.github_token }} +# parallel-finished: true \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5cc4e7a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: Tag-release + +on: + push: + tags: + - v* + +jobs: + release: + name: Tag release + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set ENV for github-release + # https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable + run: | + echo "RELEASE_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV + echo "RELEASE_NAME=$GITHUB_WORKFLOW" >> $GITHUB_ENV + + - name: Generate changelog + run: | + curl https://github.com/gookit/gitw/releases/latest/download/chlog-linux-amd64 -L -o /usr/local/bin/chlog + chmod a+x /usr/local/bin/chlog + chlog -c .github/changelog.yml -o changelog.md prev last + + # https://github.com/softprops/action-gh-release + - name: Create release and upload assets + uses: softprops/action-gh-release@v2 + with: + name: ${{ env.RELEASE_TAG }} + tag_name: ${{ env.RELEASE_TAG }} + body_path: changelog.md + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 06bb496..f3a532c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - ### OSX template *.DS_Store @@ -10,4 +9,6 @@ composer.lock *.swp *.swo +*.cache .DS_Store +test/routes-cache.php \ No newline at end of file diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..6273e5b --- /dev/null +++ b/.php_cs @@ -0,0 +1,27 @@ +setRiskyAllowed(true)->setRules([ + '@PSR2' => true, + 'array_syntax' => [ + 'syntax' => 'short' + ], + 'class_attributes_separation' => true, + 'declare_strict_types' => true, + 'encoding' => true, // MUST use only UTF-8 without BOM + 'global_namespace_import' => true, +// 'header_comment' => [ +// 'comment_type' => 'PHPDoc', +// 'header' => $header, +// 'separate' => 'bottom' +// ], + 'no_unused_imports' => true, + 'single_quote' => true, + 'standardize_not_equals' => true, + ])->setFinder(PhpCsFixer\Finder::create() + // ->exclude('test') + ->exclude('docs')->exclude('vendor')->in(__DIR__))->setUsingCache(false); diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/README.md b/README.md index 1fda0f5..786360b 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,56 @@ -# php simple router +# SRoute -[![License](https://img.shields.io/packagist/l/inhere/console.svg?style=flat-square)](LICENSE.md) -[![Php Version](https://img.shields.io/badge/php-%3E=5.6-brightgreen.svg?maxAge=2592000)](https://packagist.org/packages/inhere/sroute) +[![License](https://img.shields.io/packagist/l/inhere/sroute.svg?style=flat-square)](LICENSE) +[![PHP Version](https://img.shields.io/packagist/php-v/inhere/sroute.svg?colorB=green)](https://packagist.org/packages/inhere/sroute) [![Latest Stable Version](http://img.shields.io/packagist/v/inhere/sroute.svg)](https://packagist.org/packages/inhere/sroute) +[![Unit-tests](https://github.com/inhere/php-sroute/actions/workflows/php.yml/badge.svg)](https://github.com/inhere/php-sroute/actions) +[![Coverage Status](https://coveralls.io/repos/github/inhere/php-sroute/badge.svg?branch=master)](https://coveralls.io/github/inhere/php-sroute?branch=master) -非常轻量级的路由器。无依赖、简洁、速度快、自定义性强 +非常快速且轻量的请求匹配路由器, web 路由框架。 -- 轻量级且速度快,查找速度不受路由数量的影响 -- 支持路由组。支持路由参数定义,以及丰富的自定义路由选项(比如设定 默认值、domains、schemas等检查限制) -- 支持请求方法: `GET` `POST` `PUT` `DELETE` `HEAD` `OPTIONS` ... -- 支持自动匹配路由到控制器就像 Yii 一样, 请参看配置项 `autoRoute`. -- 三个版本:静态版本 `SRouter`, 对象版本 `ORouter`, 支持路由缓存的对象版本 `CachedRouter` + - 无依赖、简洁、速度快、功能完善 + - 轻量级且速度快,查找速度不受路由数量的影响 + - 支持路由组, 支持路由参数定义,以及丰富的自定义路由选项 + - 支持给指定的路由命名,可根据名称拿到注册的路由对象 + - 支持请求方法: `GET` `POST` `PUT` `DELETE` `HEAD` `OPTIONS` ... + - 支持自动匹配路由到控制器就像 Yii 一样, 请参看配置项 `autoRoute` (不推荐) + - 压测对比数据请看[路由测试](#ab-test) -内置了一个调度器: +**多个版本:** + +> 不同的版本有稍微的区别以适应不同的场景 + +- `Router` 通用版本,也是后几个版本的基础类,适用于所有的情况。 +- `SRouter` 静态类版本。`Router` 的简单包装,通过静态方法使用(方便小应用快速使用) +- `CachedRouter` 继承自`Router`,支持路由缓存的版本,可以 **缓存路由信息到文件** + - 适合php-fpm 环境使用(有缓存将会省去每次的路由收集和解析消耗) +- `PreMatchRouter` 继承自`Router`,预匹配路由器。**当应用的静态路由较多时,将拥有更快的匹配速度** + - 适合php-fpm 环境,php-fpm 情形下,实际上我们在收集路由之前,已经知道了路由path和请求动作METHOD +- `ServerRouter` 继承自`Router`,服务器路由。内置支持**动态路由临时缓存**. 适合 `swoole` 等**常驻内存应用**使用 + - 最近请求过的动态路由将会缓存为一个静态路由信息,下次相同路由将会直接匹配命中 + +**内置调度器:** - 支持事件: `found` `notFound` `execStart` `execEnd` `execError`. 当触发事件时你可以做一些事情(比如记录日志等) - 支持动态获取`action`名。支持设置方法执行器(`actionExecutor`),通过方法执行器来自定义调用真实请求方法. -- 支持通过方法 `SRouter::dispatch($path, $method)` 手动调度一个路由 +- 支持通过方法 `$router->dispatch($path, $method)` 手动调度一个路由 - 你即使不配置任何东西, 它也能很好的工作 -**[EN README](./README.md)** +**路由器管理** + +`RouterManager` 当需要在一个项目里处理多个域名下的请求时,方便的根据不同域名配置多个路由器 + +**[EN README](README_en.md)** ## 项目地址 -- **github** https://github.com/inhere/php-srouter.git -- **git@osc** https://gitee.com/inhere/php-srouter.git +- **github** https://github.com/inhere/php-sroute.git +- **gitee** https://gitee.com/inhere/php-sroute.git ## 安装 +> required PHP 8.0+ + - composer 命令 ```php @@ -47,19 +70,22 @@ composer require inhere/sroute - 直接拉取 ```bash -git clone https://github.com/inhere/php-srouter.git // github -git clone https://git.oschina.net/inhere/php-srouter.git // git@osc +git clone https://github.com/inhere/php-sroute.git // github ``` + ## 压测 自动生成了1000条路由,每条有9个参数位,分别测试1000次的 - 第一条路由匹配 - 最后一条路由匹配 -- 不会匹配到的路由 +- 不存在的路由匹配 + +详细的测试代码请看仓库 https://github.com/ulue/php-router-benchmark -压测结果 +- 压测日期 **2018.11.19** +- An example route: `/9b37eef21e/{arg1}/{arg2}/{arg3}/{arg4}/{arg5}/{arg6}/{arg7}/{arg8}/{arg9}/bda37e9f9b` ## Worst-case matching @@ -67,23 +93,25 @@ This benchmark matches the last route and unknown route. It generates a randomly This benchmark consists of 14 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. -Test Name | Results | Time | + Interval | Change ---------- | ------- | ---- | ---------- | ------ -**ORouter** - unknown route (1000 routes) | 988 | 0.0000120063 | +0.0000000000 | baseline -**ORouter** - last route (1000 routes) | 988 | 0.0000122867 | +0.0000002804 | 2% slower -**SRouter** - unknown route (1000 routes) | 983 | 0.0000123633 | +0.0000003570 | 3% slower -**SRouter** - last route (1000 routes) | 998 | 0.0000142205 | +0.0000022142 | 18% slower -Symfony2 Dumped - last route (1000 routes) | 990 | 0.0000468579 | +0.0000348516 | 290% slower -Symfony2 Dumped - unknown route (1000 routes) | 995 | 0.0000490268 | +0.0000370205 | 308% slower -FastRoute - unknown route (1000 routes) | 968 | 0.0001358227 | +0.0001238164 | 1031% slower -FastRoute(cached) - last route (1000 routes) | 999 | 0.0001397746 | +0.0001277683 | 1064% slower -FastRoute(cached) - unknown route (1000 routes) | 960 | 0.0001424064 | +0.0001304001 | 1086% slower -FastRoute - last route (1000 routes) | 999 | 0.0001659009 | +0.0001538946 | 1282% slower -Pux PHP - unknown route (1000 routes) | 964 | 0.0013507533 | +0.0013387470 | 11150% slower -Pux PHP - last route (1000 routes) | 999 | 0.0014749475 | +0.0014629412 | 12185% slower -Symfony2 - unknown route (1000 routes) | 979 | 0.0038350259 | +0.0038230196 | 31842% slower -Symfony2 - last route (1000 routes) | 999 | 0.0040060059 | +0.0039939995 | 33266% slower - +Test Name | Results | Time(ms) | + Interval | Change +------------------ | ------- | ------- | ---------- | ----------- +**inhere/sroute(Router)** - unknown route(1000 routes) | 990 | 0.002031 | +0.000871 | 75% slower +inhere/sroute(SRouter) - unknown route(1000 routes) | 994 | 0.002895 | +0.001736 | 150% slower +**inhere/sroute(Router)** - last route(1000 routes) | 997 | 0.005300 | +0.004141 | 357% slower +inhere/sroute(SRouter) - last route(1000 routes) | 997 | 0.006467 | +0.005308 | 458% slower +symfony/routing(cached) - unknown route(1000 routes) | 976 | 0.012777 | +0.011618 | 1002% slower +symfony/routing(cached) - last route(1000 routes) | 996 | 0.013608 | +0.012449 | 1074% slower +mindplay/timber - last route(1000 routes) | 998 | 0.017211 | +0.016052 | 1385% slower +FastRoute - unknown route(1000 routes) | 991 | 0.039429 | +0.038270 | 3302% slower +FastRoute(cached) - unknown route(1000 routes) | 990 | 0.040800 | +0.039641 | 3420% slower +FastRoute(cached) - last route(1000 routes) | 999 | 0.045065 | +0.043906 | 3788% slower +FastRoute - last route(1000 routes) | 999 | 0.064694 | +0.063535 | 5481% slower +Pux PHP - unknown route(1000 routes) | 978 | 0.316016 | +0.314857 | 27163% slower +symfony/routing - unknown route(1000 routes) | 992 | 0.359482 | +0.358323 | 30912% slower +symfony/routing - last route(1000 routes) | 999 | 0.418813 | +0.417654 | 36031% slower +Pux PHP - last route(1000 routes) | 999 | 0.440489 | +0.439330 | 37901% slower +Macaw - unknown route(1000 routes) | 991 | 1.687441 | +1.686282 | 145475% slower +Macaw - last route(1000 routes) | 999 | 1.786542 | +1.785383 | 154024% slower ## First route matching @@ -91,133 +119,152 @@ This benchmark tests how quickly each router can match the first route. 1,000 ro This benchmark consists of 7 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. - Test Name | Results | Time | + Interval | Change --------- | ------- | ---- | ---------- | ------ -Pux PHP - first route(1000) | 993 | 0.0000105502 | +0.0000000000 | baseline -**ORouter** - first route(1000) | 984 | 0.0000118334 | +0.0000012832 | 12% slower -**SRouter** - first route(1000) | 982 | 0.0000118473 | +0.0000012971 | 12% slower -FastRoute(cached) - first route(1000) | 999 | 0.0000143361 | +0.0000037859 | 36% slower -FastRoute - first route(1000) | 999 | 0.0000143980 | +0.0000038477 | 36% slower -Symfony2 Dumped - first route | 993 | 0.0000350874 | +0.0000245372 | 233% slower -Symfony2 - first route | 999 | 0.0000630564 | +0.0000525061 | 498% slower +nikic/fast-route - first route(1000) | 998 | 0.002929 | +0.001571 | 116% slower +corneltek/pux(php) - first route(1000) | 996 | 0.002971 | +0.001613 | 119% slower +inhere/sroute(Router) - first(1000) | 979 | 0.006202 | +0.004844 | 357% slower +inhere/sroute(SRouter) - first(1000) | 999 | 0.006627 | +0.005269 | 388% slower +symfony/routing(cached) - first route(1000) | 985 | 0.006858 | +0.005501 | 405% slower +symfony/routing - first route(1000) | 995 | 0.023105 | +0.021747 | 1601% slower +nikic/fast-route(cached) - first route(1000) | 999 | 0.041133 | +0.039775 | 2929% slower +Macaw - first route (1000 routes) | 999 | 1.782017 | +1.780659 | 131128% slower + +## 使用说明 + +> 各个版本的方法名和参数都是一样的 + +首先, 需要导入类 + +```php +use Inhere\Route\Router; + +$router = new Router(); +``` -## 使用 +### 快速开始 -- `Inhere\Route\SRouter` 是静态类版本 -- `Inhere\Route\ORouter` 是对象版本 +创建一个简单的 `public/index.php` 文件: -两个类的方法名和参数都是一样的 +```php +use Inhere\Route\Router; + +// 需要先加载 autoload 文件 +require dirname(__DIR__) . '/vendor/autoload.php'; + +$router = new Router(); + +$router->get('/', function() { + echo 'hello'; +}); + +// 开始调度运行 +$router->dispatch(); +``` + +使用php启动一个测试server: `php -S 127.0.0.1:8080 -t ./public` -首先, 导入类 +好了,现在你可以访问 http://127.0.0.1:8080 可以看到输出 `hello` + +- 不使用 Composer + +如果是直接下载的包代码,可以加载 `test/boot.php` 文件,也可以加载到 `Inhere\Route` 命名空间. + +用如下的语句替换上面的 `autoload.php` 加载语句即可: ```php -use Inhere\Route\SRouter; +require dirname(__DIR__) . '/test/boot.php'; ``` ## 添加路由 ```php // 匹配 GET 请求. 处理器是个闭包 Closure -SRouter::get('/', function() { +$router->get('/', function() { echo 'hello'; }); // 匹配参数 'test/john' -SRouter::get('/test/{name}', function($params) { +$router->get('/test/{name}', function($params) { echo $params['name']; // 'john' }, [ - 'params' => [ - 'name' => '\w+', // 添加参数匹配限制。若不添加对应的限制,将会自动设置为匹配除了'/'外的任何字符 - ] + 'name' => '\w+', // 添加参数匹配限制。若不添加对应的限制,将会自动设置为匹配除了'/'外的任何字符 ]); // 可选参数支持。匹配 'hello' 'hello/john' -SRouter::get('/hello[/{name}]', function() { +$router->get('/hello[/{name}]', function() { echo $params['name'] ?? 'No input'; // 'john' }, [ - 'params' => [ - 'name' => '\w+', // 添加参数匹配限制 - ] + 'name' => '\w+', // 添加参数匹配限制 ]); // 匹配 POST 请求 -SRouter::post('/user/login', function() { +$router->post('/user/login', function() { var_dump($_POST); }); // 匹配 GET 或者 POST -SRouter::map(['get', 'post'], '/user/login', function() { +$router->map(['get', 'post'], '/user/login', function() { var_dump($_GET, $_POST); }); // 允许任何请求方法 -SRouter::any('/home', function() { +$router->any('/home', function() { echo 'hello, you request page is /home'; }); -SRouter::any('/404', function() { +$router->any('/404', function() { echo "Sorry,This page not found."; }); +``` + +### 使用路由组 +```php // 路由组 -SRouter::group('/user', function () { - SRouter::get('/', function () { +$router->group('/user', function ($router) { + $router->get('/', function () { echo 'hello. you access: /user/'; }); - SRouter::get('/index', function () { + $router->get('/index', function () { echo 'hello. you access: /user/index'; }); }); +``` +### 使用控制器 + +```php // 使用 控制器 -SRouter::get('/', app\controllers\HomeController::class); -SRouter::get('/index', 'app\controllers\HomeController@index'); +$router->get('/', App\Controllers\HomeController::class); +$router->get('/index', 'App\Controllers\HomeController@index'); ``` -> 如果配置了 `'ignoreLastSep' => true`, '/index' 等同于 '/index/' +### 备用路由处理 -### 添加路由方法 +可以注册一个备用路由处理。当没匹配到时,就会使用它 ```php -public function map(string|array $methods, string $route, mixed $handler, array $opts = []) +$router->any('*', 'fallback_handler'); ``` -添加路由方法 +> 如果配置了 `'ignoreLastSlash' => true`, '/index' 等同于 '/index/' -> 其他的添加路由方法底层都是调用的 `map()` 方法,除了没有第一个参数外,其他参数都是一样的 +#### 注意 -- `$methods` string|array 请求的METHOD. e.g `GET` `['GET', 'POST]` -- `$route` string 定义的路由字符串 e.g `/user/login` `/article/{id}` -- `$handler` string|object 对应路由的处理者 -- `$opts` array 选项设置,可以添加自定义的数据。匹配成功会将选项数据返回(e.g middleware, domains),自己再做进一步验证等。下面是已使用的选项 - - `params` 添加路由时设置的参数匹配信息, 若有的话 e.g `'name' => '\w+'` - - `defaults` 有可选参数时,可以设置默认值 +可选参数 - 只能是在路由path的最后 -一个较为完整的示例: - -> 提示: 若不在选项中设置参数匹配,那么参数将会匹配除了 '/' 之外的任何字符 +正确的: ```php -$router->map(['get', 'post'], '/im/{name}[/{age}]', function(array $params) { - var_dump($params); -}, [ - // 设置参数匹配 - 'params' => [ - 'name' => '\w+', - 'age' => '\d+', - ], - 'defaults' => [ - 'age' => 20, // 给可选参数 age 添加一个默认值 - ] - - // 可添加更多自定义设置 - 'middleware' => ['AuthCheck'], - 'domains' => ['localhost'], - ... ... -]); +/hello[/{name}] // match: /hello/tom /hello +/my[/{name}[/{age}]] // match: /my/tom/78 /my/tom ``` -Now, 访问 `/im/john/18` 或者 `/im/john` 查看效果 +错误的: + +```php +/my[/{name}]/{age} +``` ### 自动匹配路由 @@ -239,43 +286,19 @@ Now, 访问 `/im/john/18` 或者 `/im/john` 查看效果 - 大于等于两节的默认先认为最后一节是控制器类名,进行查找 - 若失败,再尝试将倒数第二节认为是控制器名,最后一节是action名 -### 匹配所有 - -配置 `intercept` 可用于拦截所有请求。 (例如网站维护时) - -可允许配置 `intercept` 的值为 - -- 路由path - -```php - 'intercept' => '/about', // a route path -``` - -将会直接执行此路由后停止执行 - -- 回调 - -```php - 'intercept' => function () { - echo '系统维护中 :)'; - }, -``` - -将会直接执行此回调后停止执行 - ## 设置路由配置 ```php // set config -SRouter::setConfig([ - 'ignoreLastSep' => true, +$router->config([ + 'ignoreLastSlash' => true, 'autoRoute' => 1, 'controllerNamespace' => 'app\\controllers', 'controllerSuffix' => 'Controller', ]); ``` -> NOTICE: 必须在添加路由之前调用 `SRouter::setConfig()` +> NOTICE: 必须在添加路由之前调用 `$router->config()` ## 路由匹配 @@ -295,66 +318,31 @@ array public function match($path, $method) $path = parse_url(http://github.com/$_SERVER['REQUEST_URI'],%20PHP_URL_PATH); $method = $_SERVER['REQUEST_METHOD']; -$route = SRouter::match($path, $method); +$routeInfo = $router->match($path, $method); ``` -将会返回如下格式的信息. 可以根据此信息进行 判断匹配是否成功 -> 路由调度 +根据返回的路由信息,我们就可以自由的决定如何调用对应的处理。 -```php -[ - // 路由匹配结果状态. - // 可能为: RouterInterface::FOUND, RouterInterface::NOT_FOUND, RouterInterface::METHOD_NOT_ALLOWED - INT, - - // 格式化后的 $path 的返回(会去除多余的空白,'/'等字符) - 'URI PATH', - - // 路由信息。 匹配失败时(RouterInterface::NOT_FOUND)为 null - [ - // (可能存在)配置的请求 METHOD。 自动匹配时无此key - 'method' => 'GET', - - // 此路由的 handler callback - 'handler' => 'handler', - - // (可能存在)此路由的 原始path。 仅动态路由有 - 'original' => '/hi/{name}', - - // (可能存在) 有参数匹配的路由匹配成功后,会将参数值放入这里 - 'matches' => ['name' => value ], - - // 此路由的自定义选项信息. 可能为空 - // - params - 来自添加路由时设置的参数匹配信息, 若有的话 - // - defaults - 有可选参数时,可以设置默认值 - // 还可以自定义追加此路由的选项:如下经供参考 - // - domains 允许访问路由的域名 - // - schemas 允许访问路由的schema - // - enter 进入路由的事件回调 - // ... ... - 'option' => [ - 'params' => [], - 'defaults' => [], - - // 'domains' => null, - // 'schemas' => null, // ['http','https'], - // route event. custom design ... - // 'enter' => null, - // 'leave' => null, - ], - - ], -] -``` +> 关于返回的数据结构,可以查看 [关键方法参考](docs/classes-api.md) ## 路由调度 -已内置了一个路由调度器 `Inhere\Route\Dispatcher` +如果你不想自己实现路由调度,可以使用内置的路由调度器 `Inhere\Route\Dispatcher\Dispatcher` ```php -use Inhere\Route\Dispatcher; +use Inhere\Route\Dispatcher\Dispatcher; $dispatcher = new Dispatcher([ + // default action method name + 'defaultAction' => 'index', + + 'actionPrefix' => '', + + 'actionSuffix' => 'Action', + 'dynamicAction' => true, + // @see Router::$globalParams['act'] + 'dynamicActionVar' => 'act', ]); ``` @@ -379,26 +367,33 @@ $dispatcher->on('notFound', function ($uri) { 通过`@`符号连接控制器类和方法名可以指定执行方法。 ```php -SRouter::get('/', app\controllers\HomeController::class); +$router->get('/', App\Controllers\HomeController::class); -SRouter::get('/index', 'app\controllers\HomeController@index'); -SRouter::get('/about', 'app\controllers\HomeController@about'); +$router->get('/index', 'App\Controllers\HomeController@index'); +$router->get('/about', 'App\Controllers\HomeController@about'); ``` > NOTICE: 若第二个参数仅仅是个 类,将会尝试执行通过 `defaultAction` 配置的默认方法 ### 动态匹配控制器方法 -动态匹配控制器方法, 需配置 `'dynamicAction' => true` +动态匹配控制器方法, 需配置 + +```php +'dynamicAction' => true, // 启用 +// action 方法名匹配参数名称,符合条件的才会当做action名称 +// @see Router::$globalParams['act'] 匹配 '[a-zA-Z][\w-]+' +'dynamicActionVar' => 'act', +``` -> NOTICE: 使用动态匹配控制器方法, 应当使用 `any()` 添加路由. 即此时无法限定请求方法 `REQUEST_METHOD` +> NOTICE: 使用动态匹配控制器方法, 应当使用 `any()` 添加路由. 即此时不能限定请求方法 `REQUEST_METHOD` ```php -// 访问 '/home/test' 将会执行 'app\controllers\HomeController::test()' -SRouter::any('/home/{any}', app\controllers\HomeController::class); +// 访问 '/home/test' 将会执行 'App\Controllers\HomeController::test()' +$router->any('/home/{act}', App\Controllers\HomeController::class); // 可匹配 '/home', '/home/test' 等 -SRouter::any('/home[/{name}]', app\controllers\HomeController::class); +$router->any('/home[/{act}]', App\Controllers\HomeController::class); ``` > NOTICE: 上面两个的区别是 第一个无法匹配 `/home` @@ -413,36 +408,31 @@ SRouter::any('/home[/{name}]', app\controllers\HomeController::class); 示例: ```php -// 访问 '/user', 将会调用 app\controllers\UserController::run('') -SRouter::get('/user', 'app\controllers\UserController'); +// 访问 '/user', 将会调用 App\Controllers\UserController::run('') +$router->get('/user', 'App\Controllers\UserController'); -// 访问 '/user/profile', 将会调用 app\controllers\UserController::run('profile') -SRouter::get('/user/profile', 'app\controllers\UserController'); +// 访问 '/user/profile', 将会调用 App\Controllers\UserController::run('profile') +$router->get('/user/profile', 'App\Controllers\UserController'); // 同时配置 'actionExecutor' => 'run' 和 'dynamicAction' => true, -// 访问 '/user', 将会调用 app\controllers\UserController::run('') -// 访问 '/user/profile', 将会调用 app\controllers\UserController::run('profile') -SRouter::any('/user[/{name}]', 'app\controllers\UserController'); +// 访问 '/user', 将会调用 App\Controllers\UserController::run('') +// 访问 '/user/profile', 将会调用 App\Controllers\UserController::run('profile') +$router->any('/user[/{name}]', 'App\Controllers\UserController'); ``` ## 开始路由匹配和调度 ```php -SRouter::dispatch($dispatcher); -// $router->dispatch($dispatcher); +$router->dispatch($dispatcher); ``` ## 运行示例 -示例代码在 `examples` 下。 - -- 静态版本 - -你可以通过 `php -S 127.0.0.1:5670 examples/static.php` 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5670 +示例代码在 `example` 下。 - 对象版本 -你可以通过 `php -S 127.0.0.1:5670 examples/object.php` 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5671 +你可以通过 `php -S 127.0.0.1:5670 example/object.php` 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5671 ## 测试 @@ -450,6 +440,12 @@ SRouter::dispatch($dispatcher); phpunit ``` +- simple benchmark + +```bash +php example/benchmark.php +``` + ## License MIT @@ -460,14 +456,7 @@ MIT 功能丰富的命令行应用,命令行工具库 -### `inhere/redis` [github](https://github.com/inhere/php-redis) [git@osc](https://git.oschina.net/inhere/php-redis) - -简单的redis操作客户端包装库 - ### `inhere/php-validate` [github](https://github.com/inhere/php-validate) [git@osc](https://git.oschina.net/inhere/php-validate) 一个简洁小巧且功能完善的php验证库。仅有几个文件,无依赖。 -### `inhere/http` [github](https://github.com/inhere/php-http) [git@osc](https://git.oschina.net/inhere/php-http) - -http 工具库(`request` 请求 `response` 响应 `curl` curl请求库,有简洁、完整和并发请求三个版本的类) diff --git a/README_en.md b/README_en.md index 108ef90..9a3abeb 100644 --- a/README_en.md +++ b/README_en.md @@ -1,29 +1,33 @@ -# php simple router +# SRoute -[![License](https://img.shields.io/packagist/l/inhere/console.svg?style=flat-square)](LICENSE.md) -[![Php Version](https://img.shields.io/badge/php-%3E=5.6-brightgreen.svg?maxAge=2592000)](https://packagist.org/packages/inhere/sroute) +[![License](https://img.shields.io/packagist/l/inhere/sroute.svg?style=flat-square)](LICENSE.md) +[![PHP Version](https://img.shields.io/packagist/php-v/inhere/sroute.svg?colorB=green)](https://packagist.org/packages/inhere/sroute) [![Latest Stable Version](http://img.shields.io/packagist/v/inhere/sroute.svg)](https://packagist.org/packages/inhere/sroute) +[![Unit-tests](https://github.com/inhere/php-sroute/actions/workflows/php.yml/badge.svg)](https://github.com/inhere/php-sroute/actions) +[![Coverage Status](https://coveralls.io/repos/github/inhere/php-sroute/badge.svg?branch=master)](https://coveralls.io/github/inhere/php-sroute?branch=master) -a very lightweight and fast speed router. +A very lightweight and fasted request router. lightweight web framework. - Lightweight and fast speed, the search speed is not affected by the routing number - supported request methods: `GET` `POST` `PUT` `DELETE` `HEAD` `OPTIONS` - support event: `found` `notFound`. Some things you can do when the triggering event (such as logging, etc.) -- support manual dispatch a URI route by `SRouter::dispatch($path, $method)`, you can dispatch a URI in your logic. +- support manual dispatch a URI route by `$router->dispatch($path, $method)`, you can dispatch a URI in your logic. - Support automatic matching routing like yii framework, by config `autoRoute`. -- more interesting config, please see `SRouter::setConfig` +- more interesting config, please see `$router->config` - You can also do not have to configure anything, it can also work very well -**[中文README](./README_zh.md)更详细** +## [中文README](./README.md)更详细 -## project +## Project -- **github** https://github.com/inhere/php-srouter.git -- **git@osc** https://git.oschina.net/inhere/php-srouter.git +- **github** https://github.com/inhere/php-sroute.git +- **git@osc** https://git.oschina.net/inhere/php-sroute.git -## install +## Install -- by composer +> required PHP 8.0+ + +- by `composer.json` ```json { @@ -33,14 +37,17 @@ a very lightweight and fast speed router. } ``` -- fetch code +- by `composer require` ```bash -git clone https://github.com/inhere/php-srouter.git // github -git clone https://git.oschina.net/inhere/php-srouter.git // git@osc +composer require inhere/sroute ``` -## benchmark +## Benchmark + +> Test time: `2018.11.19` + +- test codes: https://github.com/ulue/php-router-benchmark ## Worst-case matching @@ -48,23 +55,25 @@ This benchmark matches the last route and unknown route. It generates a randomly This benchmark consists of 14 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. -Test Name | Results | Time | + Interval | Change ---------- | ------- | ---- | ---------- | ------ -ORouter - unknown route (1000 routes) | 988 | 0.0000120063 | +0.0000000000 | baseline -ORouter - last route (1000 routes) | 988 | 0.0000122867 | +0.0000002804 | 2% slower -SRouter - unknown route (1000 routes) | 983 | 0.0000123633 | +0.0000003570 | 3% slower -SRouter - last route (1000 routes) | 998 | 0.0000142205 | +0.0000022142 | 18% slower -Symfony2 Dumped - last route (1000 routes) | 990 | 0.0000468579 | +0.0000348516 | 290% slower -Symfony2 Dumped - unknown route (1000 routes) | 995 | 0.0000490268 | +0.0000370205 | 308% slower -FastRoute - unknown route (1000 routes) | 968 | 0.0001358227 | +0.0001238164 | 1031% slower -FastRoute(cached) - last route (1000 routes) | 999 | 0.0001397746 | +0.0001277683 | 1064% slower -FastRoute(cached) - unknown route (1000 routes) | 960 | 0.0001424064 | +0.0001304001 | 1086% slower -FastRoute - last route (1000 routes) | 999 | 0.0001659009 | +0.0001538946 | 1282% slower -Pux PHP - unknown route (1000 routes) | 964 | 0.0013507533 | +0.0013387470 | 11150% slower -Pux PHP - last route (1000 routes) | 999 | 0.0014749475 | +0.0014629412 | 12185% slower -Symfony2 - unknown route (1000 routes) | 979 | 0.0038350259 | +0.0038230196 | 31842% slower -Symfony2 - last route (1000 routes) | 999 | 0.0040060059 | +0.0039939995 | 33266% slower - +Test Name | Results | Time(ms) | + Interval | Change +------------------ | ------- | ------- | ---------- | ----------- +**inhere/sroute(Router)** - unknown route(1000 routes) | 990 | 0.002031 | +0.000871 | 75% slower +inhere/sroute(SRouter) - unknown route(1000 routes) | 994 | 0.002895 | +0.001736 | 150% slower +**inhere/sroute(Router)** - last route(1000 routes) | 997 | 0.005300 | +0.004141 | 357% slower +inhere/sroute(SRouter) - last route(1000 routes) | 997 | 0.006467 | +0.005308 | 458% slower +symfony/routing(cached) - unknown route(1000 routes) | 976 | 0.012777 | +0.011618 | 1002% slower +symfony/routing(cached) - last route(1000 routes) | 996 | 0.013608 | +0.012449 | 1074% slower +mindplay/timber - last route(1000 routes) | 998 | 0.017211 | +0.016052 | 1385% slower +FastRoute - unknown route(1000 routes) | 991 | 0.039429 | +0.038270 | 3302% slower +FastRoute(cached) - unknown route(1000 routes) | 990 | 0.040800 | +0.039641 | 3420% slower +FastRoute(cached) - last route(1000 routes) | 999 | 0.045065 | +0.043906 | 3788% slower +FastRoute - last route(1000 routes) | 999 | 0.064694 | +0.063535 | 5481% slower +Pux PHP - unknown route(1000 routes) | 978 | 0.316016 | +0.314857 | 27163% slower +symfony/routing - unknown route(1000 routes) | 992 | 0.359482 | +0.358323 | 30912% slower +symfony/routing - last route(1000 routes) | 999 | 0.418813 | +0.417654 | 36031% slower +Pux PHP - last route(1000 routes) | 999 | 0.440489 | +0.439330 | 37901% slower +Macaw - unknown route(1000 routes) | 991 | 1.687441 | +1.686282 | 145475% slower +Macaw - last route(1000 routes) | 999 | 1.786542 | +1.785383 | 154024% slower ## First route matching @@ -72,72 +81,74 @@ This benchmark tests how quickly each router can match the first route. 1,000 ro This benchmark consists of 7 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. - Test Name | Results | Time | + Interval | Change --------- | ------- | ---- | ---------- | ------ -Pux PHP - first route(1000) | 993 | 0.0000105502 | +0.0000000000 | baseline -ORouter - first route(1000) | 984 | 0.0000118334 | +0.0000012832 | 12% slower -SRouter - first route(1000) | 982 | 0.0000118473 | +0.0000012971 | 12% slower -FastRoute(cached) - first route(1000) | 999 | 0.0000143361 | +0.0000037859 | 36% slower -FastRoute - first route(1000) | 999 | 0.0000143980 | +0.0000038477 | 36% slower -Symfony2 Dumped - first route | 993 | 0.0000350874 | +0.0000245372 | 233% slower -Symfony2 - first route | 999 | 0.0000630564 | +0.0000525061 | 498% slower +nikic/fast-route - first route(1000) | 998 | 0.002929 | +0.001571 | 116% slower +corneltek/pux(php) - first route(1000) | 996 | 0.002971 | +0.001613 | 119% slower +inhere/sroute(Router) - first(1000) | 979 | 0.006202 | +0.004844 | 357% slower +inhere/sroute(SRouter) - first(1000) | 999 | 0.006627 | +0.005269 | 388% slower +symfony/routing(cached) - first route(1000) | 985 | 0.006858 | +0.005501 | 405% slower +symfony/routing - first route(1000) | 995 | 0.023105 | +0.021747 | 1601% slower +nikic/fast-route(cached) - first route(1000) | 999 | 0.041133 | +0.039775 | 2929% slower +Macaw - first route (1000 routes) | 999 | 1.782017 | +1.780659 | 131128% slower -## usage +## Usage first, import the class ```php -use Inhere\Route\SRouter; +use Inhere\Route\Router; + +$router = new Router(); ``` ## add some routes ```php // match GET. handler use Closure -SRouter::get('/', function() { +$router->get('/', function() { echo 'hello'; }); // access 'test/john' -SRouter::get('/test/{name}', function($params) { +$router->get('/test/{name}', function($params) { echo $params['name']; // 'john' -}); +}, ['name' => '\w+']); // match POST -SRouter::post('/user/login', function() { +$router->post('/user/login', function() { var_dump($_POST); }); // match GET or POST -SRouter::map(['get', 'post'], '/user/login', function() { +$router->map(['get', 'post'], '/user/login', function() { var_dump($_GET, $_POST); }); // match any method -SRouter::any('/home', function() { +$router->any('/home', function() { echo 'hello, you request page is /home'; }); // route group -SRouter::group('/user', function () { - SRouter::get('/', function () { +$router->group('/user', function () { + $router->get('/', function () { echo 'hello. you access: /user/'; }); - SRouter::get('/index', function () { + $router->get('/index', function () { echo 'hello. you access: /user/index'; }); }); ``` -### use controller action +### Use controller action ```php -// if you config 'ignoreLastSep' => true, '/index' is equals to '/index/' -SRouter::get('/index', 'app\controllers\Home@index'); +// if you config 'ignoreLastSlash' => true, '/index' is equals to '/index/' +$router->get('/index', 'app\controllers\Home@index'); ``` -### dynamic action +### Dynamic action match dynamic action, config `'dynamicAction' => true` @@ -145,26 +156,26 @@ match dynamic action, config `'dynamicAction' => true` ```php // access '/home/test' will call 'app\controllers\Home::test()' -SRouter::any('/home/{name}', app\controllers\Home::class); +$router->any('/home/{name}', app\controllers\Home::class); // can match '/home', '/home/test' -SRouter::any('/home[/{name}]', app\controllers\Home::class); +$router->any('/home[/{name}]', app\controllers\Home::class); ``` -### use action executor +### Use action executor if you config `'actionExecutor' => 'run'` ```php // access '/user', will call app\controllers\User::run('') // access '/user/profile', will call app\controllers\User::run('profile') -SRouter::get('/user', 'app\controllers\User'); -SRouter::get('/user/profile', 'app\controllers\User'); +$router->get('/user', 'app\controllers\User'); +$router->get('/user/profile', 'app\controllers\User'); // if config 'actionExecutor' => 'run' and 'dynamicAction' => true, // access '/user', will call app\controllers\User::run('') // access '/user/profile', will call app\controllers\User::run('profile') -SRouter::get('/user[/{name}]', 'app\controllers\User'); +$router->get('/user[/{name}]', 'app\controllers\User'); ``` @@ -174,50 +185,21 @@ Support automatic matching like yii routed to the controller, need config `autoR ```php 'autoRoute' => 1, // enanbled - 'controllerNamespace' => 'examples\\controllers', // The controller class in the namespace + 'controllerNamespace' => 'Example\\controllers', // The controller class in the namespace 'controllerSuffix' => 'Controller', // The controller class suffix ``` -### intercept all requests - -you can config 'intercept', All requests for intercepting。 (eg. web site maintenance) - -you can config 'intercept' as - -- route path - -```php - 'intercept' => '/about', // a route path -``` - -Will be executed directly the route. - -- callback - -```php - 'intercept' => function () { - echo 'System Maintaining ... ...'; - }, -``` - -Will directly execute the callback - ### setting config ```php // set config -SRouter::setConfig([ - 'ignoreLastSep' => true, - -// 'intercept' => '/', // a route path -// 'intercept' => function () { -// echo 'System Maintaining ... ...'; -// }, +$router->config([ + 'ignoreLastSlash' => true, // enable autoRoute, work like yii framework // you can access '/demo' '/admin/user/info', Don't need to configure any route 'autoRoute' => 1, - 'controllerNamespace' => 'examples\\controllers', + 'controllerNamespace' => 'Example\\controllers', 'controllerSuffix' => 'Controller', ]); ``` @@ -228,12 +210,7 @@ SRouter::setConfig([ // there are default config. [ // ignore last '/' char. If is True, will clear last '/', so '/home' equals to '/home/' - 'ignoreLastSep' => false, - - // intercept all request. - // 1. If is a valid URI path, will intercept all request uri to the path. - // 2. If is a closure, will intercept all request then call it - 'intercept' => '', // eg: '/site/maintenance' or `function () { echo 'System Maintaining ... ...'; }` + 'ignoreLastSlash' => false, // auto route match @like yii framework // If is True, will auto find the handler controller file. @@ -245,9 +222,9 @@ SRouter::setConfig([ ] ``` -> NOTICE: you must call `SRouter::setConfig()` on before the add route. +> NOTICE: you must call `$router->config()` on before the add route. -## route dispatcher +## Route dispatcher ```php use Inhere\Route\Dispatcher; @@ -257,7 +234,7 @@ $dispatcher = new Dispatcher([ ]); ``` -## events +### Events ```php $dispatcher->on(Dispatcher::ON_FOUND, function ($uri, $route) use ($app) { @@ -272,17 +249,17 @@ $dispatcher->on('notFound', function ($uri) { }); ``` -## begin dispatch +### begin dispatch ```php -SRouter::dispatch($dispatcher); +$router->dispatch($dispatcher); ``` -## examples +## example -please the `examples` folder's codes. +please the `example` folder's codes. -you can run a test server by `php -S 127.0.0.1:5670 -t examples/static`, now please access http://127.0.0.1:5670 +you can run a test server by `php -S 127.0.0.1:5670 -t example/static`, now please access http://127.0.0.1:5670 ## License diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c741881 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file diff --git a/composer.json b/composer.json index 847f1ea..0aa88f2 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,16 @@ { "name": "inhere/sroute", "type": "library", - "description": "a very lightweight single file of the router.", - "keywords": ["library","route","router","php-router"], - "homepage": "https://github.com/inhere/php-srouter", + "description": "a very lightweight and fasted request router. lightweight web framework", + "keywords": [ + "library", + "route", + "router", + "http-router", + "php-router", + "web-framework" + ], + "homepage": "https://github.com/inhere/php-sroute", "license": "MIT", "authors": [ { @@ -13,14 +20,19 @@ } ], "require": { - "php": ">=5.6.0" + "php": ">=8.1" }, "autoload": { "psr-4": { - "Inhere\\Route\\" : "src/" - } + "Inhere\\Route\\": "src/" + }, + "files": [ + "src/Helper/functions.php" + ] }, - "suggest": { - "inhere/simple-print-tool": "Very lightweight data printing tools" + "autoload-dev": { + "psr-4": { + "Inhere\\RouteTest\\": "test/" + } } } diff --git a/examples/config/.htaccess b/config/.htaccess similarity index 86% rename from examples/config/.htaccess rename to config/.htaccess index 7bfd57e..741a81f 100644 --- a/examples/config/.htaccess +++ b/config/.htaccess @@ -1,5 +1,5 @@ RewriteEngine On -RewriteBase /macaw +RewriteBase /api RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d diff --git a/examples/config/nginx.conf b/config/nginx.conf similarity index 97% rename from examples/config/nginx.conf rename to config/nginx.conf index ed9fcd2..065a2a4 100644 --- a/examples/config/nginx.conf +++ b/config/nginx.conf @@ -2,4 +2,4 @@ autoindex off; location / { try_files $uri $uri/ /index.php?/$uri; -} \ No newline at end of file +} diff --git a/docs/TODO.md b/docs/TODO.md new file mode 100644 index 0000000..ac9ee61 --- /dev/null +++ b/docs/TODO.md @@ -0,0 +1,62 @@ +# todo + +- 调整参数路由的解析,由现在的正则分析 -> 使用字符串分析 +- 增加属性 `$routesData` 存储路由中不用于匹配的数据,减轻现有路由数据的复杂度 + - 现有的变量 `$routesData` 改成 `$routesInfo` + + +- 解析参数,替换为对应的 正则 + +```php +// method 1 - it is faster +if (\preg_match_all('#\{([a-zA-Z_][\w-]*)\}#', $route, $m)) { + /** @var array[] $m */ + $pairs = []; + + foreach ($m[1] as $name) { + $key = '{' . $name . '}'; + $regex = $params[$name] ?? self::DEFAULT_REGEX; + + // Name the match (?P[^/]+) + $pairs[$key] = '(?P<' . $name . '>' . $regex . ')'; + // $pairs[$key] = '(' . $regex . ')'; + } + + $route = \strtr($route, $pairs); +} + +// method 2 +$route = (string)\preg_replace_callback('#\{[a-zA-Z_][\w-]*\}#', function (array $m) use($params) { + $name = \trim($m[0], '{}'); + $regex = $params[$name] ?? self::DEFAULT_REGEX; + $pair = '(?P<' . $name . '>' . $regex . ')'; + // $pair = '(' . $regex . ')'; + + return $pair; +}, $route); +``` + +- matchDynamicRoute() + +```php + protected function matchDynamicRoute(string $path, string $method): array + { + // method 1 + $first = \strstr(\ltrim($path, '/'), '/', true); + $fKey = $first ? $method . ' ' . $first : ''; + + // method 2 + $first = $fKey = ''; + if (1 === \preg_match('#^/([\w-]+)/#', $path, $m)) { + $first = $m[1]; + $fKey = $method . ' ' . $first; + } + + // method 3 + $fKey = $first = ''; + if ($pos = \strpos($path, '/', 1)) { + $first = \substr($path, 1, $pos - 1); + $fKey = $method . ' ' . $first; + } +``` + diff --git a/docs/benchmark-170706.md b/docs/benchmark-170706.md new file mode 100644 index 0000000..2ae89cd --- /dev/null +++ b/docs/benchmark-170706.md @@ -0,0 +1,51 @@ +# benchmark + +压测时间: 2017-07-16 +改进路由收集和匹配逻辑后的压测结果 + +自动生成了1000条路由,每条有9个参数位,分别测试1000次的 + +- 第一条路由匹配 +- 最后一条路由匹配 +- 不会匹配到的路由 + +## Worst-case matching + +This benchmark matches the last route and unknown route. It generates a randomly prefixed and suffixed route in an attempt to thwart any optimization. 1,000 routes each with 9 arguments. + +This benchmark consists of 14 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. + +Test Name | Results | Time | + Interval | Change +--------- | ------- | ---- | ---------- | ------ +Router - unknown route (1000 routes) | 988 | 0.0000120063 | +0.0000000000 | baseline +Router - last route (1000 routes) | 988 | 0.0000122867 | +0.0000002804 | 2% slower +SRouter - unknown route (1000 routes) | 983 | 0.0000123633 | +0.0000003570 | 3% slower +SRouter - last route (1000 routes) | 998 | 0.0000142205 | +0.0000022142 | 18% slower +Symfony Dumped - last route (1000 routes) | 990 | 0.0000468579 | +0.0000348516 | 290% slower +Symfony Dumped - unknown route (1000 routes) | 995 | 0.0000490268 | +0.0000370205 | 308% slower +FastRoute - unknown route (1000 routes) | 968 | 0.0001358227 | +0.0001238164 | 1031% slower +FastRoute(cached) - last route (1000 routes) | 999 | 0.0001397746 | +0.0001277683 | 1064% slower +FastRoute(cached) - unknown route (1000 routes) | 960 | 0.0001424064 | +0.0001304001 | 1086% slower +FastRoute - last route (1000 routes) | 999 | 0.0001659009 | +0.0001538946 | 1282% slower +Pux PHP - unknown route (1000 routes) | 964 | 0.0013507533 | +0.0013387470 | 11150% slower +Pux PHP - last route (1000 routes) | 999 | 0.0014749475 | +0.0014629412 | 12185% slower +Symfony - unknown route (1000 routes) | 979 | 0.0038350259 | +0.0038230196 | 31842% slower +Symfony - last route (1000 routes) | 999 | 0.0040060059 | +0.0039939995 | 33266% slower + + +## First route matching + +This benchmark tests how quickly each router can match the first route. 1,000 routes each with 9 arguments. + +This benchmark consists of 7 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. + + +Test Name | Results | Time | + Interval | Change +--------- | ------- | ---- | ---------- | ------ +Pux PHP - first route(1000) | 993 | 0.0000105502 | +0.0000000000 | baseline +Router - first route(1000) | 984 | 0.0000118334 | +0.0000012832 | 12% slower +SRouter - first route(1000) | 982 | 0.0000118473 | +0.0000012971 | 12% slower +FastRoute(cached) - first route(1000) | 999 | 0.0000143361 | +0.0000037859 | 36% slower +FastRoute - first route(1000) | 999 | 0.0000143980 | +0.0000038477 | 36% slower +Symfony Dumped - first route | 993 | 0.0000350874 | +0.0000245372 | 233% slower +Symfony - first route | 999 | 0.0000630564 | +0.0000525061 | 498% slower diff --git a/docs/benchmark-old.md b/docs/benchmark-old.md index 8390dc0..b9c9fb6 100644 --- a/docs/benchmark-old.md +++ b/docs/benchmark-old.md @@ -10,14 +10,14 @@ This benchmark consists of 12 tests. Each test is executed 1,000 times, the resu Test Name | Results | Time | + Interval | Change --------- | ------- | ---- | ---------- | ------ -Symfony2 Dumped - last route (1000 routes) | 994 | 0.0000389371 | +0.0000000000 | baseline -Symfony2 Dumped - unknown route (1000 routes) | 985 | 0.0000407054 | +0.0000017684 | 5% slower +Symfony Dumped - last route (1000 routes) | 994 | 0.0000389371 | +0.0000000000 | baseline +Symfony Dumped - unknown route (1000 routes) | 985 | 0.0000407054 | +0.0000017684 | 5% slower FastRoute - unknown route (1000 routes) | 961 | 0.0001322015 | +0.0000932644 | 240% slower FastRoute - last route (1000 routes) | 999 | 0.0001686443 | +0.0001297072 | 333% slower Pux PHP - unknown route (1000 routes) | 971 | 0.0012761564 | +0.0012372194 | 3177% slower Pux PHP - last route (1000 routes) | 999 | 0.0014034189 | +0.0013644818 | 3504% slower -Symfony2 - unknown route (1000 routes) | 981 | 0.0036823390 | +0.0036434019 | 9357% slower -Symfony2 - last route (1000 routes) | 999 | 0.0037877016 | +0.0037487645 | 9628% slower +Symfony - unknown route (1000 routes) | 981 | 0.0036823390 | +0.0036434019 | 9357% slower +Symfony - last route (1000 routes) | 999 | 0.0037877016 | +0.0037487645 | 9628% slower SRouter - last route (1000 routes) | 999 | 0.0039463984 | +0.0039074613 | 10035% slower SRoute - last route (1000 routes) | 999 | 0.0039622600 | +0.0039233229 | 10076% slower SRoute - unknown route (1000 routes) | 999 | 0.0078473841 | +0.0078084470 | 20054% slower @@ -34,7 +34,7 @@ Test Name | Results | Time | + Interval | Change --------- | ------- | ---- | ---------- | ------ Pux PHP - first route | 991 | 0.0000130298 | +0.0000000000 | baseline FastRoute - first route | 999 | 0.0000136595 | +0.0000006298 | 5% slower -Symfony2 Dumped - first route | 986 | 0.0000327519 | +0.0000197221 | 151% slower -Symfony2 - first route | 998 | 0.0000625880 | +0.0000495582 | 380% slower +Symfony Dumped - first route | 986 | 0.0000327519 | +0.0000197221 | 151% slower +Symfony - first route | 998 | 0.0000625880 | +0.0000495582 | 380% slower SRouter - first route | 976 | 0.0037495811 | +0.0037365514 | 28677% slower SRoute - first route | 999 | 0.0038005320 | +0.0037875022 | 29068% slower diff --git a/docs/benchmark.md b/docs/benchmark.md index 33526f6..680894a 100644 --- a/docs/benchmark.md +++ b/docs/benchmark.md @@ -1,51 +1,57 @@ -# benchmark -压测时间: 2017-07-16 -改进路由收集和匹配逻辑后的压测结果 +# 压测 自动生成了1000条路由,每条有9个参数位,分别测试1000次的 - 第一条路由匹配 - 最后一条路由匹配 -- 不会匹配到的路由 +- 不存在的路由匹配 -## Worst-case matching +详细的测试代码请看仓库 https://github.com/ulue/php-router-benchmark + +- 压测日期 **2017.12.3** +- An example route: `/9b37eef21e/{arg1}/{arg2}/{arg3}/{arg4}/{arg5}/{arg6}/{arg7}/{arg8}/{arg9}/bda37e9f9b` -This benchmark matches the last route and unknown route. It generates a randomly prefixed and suffixed route in an attempt to thwart any optimization. 1,000 routes each with 9 arguments. +压测结果 -This benchmark consists of 14 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. +## Worst-case matching -Test Name | Results | Time | + Interval | Change +Test Name | Results | Time(ms) | + Interval | Change --------- | ------- | ---- | ---------- | ------ -ORouter - unknown route (1000 routes) | 988 | 0.0000120063 | +0.0000000000 | baseline -ORouter - last route (1000 routes) | 988 | 0.0000122867 | +0.0000002804 | 2% slower -SRouter - unknown route (1000 routes) | 983 | 0.0000123633 | +0.0000003570 | 3% slower -SRouter - last route (1000 routes) | 998 | 0.0000142205 | +0.0000022142 | 18% slower -Symfony2 Dumped - last route (1000 routes) | 990 | 0.0000468579 | +0.0000348516 | 290% slower -Symfony2 Dumped - unknown route (1000 routes) | 995 | 0.0000490268 | +0.0000370205 | 308% slower -FastRoute - unknown route (1000 routes) | 968 | 0.0001358227 | +0.0001238164 | 1031% slower -FastRoute(cached) - last route (1000 routes) | 999 | 0.0001397746 | +0.0001277683 | 1064% slower -FastRoute(cached) - unknown route (1000 routes) | 960 | 0.0001424064 | +0.0001304001 | 1086% slower -FastRoute - last route (1000 routes) | 999 | 0.0001659009 | +0.0001538946 | 1282% slower -Pux PHP - unknown route (1000 routes) | 964 | 0.0013507533 | +0.0013387470 | 11150% slower -Pux PHP - last route (1000 routes) | 999 | 0.0014749475 | +0.0014629412 | 12185% slower -Symfony2 - unknown route (1000 routes) | 979 | 0.0038350259 | +0.0038230196 | 31842% slower -Symfony2 - last route (1000 routes) | 999 | 0.0040060059 | +0.0039939995 | 33266% slower +inhere/sroute(Router) - unknown route (1000 routes) | 987 | 0.010222 | +0.000000 | baseline +inhere/sroute(SRouter) - unknown route (1000 routes) | 984 | 0.012239 | +0.002017 | 20% slower +inhere/sroute(SRouter) - last route (1000 routes) | 999 | 0.024386 | +0.014820 | 155% slower +inhere/sroute(Router) - last route (1000 routes) | 975 | 0.024554 | +0.014989 | 157% slower +Symfony Cached - last route (1000 routes) | 997 | 0.029091 | +0.019525 | 204% slower +Symfony Cached - unknown route (1000 routes) | 985 | 0.037226 | +0.027661 | 289% slower +FastRoute - unknown route (1000 routes) | 988 | 0.089904 | +0.080338 | 840% slower +FastRoute(cached) - unknown route (1000 routes) | 988 | 0.091358 | +0.081792 | 855% slower +FastRoute(cached) - last route (1000 routes) | 999 | 0.092567 | +0.083001 | 868% slower +FastRoute - last route (1000 routes) | 999 | 0.113668 | +0.104103 | 1088% slower +phroute/phroute - unknown route (1000 routes) | 987 | 0.168871 | +0.159305 | 1665% slower +phroute/phroute - last route (1000 routes) | 999 | 0.169914 | +0.160348 | 1676% slower +Pux PHP - unknown route (1000 routes) | 981 | 0.866280 | +0.856714 | 8956% slower +Pux PHP - last route (1000 routes) | 999 | 0.941322 | +0.931757 | 9741% slower +AltoRouter - unknown route (1000 routes) | 982 | 2.245384 | +2.235819 | 23373% slower +AltoRouter - last route (1000 routes) | 979 | 2.281995 | +2.272429 | 23756% slower +Symfony - unknown route (1000 routes) | 984 | 2.488247 | +2.478681 | 25912% slower +Symfony - last route (1000 routes) | 999 | 2.540170 | +2.530605 | 26455% slower +Macaw - unknown route (1000 routes) | 982 | 2.617635 | +2.608069 | 27265% slower +Macaw - last route (1000 routes) | 999 | 2.700128 | +2.690562 | 28127% slower ## First route matching -This benchmark tests how quickly each router can match the first route. 1,000 routes each with 9 arguments. - -This benchmark consists of 7 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded. - - -Test Name | Results | Time | + Interval | Change +Test Name | Results | Time(ms) | + Interval | Change --------- | ------- | ---- | ---------- | ------ -Pux PHP - first route(1000) | 993 | 0.0000105502 | +0.0000000000 | baseline -ORouter - first route(1000) | 984 | 0.0000118334 | +0.0000012832 | 12% slower -SRouter - first route(1000) | 982 | 0.0000118473 | +0.0000012971 | 12% slower -FastRoute(cached) - first route(1000) | 999 | 0.0000143361 | +0.0000037859 | 36% slower -FastRoute - first route(1000) | 999 | 0.0000143980 | +0.0000038477 | 36% slower -Symfony2 Dumped - first route | 993 | 0.0000350874 | +0.0000245372 | 233% slower -Symfony2 - first route | 999 | 0.0000630564 | +0.0000525061 | 498% slower +Pux PHP - first route(1000) | 997 | 0.006587 | +0.000000 | baseline +FastRoute - first route(1000) | 999 | 0.008751 | +0.002165 | 33% slower +phroute/phroute - first route (1000 routes) | 999 | 0.021902 | +0.015315 | 233% slower +Symfony Dumped - first route | 997 | 0.022254 | +0.015667 | 238% slower +Router - first route(1000) | 993 | 0.025026 | +0.018440 | 280% slower +SRouter - first route(1000) | 997 | 0.025553 | +0.018967 | 288% slower +noodlehaus/dispatch - first route (1000 routes) | 989 | 0.030126 | +0.023540 | 357% slower +AltoRouter - first route (1000 routes) | 994 | 0.041488 | +0.034902 | 530% slower +Symfony - first route | 991 | 0.047335 | +0.040748 | 619% slower +FastRoute(cached) - first route(1000) | 999 | 0.092703 | +0.086117 | 1307% slower +Macaw - first route (1000 routes) | 999 | 2.710132 | +2.703545 | 41047% slower diff --git a/docs/classes-api.md b/docs/classes-api.md new file mode 100644 index 0000000..9fd639e --- /dev/null +++ b/docs/classes-api.md @@ -0,0 +1,91 @@ +# 关键方法参考 + +## 添加路由方法 + +```php +public function map(string|array $methods, string $path, mixed $handler, array $opts = []) +``` + +添加路由方法 + +> 其他的添加路由方法底层都是调用的 `map()` 方法,除了没有第一个参数外,其他参数都是一样的 + +- `$methods` string/array 请求的METHOD. e.g `GET` `['GET', 'POST]` +- `$path` string 定义的路由字符串 e.g `/user/login` `/article/{id}` +- `$handler` string/object 对应路由的处理者 +- `$binds` array 路由参数匹配限制 eg `[ 'name' => '\w+' ]` +- `$opts` array 选项设置,可以添加自定义的数据。匹配成功会将选项数据返回(e.g middleware, domains),自己再做进一步验证等。下面是已使用的选项 + - `defaults` 有可选参数时,可以设置默认值 + +一个较为完整的示例: + +> 提示: 若不在选项中设置参数匹配,那么参数将会匹配除了 '/' 之外的任何字符 + +```php +$router->map(['get', 'post'], '/im/{name}[/{age}]', function(array $params) { + var_dump($params); +}, [ // 设置参数匹配 + 'name' => '\w+', + 'age' => '\d+', + ],[ + 'defaults' => [ + 'age' => 20, // 给可选参数 age 添加一个默认值 + ] + + // 可添加更多自定义设置 + 'middleware' => ['AuthCheck'], + ... ... +]); +``` + +Now, 访问 `/im/john/18` 或者 `/im/john` 查看效果 + +## 路由匹配 + +```php +array public function match(string $path, string $method) +``` + +- `$path` string 请求的URI path +- `$method` string 请求的request method +- 返回 `array` 返回匹配结果信息 + +### 示例 + +根据请求的 URI path 和 请求 METHOD 查找匹配我们定义的路由信息。 + +```php +$path = parse_url(http://github.com/$_SERVER['REQUEST_URI'],%20PHP_URL_PATH); +$method = $_SERVER['REQUEST_METHOD']; + +$route = $router->match($path, $method); +``` + + +将会返回如下格式的信息. 可以根据此信息进行 判断匹配是否成功 -> 路由调度 + +> 始终是三个元素的数组。第一二个元素是固定的, 第三个根据状态有所变化 + +- 第一个 匹配结果状态. 只有三个 `FOUND`, `NOT_FOUND`, `METHOD_NOT_ALLOWED` +- 第二个 格式化后的 $path 的返回(会去除多余的空白,'/'等字符) +- 第三个 根据状态有所不同: + - `FOUND` 路由信息对象 `Route` + - `NOT_FOUND` 为空 `null` + - `METHOD_NOT_ALLOWED` 返回的是允许的 METHODs `array` +- 结构信息如下: + +```php +[ + // 路由匹配结果状态. + // 可能为: RouterInterface::FOUND, RouterInterface::NOT_FOUND, RouterInterface::METHOD_NOT_ALLOWED + INT, + + // 格式化后的 $path 的返回(会去除多余的空白,'/'等字符) + 'URI PATH', + + // 第三个元素 + // NOT_FOUND 匹配失败时为 null, + // METHOD_NOT_ALLOWED 返回的array, 是允许的 METHODs + // FOUND 时为匹配的路由信息对象,object(Route) +] +``` diff --git a/docs/dispatcher.md b/docs/dispatcher.md index 47db91e..50306c0 100644 --- a/docs/dispatcher.md +++ b/docs/dispatcher.md @@ -102,7 +102,7 @@ $dispatcher->setMatcher(function ($path, $method) { }); ``` -- 使用 `ORouter` +- 使用 `Router` ```php $dispatcher->setMatcher(function ($path, $method) use ($router) { @@ -123,12 +123,12 @@ $dispatcher->dispatch(); ## 示例 -示例代码在 `examples` 下。 +示例代码在 `example` 下。 - SRouter -你可以通过 `php -S 127.0.0.1:5670 -t examples/static` 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5670 +你可以通过 `php -S 127.0.0.1:5670 -t example/static` 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5670 -- ORouter +- Router -你可以通过 `php -S 127.0.0.1:5671 -t examples/object` 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5671 +你可以通过 `php -S 127.0.0.1:5671 -t example/object` 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5671 diff --git a/docs/router.md b/docs/router.md index aaa57d8..e495c8c 100644 --- a/docs/router.md +++ b/docs/router.md @@ -5,22 +5,24 @@ > 匹配速度快,查找匹配速度基本上不受路由数量和路由的复杂度的影响 - `Inhere\Route\SRouter` 是静态类版本. -- `Inhere\Route\ORouter` 是对象版本 +- `Inhere\Route\Router` 是对象版本 压测: [benchmark](./benchmark.md) ## 路由收集 ```php -use Inhere\Route\SRouter; +use Inhere\Route\Router; + +$router = new Router(); // 匹配 GET 请求. 处理器是个闭包 Closure -SRouter::get('/', function() { +$router->get('/', function() { echo 'hello'; }); // 匹配参数 'test/john' -SRouter::get('/test/{name}', function($arg) { +$router->get('/test/{name}', function($arg) { echo $arg; // 'john' }, [ 'params' => [ @@ -29,7 +31,7 @@ SRouter::get('/test/{name}', function($arg) { ]); // 可选参数支持。匹配 'hello' 'hello/john' -SRouter::get('/hello[/{name}]', function($name = 'No') { +$router->get('/hello[/{name}]', function($name = 'No') { echo $name; // 'john' }, [ 'params' => [ @@ -38,60 +40,33 @@ SRouter::get('/hello[/{name}]', function($name = 'No') { ]); // 匹配 POST 请求 -SRouter::post('/user/login', function() { +$router->post('/user/login', function() { var_dump($_POST); }); // 匹配 GET 或者 POST -SRouter::map(['get', 'post'], '/user/login', function() { +$router->map(['get', 'post'], '/user/login', function() { var_dump($_GET, $_POST); }); // 允许任何请求方法 -SRouter::any('/home', function() { +$router->any('/home', function() { echo 'hello, you request page is /home'; }); // 路由组 -SRouter::group('/user', function () { - SRouter::get('/', function () { - echo 'hello. you access: /user/'; - }); - SRouter::get('/index', function () { - echo 'hello. you access: /user/index'; - }); -}); -``` - -使用 `ORouter` 则需先创建对象: - -```php -use Inhere\Route\ORouter; - -$router = new ORouter; - -// 添加路由 -// $router->get(); -// $router->post(); -// $router->put(); -// ... ... $router->group('/user', function ($router) { - /** @var \Inhere\Route\ORouter $router */ - $router->get('', function () { - echo 'hello. you access: /user'; + /** @var \Inhere\Route\Router $router */ + $router->get('/', function () { + echo 'hello. you access: /user/'; }); - - //$router->get('/', function () { - // echo 'hello. you access: /user/'; - //}); - $router->get('/index', function () { echo 'hello. you access: /user/index'; }); }); ``` -> 如果配置了 `'ignoreLastSep' => true`, '/index' 等同于 '/index/' +> 如果配置了 `'ignoreLastSlash' => true`, '/index' 等同于 '/index/' ### 实现原理(如何收集) @@ -99,23 +74,80 @@ $router->group('/user', function ($router) { #### 1. 静态路由 +整个路由 path 都是静态字符串 e.g. '/user/login' + 例如: ```php $router->post('/user/signUp', 'handler2'); ``` +- 存储结构 + +```php +array ( + '/' => array ( + 'GET' => array ( + 'handler' => 'handler0', + 'option' => array ( + ), + ), + ), + '/home' => array ( + 'GET' => array ( + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController@index', + 'option' => array ( + ), + ), + ), + '/post' => array ( + 'POST' => array ( + 'handler' => 'post_handler', + 'option' => array ( + ), + ), + ), + '/put' => array ( + 'PUT' => array ( + 'handler' => 'main_handler', + 'option' => array ( + ), + ), + ), + '/del' => array ( + 'DELETE' => array ( + 'handler' => 'main_handler', + 'option' => array ( + ), + ), + ), + '/pd' => array ( + 'POST' => array ( + 'handler' => 'multi_method_handler', + 'option' => array ( + ), + ), + 'DELETE' => array ( + 'handler' => 'multi_method_handler', + 'option' => array ( + ), + ), + ), +); +``` + #### 2. (有规律的)动态路由 +第一节是个静态字符串,称之为有规律的动态路由。按第一节的信息进行分组存储 + 例如: ```php /* match: /hello/tom - /hello */ -$router->get('/hello[/{name}]', function($name='NO') { +$router->get('/hello/{name}', function($name='NO') { echo "hello, $name"; // 'john' },[ 'params' => [ @@ -124,8 +156,47 @@ $router->get('/hello[/{name}]', function($name='NO') { ]); ``` +- 存储结构 + +```php + 'user' => array ( + 0 => array ( + 'regex' => '#^/user/(?P[1-9][0-9]*)$#', + 'start' => '/user/', + 'original' => '/user/{id}', + 'handler' => 'main_handler', + 'option' => array ( + ), + 'methods' => 'GET', + ), + 1 => array ( + 'regex' => '#^/user/(?P[1-9][0-9]*)$#', + 'start' => '/user/', + 'original' => '/user/{id}', + 'handler' => 'main_handler', + 'option' => array ( + ), + 'methods' => 'POST', + ), + ), + 'home' => array ( + 0 => array ( + 'regex' => '#^/home/(?P[a-zA-Z][\\w-]+)$#', + 'start' => '/home/', + 'original' => '/home/{act}', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'option' => array ( + ), + 'methods' => 'GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD,SEARCH,CONNECT,TRACE', + ), + ), +) +``` + #### 3. (无规律的)动态路由 +第一节就包含了正则匹配,称之为无规律/模糊的动态路由 + 例如: ```php @@ -136,6 +207,52 @@ $router->get('/{name}', 'default_handler', [ ]); ``` +- 存储结构 + +```php +array ( + 'GET' => array ( + 0 => array ( + 'regex' => '#^/about(?:\\.html)?$#', + 'start' => '/about', + 'original' => '/about[.html]', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController@about', + 'option' => array ( + ), + ), + 1 => array ( + 'regex' => '#^/(?Pblog|saying)$#', + 'start' => NULL, + 'original' => '/{name}', + 'handler' => 'default_handler', + 'option' => array ( + 'params' => array ( + 'name' => 'blog|saying', + ), + ), + ), + 2 => array ( + 'regex' => '#^/test(?:/optional)?$#', + 'start' => '/test', + 'original' => '/test[/optional]', + 'handler' => 'default_handler', + 'option' => array ( + ), + ), + 3 => array ( + 'regex' => '#^/blog-(?P[^/]+)$#', + 'start' => '/blog-', + 'original' => '/blog-{post}', + 'handler' => 'default_handler', + 'option' => array ( + ), + ), + ), + 'POST' => array( ... ), + 'PUT' => array( ... ) +) +``` + ## 路由匹配 ```php @@ -154,7 +271,7 @@ array|false public function match($path, $method) $path = parse_url(http://github.com/$_SERVER['REQUEST_URI'],%20PHP_URL_PATH); $method = $_SERVER['REQUEST_METHOD']; -$route = SRouter::match($path, $method); +$route = $router->match($path, $method); ``` 匹配失败,返回 `false` @@ -216,8 +333,8 @@ todo ... ```php // set config -SRouter::setConfig([ - 'ignoreLastSep' => true, +$router->config([ + 'ignoreLastSlash' => true, 'autoRoute' => 1, 'controllerNamespace' => 'app\\controllers', 'controllerSuffix' => 'Controller', @@ -228,14 +345,9 @@ SRouter::setConfig([ ```php // 所有的默认的配置 -[ - // 是否忽略最后的 '/' 分隔符. 如果是 true,将清除最后一个 '/', 此时请求 '/home' 和 '/home/' 效果相同 - 'ignoreLastSep' => false, - // 匹配所有请求 - // 1. 如果是一个有效的URI路径,将匹配所有请求到此URI路径。 - // 2. 如果是一个可用回调,将匹配所有请求然后调用它 - 'intercept' => '', // 例如: '/site/maintenance' 或者 `function () { echo 'System Maintaining ... ...'; }` + // 是否忽略最后的 '/' 分隔符. 如果是 true,将清除最后一个 '/', 此时请求 '/home' 和 '/home/' 效果相同 + 'ignoreLastSlash' = false, // 是否启用, 自动匹配路由到控制器就像 yii 一样. 'autoRoute' => false, @@ -243,10 +355,10 @@ SRouter::setConfig([ 'controllerNamespace' => '', // eg: 'app\\controllers' // 控制器类后缀 'controllerSuffix' => '', // eg: 'Controller' -] + ``` -> NOTICE: 必须在添加路由之前调用 `SRouter::setConfig()` +> NOTICE: 必须在添加路由之前调用 `$router->config()` ### 自动匹配路由 @@ -268,26 +380,3 @@ SRouter::setConfig([ - 大于等于两节的默认先认为最后一节是控制器类名,进行查找 - 若失败,再尝试将倒数第二节认为是控制器名,最后一节是action名 -### 匹配所有 - -配置 `intercept` 可用于拦截所有请求。 (例如网站维护时) - -可允许配置 `intercept` 的值为 - -- 路由path - -```php - 'intercept' => '/about', // a route path -``` - -将会直接执行此路由后停止执行 - -- 回调 - -```php - 'intercept' => function () { - echo '系统维护中 :)'; - }, -``` - -将会直接执行此回调后停止执行 diff --git a/example/benchmark.php b/example/benchmark.php new file mode 100644 index 0000000..1a4d038 --- /dev/null +++ b/example/benchmark.php @@ -0,0 +1,183 @@ + + * + * Options: + * + * : + * The number of routes to map & match. Defaults to 1000. + */ + +require dirname(__DIR__) . '/test/boot.php'; + +global $argv; +$n = isset($argv[1]) ? (int)$argv[1] : 1000; +$c = isset($argv[2]) ? (int)$argv[2] : 5; + +echo "There are generate $n routes. and dynamic route with {$c}0% chance\n\n"; + +// prepare benchmark data +$requests = []; +for ($i = 0; $i < $n; $i++) { + $requests[] = [ + 'method' => random_request_method(), + 'url' => random_request_url(http://github.com/$c), + ]; +} + +$startMem = memory_get_usage(); +$router = new \Inhere\Route\CachedRouter([ + 'cacheFile' => __DIR__ . '/cached/bench-routes-cache.php', + 'cacheEnable' => 0, + // 'tmpCacheNumber' => 100, +]); + +$requests[2] = [ + 'method' => 'GET', + 'url' => '/50be3774f6/{arg1}/{arg2}/{arg3}/{arg4}/{arg5}/{arg6}/{arg7}/{arg8}/{arg9}/850726135a' +]; + +/** + * collect routes + */ +$start = microtime(true); +foreach ($requests as $r) { + $router->add($r['method'], $r['url'], 'handler_func'); +} +$end = microtime(true); +$buildTime = $end - $start; +echo "Build time ($n routes): ", +pretty_echo(number_format($buildTime * 1000, 3), 'cyan'), +" ms, For collect and parse routes.\n\n"; + +// dump caches +$router->completed(); + +/** + * match first route + */ + +$r = $requests[0]; +$uri = str_replace(['{', '}'], '1', $r['url']); + +$start = microtime(true); +$ret['first'] = $router->match($uri, $r['method']); +$end = microtime(true); +$matchTimeF = $end - $start; +echo 'Match time (first route): ', +pretty_echo(number_format($matchTimeF, 6)), +" s.\n - URI: {$uri}, will match: {$r['url']}\n"; + +// try again +$start = microtime(true); +$router->match($uri, $r['method']); +$end = microtime(true); +$matchTimeF = $end - $start; +echo 'Match time (first route, second): ', +pretty_echo(number_format($matchTimeF, 6)), PHP_EOL; + +/** + * match random route + */ + +// pick random route to match +$r = $requests[random_int(0, $n)]; +$uri = str_replace(['{', '}'], '2', $r['url']); + +$start = microtime(true); +$ret['random'] = $router->match($uri, $r['method']); +$end = microtime(true); +$matchTimeR = $end - $start; +echo 'Match time (random route): ', +pretty_echo(number_format($matchTimeR, 6)), +" s.\n - URI: {$uri}, will match: {$r['url']}\n"; + +/** + * match last route + */ +$r = $requests[$n - 1]; +$uri = str_replace(['{', '}'], '3', $r['url']); + +$start = microtime(true); +$ret['last'] = $router->match($uri, $r['method']); +$end = microtime(true); +$matchTimeE = $end - $start; +echo 'Match time (last route): ', +pretty_echo(number_format($matchTimeE, 6)), +" s.\n - URI: {$uri}, will match: {$r['url']}\n"; + +/** + * match unknown route + */ +$start = microtime(true); +$ret['unknown'] = $router->match('/55-foo-bar', 'GET'); +$end = microtime(true); +$matchTimeU = $end - $start; +echo 'Match time (unknown route): ', pretty_echo(number_format($matchTimeU, 6)), " s\n"; + +// print totals +$totalTime = number_format($buildTime + $matchTimeF + $matchTimeR + $matchTimeU, 5); +echo PHP_EOL . 'Total time: ' . $totalTime . ' s' . PHP_EOL; +echo 'Memory usage: ' . round((memory_get_usage() - $startMem) / 1024) . ' KB' . PHP_EOL; +echo 'Peak memory usage: ' . round(memory_get_peak_usage(true) / 1024) . ' KB' . PHP_EOL; +echo "Match result: \n" . pretty_match_result($ret) . "\n\n"; + +/* +// 2017.12.3 +$ php example/benchmark.php +There are generate 1000 routes. and dynamic route with 10% chance + +Build time (1000 routes): 0.011926 s +Match time (first route): 0.000072 s(URI: /rlpkswupqzo/g) +Match time (random route): 0.000015 s(URI: /muq/vs) +Match time (last route): 0.000013 s(URI: /fneek/aedpctey/v/aaxzpf) +Match time (unknown route): 0.000014 s +Total time: 0.011953 s +Memory usage: 1814 KB +Peak memory usage: 2048 KB + +// 2017.12.26 +$ php example/benchmark.php +There are generate 1000 routes. and dynamic route with 50% chance + +Build time (1000 routes): 0.017 s, For collect and parse routes. + +Match time (first route): 0.000126 s(URI: /frlpz/y/yv/hzmjycn/fyuus/name) +Match time (random route): 0.000012 s(URI: /rt/tbivsuspclfyra/mrys) +Match time (last route): 0.000008 s(URI: /ltinm/mxrtqcbjb) +Match time (unknown route): 0.000015 s + +Total time: 0.017024 s +Memory usage: 1078 KB +Peak memory usage: 4096 KB + +// 2017.12.26 +$ php example/benchmark.php +There are generate 1000 routes. and no dynamic route + +Build time (1000 routes): 0.012 s, For collect and parse routes. + +Match time (first route): 0.000221 s(URI: /ltnwon/epwnihhylz/qmd) +Match time (random route): 0.000014 s(URI: /okluuvfaz/bolsgvnjp) +Match time (last route): 0.000009 s(URI: /rwako/vg/x) +Match time (unknown route): 0.000019 s + +Total time: 0.012515 s +Memory usage: 1014 KB +Peak memory usage: 2048 KB + +// 2018.11.17 +There are generate 1000 routes. and dynamic route with 50% chance + +Build time (1000 routes): 5.885 ms, For collect and parse routes. + +Match time (first route): 0.000593 s. +Match time (first route, second): 0.000015 +Match time (random route): 0.000042 s. +Match time (last route): 0.000006 s. +Match time (unknown route): 0.000008 s + + */ diff --git a/examples/cached.php b/example/cached.php similarity index 58% rename from examples/cached.php rename to example/cached.php index 50cbd29..79e12c6 100644 --- a/examples/cached.php +++ b/example/cached.php @@ -1,4 +1,4 @@ - true, - // 'tmpCacheNumber' => 100, + // 'ignoreLastSlash' => true, -// 'cacheFile' => '', + // 'cacheFile' => '', 'cacheFile' => __DIR__ . '/cached/routes-cache.php', 'cacheEnable' => 1, -// 'matchAll' => '/', // a route path -// 'matchAll' => function () { -// echo 'System Maintaining ... ...'; -// }, - // enable autoRoute // you can access '/demo' '/admin/user/info', Don't need to configure any route - 'autoRoute' => 1, - 'controllerNamespace' => 'Inhere\Route\Examples\Controllers', + 'autoRoute' => 1, + 'controllerNamespace' => 'Inhere\RouteTest\Controllers', 'controllerSuffix' => 'Controller', ]); -function dump_routes() { +function dump_routes() +{ global $router; - - var_dump( - $router->getStaticRoutes(), - $router->getVagueRoutes() - ); - - var_dump($router->getRegularRoutes()); + echo "
{$router->__toString()}
"; } $router->get('/routes', 'dump_routes'); +$router->any('*', 'main_handler'); /** @var array $routes */ $routes = require __DIR__ . '/some-routes.php'; - foreach ($routes as $route) { // group if (is_array($route[1])) { $rs = $route[1]; - $router->group($route[0], function (CachedRouter $router) use($rs){ + $router->group($route[0], function (RouterInterface $router) use ($rs) { foreach ($rs as $r) { // cannot cache the \Closure if (is_object($r[2])) { continue; } - $router->map($r[0], $r[1], $r[2], isset($r[3]) ? $r[3] : []); + $router->map($r[0], $r[1], $r[2], $r[3] ?? [], $r[4] ?? []); } }); @@ -74,8 +64,9 @@ function dump_routes() { continue; } - $router->map($route[0], $route[1], $route[2], isset($route[3]) ? $route[3] : []); + $router->map($route[0], $route[1], $route[2], $route[3] ?? [], $route[4] ?? []); } +$router->completed(); $dispatcher = new Dispatcher([ 'dynamicAction' => true, @@ -86,7 +77,12 @@ function dump_routes() { echo "the page $path not found!"; }); -// $dispatcher->dispatch(); +$dispatcher->setRouter($router); // var_dump($router->getConfig(),$router);die; -$router->dispatch($dispatcher); +try { + // $router->dispatch($dispatcher); + $dispatcher->dispatchUri(); +} catch (Throwable $e) { + var_dump($e); +} diff --git a/example/cached/bench-routes-cache.php b/example/cached/bench-routes-cache.php new file mode 100644 index 0000000..8d5dbe4 --- /dev/null +++ b/example/cached/bench-routes-cache.php @@ -0,0 +1,19309 @@ + [ + 'GET /h/akjnpgrn' => [ + 'name' => '', + 'path' => '/h/akjnpgrn', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /qm/mnkkaosj/f/oyfciidad/' => [ + 'name' => '', + 'path' => '/qm/mnkkaosj/f/oyfciidad/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /i/hk/dikhdhtaccbethew' => [ + 'name' => '', + 'path' => '/i/hk/dikhdhtaccbethew', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /p/lfezeldnk' => [ + 'name' => '', + 'path' => '/p/lfezeldnk', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /qj/gjiqcq/jj/' => [ + 'name' => '', + 'path' => '/qj/gjiqcq/jj/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ea/qsk/dtu' => [ + 'name' => '', + 'path' => '/ea/qsk/dtu', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /qxvrbtprga' => [ + 'name' => '', + 'path' => '/qxvrbtprga', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /hz/ccbnpuxahzraiwh/rn/' => [ + 'name' => '', + 'path' => '/hz/ccbnpuxahzraiwh/rn/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /bhmilprlw' => [ + 'name' => '', + 'path' => '/bhmilprlw', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /tdqfbxyy/jnqjxcoxhnhc/' => [ + 'name' => '', + 'path' => '/tdqfbxyy/jnqjxcoxhnhc/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /yeu/trbfg' => [ + 'name' => '', + 'path' => '/yeu/trbfg', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /dogykdvls' => [ + 'name' => '', + 'path' => '/dogykdvls', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/wvhfzwtbwdwbhwg' => [ + 'name' => '', + 'path' => '/goods/wvhfzwtbwdwbhwg', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/vblohh' => [ + 'name' => '', + 'path' => '/user/vblohh', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /g/nsfeyzcrmzniqok' => [ + 'name' => '', + 'path' => '/g/nsfeyzcrmzniqok', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /dbilirn/m/' => [ + 'name' => '', + 'path' => '/dbilirn/m/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /vvjsxj/gj' => [ + 'name' => '', + 'path' => '/vvjsxj/gj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /user/yanntcpigcuqthy' => [ + 'name' => '', + 'path' => '/user/yanntcpigcuqthy', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /eq/hraam/' => [ + 'name' => '', + 'path' => '/eq/hraam/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ugsstkmj' => [ + 'name' => '', + 'path' => '/ugsstkmj', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /aighibehu/c/tms' => [ + 'name' => '', + 'path' => '/aighibehu/c/tms', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /qgccl/neg/zfb/jmknhw' => [ + 'name' => '', + 'path' => '/qgccl/neg/zfb/jmknhw', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/dvbjygazdmsmlry' => [ + 'name' => '', + 'path' => '/goods/dvbjygazdmsmlry', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /qnskmrpmfkq' => [ + 'name' => '', + 'path' => '/qnskmrpmfkq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /fqozwgghmypmrztj' => [ + 'name' => '', + 'path' => '/fqozwgghmypmrztj', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /aljdbj/jildsmw/auks' => [ + 'name' => '', + 'path' => '/aljdbj/jildsmw/auks', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /rc/fratzt/pn/opdb/sd/' => [ + 'name' => '', + 'path' => '/rc/fratzt/pn/opdb/sd/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /fdqtzimyhqtpfi/znvp/a/k' => [ + 'name' => '', + 'path' => '/fdqtzimyhqtpfi/znvp/a/k', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /lzyqbdb/oivfbb' => [ + 'name' => '', + 'path' => '/lzyqbdb/oivfbb', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /tjnwyuidrw/epiqjx/pij' => [ + 'name' => '', + 'path' => '/tjnwyuidrw/epiqjx/pij', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/koqwcgyfucfq' => [ + 'name' => '', + 'path' => '/user/koqwcgyfucfq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /y/kubale/' => [ + 'name' => '', + 'path' => '/y/kubale/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /zbuyrkvhuybvvurwitw' => [ + 'name' => '', + 'path' => '/zbuyrkvhuybvvurwitw', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /api/bhpusfjhpuag' => [ + 'name' => '', + 'path' => '/api/bhpusfjhpuag', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/nsnsyakwxfikuee' => [ + 'name' => '', + 'path' => '/user/nsnsyakwxfikuee', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /v2/eulqauqocyrfmmx' => [ + 'name' => '', + 'path' => '/v2/eulqauqocyrfmmx', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /qmlwpeg' => [ + 'name' => '', + 'path' => '/qmlwpeg', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /jvsyg/nr/fxj/guduixx' => [ + 'name' => '', + 'path' => '/jvsyg/nr/fxj/guduixx', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /e/ifxbkyrts/vghwqwkuqm' => [ + 'name' => '', + 'path' => '/e/ifxbkyrts/vghwqwkuqm', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /mxkrsynthu' => [ + 'name' => '', + 'path' => '/mxkrsynthu', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ik/hyqjb/dljm' => [ + 'name' => '', + 'path' => '/ik/hyqjb/dljm', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /my/sbyegp/eaw' => [ + 'name' => '', + 'path' => '/my/sbyegp/eaw', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /zgi/uwzh' => [ + 'name' => '', + 'path' => '/zgi/uwzh', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /cj/l/t/xjct' => [ + 'name' => '', + 'path' => '/cj/l/t/xjct', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ec/gbrg/lwqlp/du/jch/i/' => [ + 'name' => '', + 'path' => '/ec/gbrg/lwqlp/du/jch/i/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ikekc/dk/ycpqc/rpsnvrua' => [ + 'name' => '', + 'path' => '/ikekc/dk/ycpqc/rpsnvrua', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /lsqhrqj/ktwqg/e' => [ + 'name' => '', + 'path' => '/lsqhrqj/ktwqg/e', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/augmqstkrnxpsxjkvb' => [ + 'name' => '', + 'path' => '/goods/augmqstkrnxpsxjkvb', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /krokzzizl' => [ + 'name' => '', + 'path' => '/krokzzizl', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/ygpjan' => [ + 'name' => '', + 'path' => '/api/ygpjan', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /wpnrlq/jmffnlk/xhpk/ggv' => [ + 'name' => '', + 'path' => '/wpnrlq/jmffnlk/xhpk/ggv', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /wqqivdv/' => [ + 'name' => '', + 'path' => '/wqqivdv/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /v2/djjevmlptjwklbv' => [ + 'name' => '', + 'path' => '/v2/djjevmlptjwklbv', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /api/tkdgtdtgbqyicak' => [ + 'name' => '', + 'path' => '/api/tkdgtdtgbqyicak', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /b/baz/w/iim' => [ + 'name' => '', + 'path' => '/b/baz/w/iim', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /fre/iat/ulu/mjaev' => [ + 'name' => '', + 'path' => '/fre/iat/ulu/mjaev', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /edvo/dynqnnh/dpnwkw' => [ + 'name' => '', + 'path' => '/edvo/dynqnnh/dpnwkw', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /v/cpy/ls/hrprf' => [ + 'name' => '', + 'path' => '/v/cpy/ls/hrprf', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /goods/bakvga' => [ + 'name' => '', + 'path' => '/goods/bakvga', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /lsefkvozx/gljcbioeemk' => [ + 'name' => '', + 'path' => '/lsefkvozx/gljcbioeemk', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /giwqnmfxihb/' => [ + 'name' => '', + 'path' => '/giwqnmfxihb/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /sgdnlozjhho/rq/' => [ + 'name' => '', + 'path' => '/sgdnlozjhho/rq/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /smizgtam' => [ + 'name' => '', + 'path' => '/smizgtam', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /qdgjr' => [ + 'name' => '', + 'path' => '/qdgjr', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /aiaienfnp/d/rqlgsd' => [ + 'name' => '', + 'path' => '/aiaienfnp/d/rqlgsd', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /v2/hodaykhuqscg' => [ + 'name' => '', + 'path' => '/v2/hodaykhuqscg', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /xadpq' => [ + 'name' => '', + 'path' => '/xadpq', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /uoqbc' => [ + 'name' => '', + 'path' => '/uoqbc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /api/qpsvpcicgzbiarg' => [ + 'name' => '', + 'path' => '/api/qpsvpcicgzbiarg', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /mcbdp' => [ + 'name' => '', + 'path' => '/mcbdp', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /uucse/' => [ + 'name' => '', + 'path' => '/uucse/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /sqfdrmpb/ohvqyo' => [ + 'name' => '', + 'path' => '/sqfdrmpb/ohvqyo', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /dzafkazfhx' => [ + 'name' => '', + 'path' => '/dzafkazfhx', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /stx/bphtk' => [ + 'name' => '', + 'path' => '/stx/bphtk', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /jsmjgyjquxiyvl/lp' => [ + 'name' => '', + 'path' => '/jsmjgyjquxiyvl/lp', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/zpjaxcuwpqhi' => [ + 'name' => '', + 'path' => '/user/zpjaxcuwpqhi', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /v2/swobnj' => [ + 'name' => '', + 'path' => '/v2/swobnj', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /mjplivkj' => [ + 'name' => '', + 'path' => '/mjplivkj', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /otx/ll' => [ + 'name' => '', + 'path' => '/otx/ll', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/ljgvmxztjsrogni' => [ + 'name' => '', + 'path' => '/goods/ljgvmxztjsrogni', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ccbbp' => [ + 'name' => '', + 'path' => '/ccbbp', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/fpduszgwvtkl' => [ + 'name' => '', + 'path' => '/user/fpduszgwvtkl', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /kb/amjvvn/cv/rxcgkmt' => [ + 'name' => '', + 'path' => '/kb/amjvvn/cv/rxcgkmt', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /vchoy/hmityjttuth/m' => [ + 'name' => '', + 'path' => '/vchoy/hmityjttuth/m', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /zhqsqdygnvomzhyhtgww' => [ + 'name' => '', + 'path' => '/zhqsqdygnvomzhyhtgww', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /otqwz/fsqvsts/f' => [ + 'name' => '', + 'path' => '/otqwz/fsqvsts/f', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /yq/uhrlc' => [ + 'name' => '', + 'path' => '/yq/uhrlc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /loln/hboxfokqlrjpmwz/w' => [ + 'name' => '', + 'path' => '/loln/hboxfokqlrjpmwz/w', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /oejea/cay' => [ + 'name' => '', + 'path' => '/oejea/cay', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /tyaih/rnjcwxia' => [ + 'name' => '', + 'path' => '/tyaih/rnjcwxia', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /user/sjuskk' => [ + 'name' => '', + 'path' => '/user/sjuskk', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /knodhaturp' => [ + 'name' => '', + 'path' => '/knodhaturp', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /fv/qvnbblw/' => [ + 'name' => '', + 'path' => '/fv/qvnbblw/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /api/pfttrhshavuxnwjhlh' => [ + 'name' => '', + 'path' => '/api/pfttrhshavuxnwjhlh', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /api/gbuukv' => [ + 'name' => '', + 'path' => '/api/gbuukv', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /efdzykvzn' => [ + 'name' => '', + 'path' => '/efdzykvzn', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /cbsvhdikmxjoy' => [ + 'name' => '', + 'path' => '/cbsvhdikmxjoy', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/obluhxpghgmgexjnbi' => [ + 'name' => '', + 'path' => '/goods/obluhxpghgmgexjnbi', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ghyoefd' => [ + 'name' => '', + 'path' => '/ghyoefd', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /fz/p/vtnvhzhfklhibf' => [ + 'name' => '', + 'path' => '/fz/p/vtnvhzhfklhibf', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /t/o/e/ypn/uau' => [ + 'name' => '', + 'path' => '/t/o/e/ypn/uau', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /zfsqtol/igmgjndy/nfn/th' => [ + 'name' => '', + 'path' => '/zfsqtol/igmgjndy/nfn/th', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /hij/ex/sanbqumjz' => [ + 'name' => '', + 'path' => '/hij/ex/sanbqumjz', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ktoyxkb' => [ + 'name' => '', + 'path' => '/ktoyxkb', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /zxne/ytaj/t' => [ + 'name' => '', + 'path' => '/zxne/ytaj/t', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /xhq/goze/ttyv/jms/' => [ + 'name' => '', + 'path' => '/xhq/goze/ttyv/jms/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /fcbkoocki/' => [ + 'name' => '', + 'path' => '/fcbkoocki/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /goods/arfmwjwowsdecis' => [ + 'name' => '', + 'path' => '/goods/arfmwjwowsdecis', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /k/bfdta/mubtvo/qp/' => [ + 'name' => '', + 'path' => '/k/bfdta/mubtvo/qp/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/nkysxi' => [ + 'name' => '', + 'path' => '/goods/nkysxi', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /davqp' => [ + 'name' => '', + 'path' => '/davqp', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /tihtcogsnh/jk/mr/' => [ + 'name' => '', + 'path' => '/tihtcogsnh/jk/mr/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /api/myclae' => [ + 'name' => '', + 'path' => '/api/myclae', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /vku/izomjl/at' => [ + 'name' => '', + 'path' => '/vku/izomjl/at', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /doblrqg/forprowbaohxl' => [ + 'name' => '', + 'path' => '/doblrqg/forprowbaohxl', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /kbve/fansycmxro' => [ + 'name' => '', + 'path' => '/kbve/fansycmxro', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/nstkpgshfjwkuhngib' => [ + 'name' => '', + 'path' => '/v2/nstkpgshfjwkuhngib', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /lxvzjrkgi/' => [ + 'name' => '', + 'path' => '/lxvzjrkgi/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/iltvyo' => [ + 'name' => '', + 'path' => '/goods/iltvyo', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /v2/zdrlnouduygynnv' => [ + 'name' => '', + 'path' => '/v2/zdrlnouduygynnv', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /qakijdmizeaqdf' => [ + 'name' => '', + 'path' => '/qakijdmizeaqdf', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /hosghaiotwfmken/stz/c/' => [ + 'name' => '', + 'path' => '/hosghaiotwfmken/stz/c/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /bihgp' => [ + 'name' => '', + 'path' => '/bihgp', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/eivahqvpihww' => [ + 'name' => '', + 'path' => '/user/eivahqvpihww', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /enw/gl/k/otwaecwbhmc' => [ + 'name' => '', + 'path' => '/enw/gl/k/otwaecwbhmc', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /oql/ybp/dc/i' => [ + 'name' => '', + 'path' => '/oql/ybp/dc/i', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /lizzk/j/nclys/nqw/ibc' => [ + 'name' => '', + 'path' => '/lizzk/j/nclys/nqw/ibc', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /xianps/yqtyp' => [ + 'name' => '', + 'path' => '/xianps/yqtyp', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/ulqmldnkaggqxyr' => [ + 'name' => '', + 'path' => '/goods/ulqmldnkaggqxyr', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/dxvryikvcwnazah' => [ + 'name' => '', + 'path' => '/api/dxvryikvcwnazah', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /tnqvdnqjtvrf/mswe/' => [ + 'name' => '', + 'path' => '/tnqvdnqjtvrf/mswe/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /hrzbgaogcc' => [ + 'name' => '', + 'path' => '/hrzbgaogcc', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /goods/iuyxmduqgspk' => [ + 'name' => '', + 'path' => '/goods/iuyxmduqgspk', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /rqcl/bmwg' => [ + 'name' => '', + 'path' => '/rqcl/bmwg', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /yk/xqlmajvry' => [ + 'name' => '', + 'path' => '/yk/xqlmajvry', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /xaq/b/utvm' => [ + 'name' => '', + 'path' => '/xaq/b/utvm', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /tqwlppkyjgu' => [ + 'name' => '', + 'path' => '/tqwlppkyjgu', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /oopdl/' => [ + 'name' => '', + 'path' => '/oopdl/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /sjs/wimcyp/' => [ + 'name' => '', + 'path' => '/sjs/wimcyp/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /u/vqq/qeaavjfrh/' => [ + 'name' => '', + 'path' => '/u/vqq/qeaavjfrh/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /api/eurnnmvxgdny' => [ + 'name' => '', + 'path' => '/api/eurnnmvxgdny', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /zz/sfyn/gxvdk/mxgdwi/' => [ + 'name' => '', + 'path' => '/zz/sfyn/gxvdk/mxgdwi/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /dmnagbvx/' => [ + 'name' => '', + 'path' => '/dmnagbvx/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /vfegazr/jzak' => [ + 'name' => '', + 'path' => '/vfegazr/jzak', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /numslh/iaq/rjqilelvw/h' => [ + 'name' => '', + 'path' => '/numslh/iaq/rjqilelvw/h', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /user/vrxgxkfwjfcbddbbph' => [ + 'name' => '', + 'path' => '/user/vrxgxkfwjfcbddbbph', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /mpbht/wwnrfyoc/jyw/g/' => [ + 'name' => '', + 'path' => '/mpbht/wwnrfyoc/jyw/g/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /mbvc/rd/oqqeqzezrw' => [ + 'name' => '', + 'path' => '/mbvc/rd/oqqeqzezrw', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ljladkw/nc/l' => [ + 'name' => '', + 'path' => '/ljladkw/nc/l', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /yg/iptyfmwwoi/eg' => [ + 'name' => '', + 'path' => '/yg/iptyfmwwoi/eg', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /sdy/q/zovzakolr/pd/mz' => [ + 'name' => '', + 'path' => '/sdy/q/zovzakolr/pd/mz', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ofns/wby/o/t' => [ + 'name' => '', + 'path' => '/ofns/wby/o/t', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /gl/hzgf/i/rp/hr/' => [ + 'name' => '', + 'path' => '/gl/hzgf/i/rp/hr/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ocrqtdbz/bmecjli/ipbbn' => [ + 'name' => '', + 'path' => '/ocrqtdbz/bmecjli/ipbbn', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/sjmpmp' => [ + 'name' => '', + 'path' => '/goods/sjmpmp', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /bfp/xmduw/b' => [ + 'name' => '', + 'path' => '/bfp/xmduw/b', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /p/gqhctjtvyfzrcb/r' => [ + 'name' => '', + 'path' => '/p/gqhctjtvyfzrcb/r', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /api/atwrrftybiyfqaw' => [ + 'name' => '', + 'path' => '/api/atwrrftybiyfqaw', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /goods/pbifjkhikrwh' => [ + 'name' => '', + 'path' => '/goods/pbifjkhikrwh', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /rhdj/eeh' => [ + 'name' => '', + 'path' => '/rhdj/eeh', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ttuw/cno/jtq' => [ + 'name' => '', + 'path' => '/ttuw/cno/jtq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /sng/r/kmcdpx' => [ + 'name' => '', + 'path' => '/sng/r/kmcdpx', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /mrrxs' => [ + 'name' => '', + 'path' => '/mrrxs', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /goods/gwlxupxlcbsrbsd' => [ + 'name' => '', + 'path' => '/goods/gwlxupxlcbsrbsd', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /s/roc/ingd/rgb' => [ + 'name' => '', + 'path' => '/s/roc/ingd/rgb', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /zquie/smlszyeqycj' => [ + 'name' => '', + 'path' => '/zquie/smlszyeqycj', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/fzjuajgsyljcwho' => [ + 'name' => '', + 'path' => '/goods/fzjuajgsyljcwho', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/nzyshycafcsk' => [ + 'name' => '', + 'path' => '/goods/nzyshycafcsk', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /wpk/oevns' => [ + 'name' => '', + 'path' => '/wpk/oevns', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /kvovzkralitge/l/u/v/' => [ + 'name' => '', + 'path' => '/kvovzkralitge/l/u/v/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /p/qjyw/kuqri' => [ + 'name' => '', + 'path' => '/p/qjyw/kuqri', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /kakiklpklau/jiskxqxyc' => [ + 'name' => '', + 'path' => '/kakiklpklau/jiskxqxyc', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/bfnmufhfsnhlxny' => [ + 'name' => '', + 'path' => '/api/bfnmufhfsnhlxny', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /tbyqrganxwm/vljojjmbb' => [ + 'name' => '', + 'path' => '/tbyqrganxwm/vljojjmbb', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /uaxp/rpqc' => [ + 'name' => '', + 'path' => '/uaxp/rpqc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /olrdzxrfxeh' => [ + 'name' => '', + 'path' => '/olrdzxrfxeh', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /c/cmo/r' => [ + 'name' => '', + 'path' => '/c/cmo/r', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /tarzgesyadhly' => [ + 'name' => '', + 'path' => '/tarzgesyadhly', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /yimaf/el' => [ + 'name' => '', + 'path' => '/yimaf/el', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /agi/fg' => [ + 'name' => '', + 'path' => '/agi/fg', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /w/maflacgzfpna/l' => [ + 'name' => '', + 'path' => '/w/maflacgzfpna/l', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /f/z/f/xdmde/lliezvi/xrwwj' => [ + 'name' => '', + 'path' => '/f/z/f/xdmde/lliezvi/xrwwj', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /dcdpwooil' => [ + 'name' => '', + 'path' => '/dcdpwooil', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/oepoibzzgchcxiz' => [ + 'name' => '', + 'path' => '/v2/oepoibzzgchcxiz', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /dmxhjouywdk' => [ + 'name' => '', + 'path' => '/dmxhjouywdk', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /om/x/tnrre/arrwf/u' => [ + 'name' => '', + 'path' => '/om/x/tnrre/arrwf/u', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /lodyb/siggaa' => [ + 'name' => '', + 'path' => '/lodyb/siggaa', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /biysqzjte/xdgqdbwr' => [ + 'name' => '', + 'path' => '/biysqzjte/xdgqdbwr', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/fvtaxntjabbc' => [ + 'name' => '', + 'path' => '/api/fvtaxntjabbc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /b/uw/fu' => [ + 'name' => '', + 'path' => '/b/uw/fu', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/gcwjtqtyqljordqipc' => [ + 'name' => '', + 'path' => '/user/gcwjtqtyqljordqipc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /e/popmanhoj' => [ + 'name' => '', + 'path' => '/e/popmanhoj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/cuexstrpygurzaj' => [ + 'name' => '', + 'path' => '/v2/cuexstrpygurzaj', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /lnprkjm' => [ + 'name' => '', + 'path' => '/lnprkjm', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /dl/bzxq/forbg/mjwbqe' => [ + 'name' => '', + 'path' => '/dl/bzxq/forbg/mjwbqe', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /ztwz/yfb/dge/wlv' => [ + 'name' => '', + 'path' => '/ztwz/yfb/dge/wlv', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /hziqw/bymy' => [ + 'name' => '', + 'path' => '/hziqw/bymy', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /kcc/cfj/ql' => [ + 'name' => '', + 'path' => '/kcc/cfj/ql', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /v2/pnhbigyuqbkxmhm' => [ + 'name' => '', + 'path' => '/v2/pnhbigyuqbkxmhm', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /izeidmfnmlgrbdhgrtnk' => [ + 'name' => '', + 'path' => '/izeidmfnmlgrbdhgrtnk', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /shcif/ab/s/z/nswuczigoh' => [ + 'name' => '', + 'path' => '/shcif/ab/s/z/nswuczigoh', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /fzazkobuj' => [ + 'name' => '', + 'path' => '/fzazkobuj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /fklwd' => [ + 'name' => '', + 'path' => '/fklwd', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /xr/t/rn/bfyszexyxhgkwl' => [ + 'name' => '', + 'path' => '/xr/t/rn/bfyszexyxhgkwl', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /qlbjpcrooyw' => [ + 'name' => '', + 'path' => '/qlbjpcrooyw', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /dkhbrtwehy/s/' => [ + 'name' => '', + 'path' => '/dkhbrtwehy/s/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /vkqsoouhlcgyuyzrn' => [ + 'name' => '', + 'path' => '/vkqsoouhlcgyuyzrn', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /zeipmwemmz/eveb/zw' => [ + 'name' => '', + 'path' => '/zeipmwemmz/eveb/zw', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ycyytqaty/xmqg' => [ + 'name' => '', + 'path' => '/ycyytqaty/xmqg', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /user/jbxhvakysalb' => [ + 'name' => '', + 'path' => '/user/jbxhvakysalb', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /kzyjrdnlw/hht/fpsijgj' => [ + 'name' => '', + 'path' => '/kzyjrdnlw/hht/fpsijgj', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /thpghmpvmpj/gue/oeefgm' => [ + 'name' => '', + 'path' => '/thpghmpvmpj/gue/oeefgm', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ugikc' => [ + 'name' => '', + 'path' => '/ugikc', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /spukc' => [ + 'name' => '', + 'path' => '/spukc', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /ymil/k/pmhce/j/gmde/wc' => [ + 'name' => '', + 'path' => '/ymil/k/pmhce/j/gmde/wc', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /et/ugxznzd' => [ + 'name' => '', + 'path' => '/et/ugxznzd', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /k/zacee/yp' => [ + 'name' => '', + 'path' => '/k/zacee/yp', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /k/mw/pv' => [ + 'name' => '', + 'path' => '/k/mw/pv', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /cezcbys' => [ + 'name' => '', + 'path' => '/cezcbys', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /user/tnseoepgynwsctwsya' => [ + 'name' => '', + 'path' => '/user/tnseoepgynwsctwsya', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/rcmqsdfyrrkqcdhjal' => [ + 'name' => '', + 'path' => '/api/rcmqsdfyrrkqcdhjal', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /h/kfqs' => [ + 'name' => '', + 'path' => '/h/kfqs', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/patjob' => [ + 'name' => '', + 'path' => '/user/patjob', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /lpbodyc' => [ + 'name' => '', + 'path' => '/lpbodyc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /nrhz/qzyfuxoj/g' => [ + 'name' => '', + 'path' => '/nrhz/qzyfuxoj/g', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /jhianp/fgonfma/yds' => [ + 'name' => '', + 'path' => '/jhianp/fgonfma/yds', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/dgjovn' => [ + 'name' => '', + 'path' => '/v2/dgjovn', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /yj/leblysnumosx' => [ + 'name' => '', + 'path' => '/yj/leblysnumosx', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /mvzkpfevwqnyiswv/bxw/' => [ + 'name' => '', + 'path' => '/mvzkpfevwqnyiswv/bxw/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /drunk/' => [ + 'name' => '', + 'path' => '/drunk/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /jclzq/mz/y/' => [ + 'name' => '', + 'path' => '/jclzq/mz/y/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/ehgshp' => [ + 'name' => '', + 'path' => '/user/ehgshp', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /mckx/trsseeb/qvmiasrw' => [ + 'name' => '', + 'path' => '/mckx/trsseeb/qvmiasrw', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /csjqbembvvlbfsjy' => [ + 'name' => '', + 'path' => '/csjqbembvvlbfsjy', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /zaiitrwgy/' => [ + 'name' => '', + 'path' => '/zaiitrwgy/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /jsfstufn/' => [ + 'name' => '', + 'path' => '/jsfstufn/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ffndbm/oaavz/dsxdmn/fy' => [ + 'name' => '', + 'path' => '/ffndbm/oaavz/dsxdmn/fy', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /api/pjrssykihlzyros' => [ + 'name' => '', + 'path' => '/api/pjrssykihlzyros', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /gepktd/edonyqvrzb/' => [ + 'name' => '', + 'path' => '/gepktd/edonyqvrzb/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /x/vgxmhb' => [ + 'name' => '', + 'path' => '/x/vgxmhb', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /goods/nenuzfxmfnisbbogxl' => [ + 'name' => '', + 'path' => '/goods/nenuzfxmfnisbbogxl', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/omwloh' => [ + 'name' => '', + 'path' => '/goods/omwloh', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /user/desrxkhmfoxmgmvphu' => [ + 'name' => '', + 'path' => '/user/desrxkhmfoxmgmvphu', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /user/yjhmisiwxheegwk' => [ + 'name' => '', + 'path' => '/user/yjhmisiwxheegwk', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /srwnke/ntsso' => [ + 'name' => '', + 'path' => '/srwnke/ntsso', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /cjcs/znckp' => [ + 'name' => '', + 'path' => '/cjcs/znckp', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /edd/yztacid/' => [ + 'name' => '', + 'path' => '/edd/yztacid/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /v2/pfmzoihkjwytmtf' => [ + 'name' => '', + 'path' => '/v2/pfmzoihkjwytmtf', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /v2/etmtzr' => [ + 'name' => '', + 'path' => '/v2/etmtzr', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/ogdxsexfeydpfcv' => [ + 'name' => '', + 'path' => '/goods/ogdxsexfeydpfcv', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /llaqvjocsp/hjuw' => [ + 'name' => '', + 'path' => '/llaqvjocsp/hjuw', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /p/zokffwu' => [ + 'name' => '', + 'path' => '/p/zokffwu', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /uu/eahuwvnp/z' => [ + 'name' => '', + 'path' => '/uu/eahuwvnp/z', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /hihlqwhnj/uhsac' => [ + 'name' => '', + 'path' => '/hihlqwhnj/uhsac', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ctjp/hlcnguqzgnoa' => [ + 'name' => '', + 'path' => '/ctjp/hlcnguqzgnoa', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /rcjrdbxokx' => [ + 'name' => '', + 'path' => '/rcjrdbxokx', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /brw/zwoxbdfnkzstboxg/' => [ + 'name' => '', + 'path' => '/brw/zwoxbdfnkzstboxg/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /yveskgwdu' => [ + 'name' => '', + 'path' => '/yveskgwdu', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /qt/hshaoea' => [ + 'name' => '', + 'path' => '/qt/hshaoea', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /jtzomdxoh' => [ + 'name' => '', + 'path' => '/jtzomdxoh', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /orhlrfy' => [ + 'name' => '', + 'path' => '/orhlrfy', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /b/t/lpmba/myz/' => [ + 'name' => '', + 'path' => '/b/t/lpmba/myz/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /jr/higwlnjo' => [ + 'name' => '', + 'path' => '/jr/higwlnjo', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /mzzwacrbmdpps' => [ + 'name' => '', + 'path' => '/mzzwacrbmdpps', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /uyoonssudh/pmg' => [ + 'name' => '', + 'path' => '/uyoonssudh/pmg', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /cs/pspaic/aulfwro/grzkl' => [ + 'name' => '', + 'path' => '/cs/pspaic/aulfwro/grzkl', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /initweoe/kpx/dor/lht' => [ + 'name' => '', + 'path' => '/initweoe/kpx/dor/lht', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /kajgxeiyv/p/iwbosm/' => [ + 'name' => '', + 'path' => '/kajgxeiyv/p/iwbosm/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /gmjdqdmn' => [ + 'name' => '', + 'path' => '/gmjdqdmn', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/vyfzohtiexmq' => [ + 'name' => '', + 'path' => '/goods/vyfzohtiexmq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /oolbmex/e' => [ + 'name' => '', + 'path' => '/oolbmex/e', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /lkjd/sd/rynkh/fj/ahk/bix' => [ + 'name' => '', + 'path' => '/lkjd/sd/rynkh/fj/ahk/bix', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /yrt/cq/gzgzcn' => [ + 'name' => '', + 'path' => '/yrt/cq/gzgzcn', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ohunzib' => [ + 'name' => '', + 'path' => '/ohunzib', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /rnevuk/fxq' => [ + 'name' => '', + 'path' => '/rnevuk/fxq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /tksmgqh' => [ + 'name' => '', + 'path' => '/tksmgqh', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /veytgylrkjt' => [ + 'name' => '', + 'path' => '/veytgylrkjt', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /user/ojiudhvuqmbanvwkek' => [ + 'name' => '', + 'path' => '/user/ojiudhvuqmbanvwkek', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/iybxsb' => [ + 'name' => '', + 'path' => '/goods/iybxsb', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /v/obkgpvyq/gq/sgf/dh/agv/l' => [ + 'name' => '', + 'path' => '/v/obkgpvyq/gq/sgf/dh/agv/l', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/yefwyt' => [ + 'name' => '', + 'path' => '/api/yefwyt', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ufpimae' => [ + 'name' => '', + 'path' => '/ufpimae', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/tqelbx' => [ + 'name' => '', + 'path' => '/user/tqelbx', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /api/cufxor' => [ + 'name' => '', + 'path' => '/api/cufxor', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /twinzaoshipuljvjevj' => [ + 'name' => '', + 'path' => '/twinzaoshipuljvjevj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /uavauvleht' => [ + 'name' => '', + 'path' => '/uavauvleht', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /v/dch/idl/ln/esbe' => [ + 'name' => '', + 'path' => '/v/dch/idl/ln/esbe', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /xlvbi/ps/j/jc/zhk' => [ + 'name' => '', + 'path' => '/xlvbi/ps/j/jc/zhk', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /wwacyspapmp' => [ + 'name' => '', + 'path' => '/wwacyspapmp', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ohifjlubnfaqgr/glintd' => [ + 'name' => '', + 'path' => '/ohifjlubnfaqgr/glintd', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v/g/mklddjl/tf' => [ + 'name' => '', + 'path' => '/v/g/mklddjl/tf', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /cnuawxaf/okodv/s' => [ + 'name' => '', + 'path' => '/cnuawxaf/okodv/s', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ev/nnynql/cnllw/vktyqzc' => [ + 'name' => '', + 'path' => '/ev/nnynql/cnllw/vktyqzc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ljdntlgbr' => [ + 'name' => '', + 'path' => '/ljdntlgbr', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /kveethxc/njzd/xggx' => [ + 'name' => '', + 'path' => '/kveethxc/njzd/xggx', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /vt/txkidnptrs/my' => [ + 'name' => '', + 'path' => '/vt/txkidnptrs/my', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /c/jllwqswklupj/jqtkb/p/e' => [ + 'name' => '', + 'path' => '/c/jllwqswklupj/jqtkb/p/e', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /t/xaxsdlse/m' => [ + 'name' => '', + 'path' => '/t/xaxsdlse/m', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /djl/sbrtukev/fgfqjwpe' => [ + 'name' => '', + 'path' => '/djl/sbrtukev/fgfqjwpe', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /smgocb/tzxvp' => [ + 'name' => '', + 'path' => '/smgocb/tzxvp', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /v2/txgmnxngeptuyvwwno' => [ + 'name' => '', + 'path' => '/v2/txgmnxngeptuyvwwno', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /ktlspeycsksiljcwaey' => [ + 'name' => '', + 'path' => '/ktlspeycsksiljcwaey', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /feqcaaxhejw' => [ + 'name' => '', + 'path' => '/feqcaaxhejw', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /xdyfjeft/g/lf' => [ + 'name' => '', + 'path' => '/xdyfjeft/g/lf', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /api/fvjixk' => [ + 'name' => '', + 'path' => '/api/fvjixk', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /h/lit/uylpzto' => [ + 'name' => '', + 'path' => '/h/lit/uylpzto', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /itbesk/leax' => [ + 'name' => '', + 'path' => '/itbesk/leax', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /yheprqnczk/tdg/' => [ + 'name' => '', + 'path' => '/yheprqnczk/tdg/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /msyhnto/' => [ + 'name' => '', + 'path' => '/msyhnto/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /xdejnla' => [ + 'name' => '', + 'path' => '/xdejnla', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /tqmzchvmklwb/k' => [ + 'name' => '', + 'path' => '/tqmzchvmklwb/k', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /cogdmvjmt/h/nvvwqy' => [ + 'name' => '', + 'path' => '/cogdmvjmt/h/nvvwqy', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /user/rabwjzmxcwvftyvdul' => [ + 'name' => '', + 'path' => '/user/rabwjzmxcwvftyvdul', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ysfjzff' => [ + 'name' => '', + 'path' => '/ysfjzff', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /xmf/wh/idd/l/ejmvvgdlojj' => [ + 'name' => '', + 'path' => '/xmf/wh/idd/l/ejmvvgdlojj', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /hplxhstclfzyvn/wb/mjm' => [ + 'name' => '', + 'path' => '/hplxhstclfzyvn/wb/mjm', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /qc/noo/kxyolv' => [ + 'name' => '', + 'path' => '/qc/noo/kxyolv', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /v2/upraviusoxrpqsb' => [ + 'name' => '', + 'path' => '/v2/upraviusoxrpqsb', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /qhlrjnuc/' => [ + 'name' => '', + 'path' => '/qhlrjnuc/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /tkmawhwgxv/l/f/ndqo/y' => [ + 'name' => '', + 'path' => '/tkmawhwgxv/l/f/ndqo/y', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/vbnats' => [ + 'name' => '', + 'path' => '/goods/vbnats', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /wo/in/xfd/zfco/xic/cqjhr' => [ + 'name' => '', + 'path' => '/wo/in/xfd/zfco/xic/cqjhr', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /api/cacwyr' => [ + 'name' => '', + 'path' => '/api/cacwyr', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /s/wndawyqymw' => [ + 'name' => '', + 'path' => '/s/wndawyqymw', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /twtp/jke' => [ + 'name' => '', + 'path' => '/twtp/jke', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /dhcmz/gzloukyq/w/btihxa' => [ + 'name' => '', + 'path' => '/dhcmz/gzloukyq/w/btihxa', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /axdf/osdgcoj' => [ + 'name' => '', + 'path' => '/axdf/osdgcoj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /z/rqlmjkct/' => [ + 'name' => '', + 'path' => '/z/rqlmjkct/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /fz/qfpi/y/lnx/ocieov' => [ + 'name' => '', + 'path' => '/fz/qfpi/y/lnx/ocieov', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /unmghaiabjiofhgklx/c/w' => [ + 'name' => '', + 'path' => '/unmghaiabjiofhgklx/c/w', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /rpagiy/ehqr' => [ + 'name' => '', + 'path' => '/rpagiy/ehqr', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /v2/mmgwfwmxwgbcrsq' => [ + 'name' => '', + 'path' => '/v2/mmgwfwmxwgbcrsq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /tdlgfnjou' => [ + 'name' => '', + 'path' => '/tdlgfnjou', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /nwgzub/x' => [ + 'name' => '', + 'path' => '/nwgzub/x', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/lmpiihzracbs' => [ + 'name' => '', + 'path' => '/goods/lmpiihzracbs', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /bbpqqqoir' => [ + 'name' => '', + 'path' => '/bbpqqqoir', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /xiuioanvo/cesb' => [ + 'name' => '', + 'path' => '/xiuioanvo/cesb', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/zwzuvksjdhjfikt' => [ + 'name' => '', + 'path' => '/api/zwzuvksjdhjfikt', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /ter/dhsa/llcayss' => [ + 'name' => '', + 'path' => '/ter/dhsa/llcayss', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/twowxy' => [ + 'name' => '', + 'path' => '/user/twowxy', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /rxxb/b/vjjmin' => [ + 'name' => '', + 'path' => '/rxxb/b/vjjmin', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /qinxtmpkecrp/j/t' => [ + 'name' => '', + 'path' => '/qinxtmpkecrp/j/t', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /v/uancplqhio' => [ + 'name' => '', + 'path' => '/v/uancplqhio', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /e/n/qrxfybzrfbk' => [ + 'name' => '', + 'path' => '/e/n/qrxfybzrfbk', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /lpbyauwero/lwe' => [ + 'name' => '', + 'path' => '/lpbyauwero/lwe', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /api/zbhrkk' => [ + 'name' => '', + 'path' => '/api/zbhrkk', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /h/jzvfwsmxelhmob/azoi' => [ + 'name' => '', + 'path' => '/h/jzvfwsmxelhmob/azoi', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /v2/jbjhbs' => [ + 'name' => '', + 'path' => '/v2/jbjhbs', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /atyxd/eanyt' => [ + 'name' => '', + 'path' => '/atyxd/eanyt', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /nixyjr/gqnhsqhrep' => [ + 'name' => '', + 'path' => '/nixyjr/gqnhsqhrep', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /v2/wbnfkm' => [ + 'name' => '', + 'path' => '/v2/wbnfkm', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /jzjaxrqh/' => [ + 'name' => '', + 'path' => '/jzjaxrqh/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /cb/oprxoes' => [ + 'name' => '', + 'path' => '/cb/oprxoes', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /user/joiqbi' => [ + 'name' => '', + 'path' => '/user/joiqbi', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /jcr/tagvxzn' => [ + 'name' => '', + 'path' => '/jcr/tagvxzn', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /bcqaocs/n/' => [ + 'name' => '', + 'path' => '/bcqaocs/n/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /vpluonodjbmuti/sde/' => [ + 'name' => '', + 'path' => '/vpluonodjbmuti/sde/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /goods/sdtzweyrhhec' => [ + 'name' => '', + 'path' => '/goods/sdtzweyrhhec', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /glaaavrztmmozqz/fzji' => [ + 'name' => '', + 'path' => '/glaaavrztmmozqz/fzji', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /pr/wbr/' => [ + 'name' => '', + 'path' => '/pr/wbr/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /mpwvqegi/o/rohtzg/x/' => [ + 'name' => '', + 'path' => '/mpwvqegi/o/rohtzg/x/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/iebgufwfffbt' => [ + 'name' => '', + 'path' => '/api/iebgufwfffbt', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /blknvhxi' => [ + 'name' => '', + 'path' => '/blknvhxi', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /crlt/hapd' => [ + 'name' => '', + 'path' => '/crlt/hapd', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /piy/fixz' => [ + 'name' => '', + 'path' => '/piy/fixz', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /esjqy/pqkqxuxsgu/abc/u' => [ + 'name' => '', + 'path' => '/esjqy/pqkqxuxsgu/abc/u', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ylakyuyafq/chbx' => [ + 'name' => '', + 'path' => '/ylakyuyafq/chbx', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/uuqcjrpvfcmyzoe' => [ + 'name' => '', + 'path' => '/v2/uuqcjrpvfcmyzoe', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /goods/xehrwhlbaopr' => [ + 'name' => '', + 'path' => '/goods/xehrwhlbaopr', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /luxujm/jj/rtbftakcd' => [ + 'name' => '', + 'path' => '/luxujm/jj/rtbftakcd', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /dxdklygwk' => [ + 'name' => '', + 'path' => '/dxdklygwk', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /lcgphyoc' => [ + 'name' => '', + 'path' => '/lcgphyoc', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /sa/xffocy/mu/lweudsd/yf' => [ + 'name' => '', + 'path' => '/sa/xffocy/mu/lweudsd/yf', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /rbxix/xfqjh' => [ + 'name' => '', + 'path' => '/rbxix/xfqjh', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /jhikwrrla' => [ + 'name' => '', + 'path' => '/jhikwrrla', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /neojabgrf/' => [ + 'name' => '', + 'path' => '/neojabgrf/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/ukgjhxfjhnuspuomum' => [ + 'name' => '', + 'path' => '/user/ukgjhxfjhnuspuomum', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /xwkomj/nbr' => [ + 'name' => '', + 'path' => '/xwkomj/nbr', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /mhzogdoxymlg/pyavyo/mi' => [ + 'name' => '', + 'path' => '/mhzogdoxymlg/pyavyo/mi', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/eqmpzsfcsjpbdvs' => [ + 'name' => '', + 'path' => '/v2/eqmpzsfcsjpbdvs', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /fheaya/ugeengsa/mp' => [ + 'name' => '', + 'path' => '/fheaya/ugeengsa/mp', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/thxllneirhvnlrj' => [ + 'name' => '', + 'path' => '/api/thxllneirhvnlrj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /diipmxhddag' => [ + 'name' => '', + 'path' => '/diipmxhddag', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /odj/vihv/lu/rt/jqqudest' => [ + 'name' => '', + 'path' => '/odj/vihv/lu/rt/jqqudest', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /xeixj/tbseufgwh/qfrp/j/' => [ + 'name' => '', + 'path' => '/xeixj/tbseufgwh/qfrp/j/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /m/wfgjvigyobhrj' => [ + 'name' => '', + 'path' => '/m/wfgjvigyobhrj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /zagh/dl/x/cvq' => [ + 'name' => '', + 'path' => '/zagh/dl/x/cvq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /ovc/geebze' => [ + 'name' => '', + 'path' => '/ovc/geebze', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /v2/gzfmbacuhclnpeo' => [ + 'name' => '', + 'path' => '/v2/gzfmbacuhclnpeo', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ata/ayiynrnmjlae/z/dy/e' => [ + 'name' => '', + 'path' => '/ata/ayiynrnmjlae/z/dy/e', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /u/lqrfteyw/' => [ + 'name' => '', + 'path' => '/u/lqrfteyw/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /eb/s/bnzbvgsgltzdr/g' => [ + 'name' => '', + 'path' => '/eb/s/bnzbvgsgltzdr/g', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /pinqfgkrjzkxza/h/utlnj' => [ + 'name' => '', + 'path' => '/pinqfgkrjzkxza/h/utlnj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /ctcmxmkgy' => [ + 'name' => '', + 'path' => '/ctcmxmkgy', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /lfqudob' => [ + 'name' => '', + 'path' => '/lfqudob', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /user/gsgsmrvzupcbilscco' => [ + 'name' => '', + 'path' => '/user/gsgsmrvzupcbilscco', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /t/tknquh' => [ + 'name' => '', + 'path' => '/t/tknquh', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/tmksgc' => [ + 'name' => '', + 'path' => '/api/tmksgc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /wmaw/l/tjcsq/sphowf' => [ + 'name' => '', + 'path' => '/wmaw/l/tjcsq/sphowf', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /wplh/tczfw/gnck/kqge/ejg' => [ + 'name' => '', + 'path' => '/wplh/tczfw/gnck/kqge/ejg', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /snhxsv/j/zuehgu' => [ + 'name' => '', + 'path' => '/snhxsv/j/zuehgu', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /k/h/ynhokfafup/a' => [ + 'name' => '', + 'path' => '/k/h/ynhokfafup/a', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /xbqmcr/a' => [ + 'name' => '', + 'path' => '/xbqmcr/a', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /om/c/qgxcwbnmqx' => [ + 'name' => '', + 'path' => '/om/c/qgxcwbnmqx', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /api/wvaxjyilienvooicwj' => [ + 'name' => '', + 'path' => '/api/wvaxjyilienvooicwj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /wwdlmpjbtletqi' => [ + 'name' => '', + 'path' => '/wwdlmpjbtletqi', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /user/aznvlxmdbzwqexv' => [ + 'name' => '', + 'path' => '/user/aznvlxmdbzwqexv', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /dmqezta' => [ + 'name' => '', + 'path' => '/dmqezta', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /rf/mkdtmja/jljofamz/xs' => [ + 'name' => '', + 'path' => '/rf/mkdtmja/jljofamz/xs', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /spjxt/ev/jcr' => [ + 'name' => '', + 'path' => '/spjxt/ev/jcr', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /b/fgy/us/trzfw/ebqowfuw' => [ + 'name' => '', + 'path' => '/b/fgy/us/trzfw/ebqowfuw', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /cdyoafpbhapsah' => [ + 'name' => '', + 'path' => '/cdyoafpbhapsah', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /mbxa/a' => [ + 'name' => '', + 'path' => '/mbxa/a', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /nhcdrcfxybjmrfup/xnog' => [ + 'name' => '', + 'path' => '/nhcdrcfxybjmrfup/xnog', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /api/jsxcte' => [ + 'name' => '', + 'path' => '/api/jsxcte', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/mfcrdnvxldecudgfcd' => [ + 'name' => '', + 'path' => '/v2/mfcrdnvxldecudgfcd', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /rj/jlkfx/wqoo/l/vaf/gv' => [ + 'name' => '', + 'path' => '/rj/jlkfx/wqoo/l/vaf/gv', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /v2/bufdljmbxxbqnae' => [ + 'name' => '', + 'path' => '/v2/bufdljmbxxbqnae', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /ez/oayskuugzvvc/wm/u/ds/k' => [ + 'name' => '', + 'path' => '/ez/oayskuugzvvc/wm/u/ds/k', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /jvww/dsltmkhyi/j/' => [ + 'name' => '', + 'path' => '/jvww/dsltmkhyi/j/', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /b/ekvieft' => [ + 'name' => '', + 'path' => '/b/ekvieft', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /user/znovbcflzqindxi' => [ + 'name' => '', + 'path' => '/user/znovbcflzqindxi', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /goods/ybnmwf' => [ + 'name' => '', + 'path' => '/goods/ybnmwf', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /z/wt/cvnvsa' => [ + 'name' => '', + 'path' => '/z/wt/cvnvsa', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /t/nbljwentimq/f' => [ + 'name' => '', + 'path' => '/t/nbljwentimq/f', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /j/shp/migfj' => [ + 'name' => '', + 'path' => '/j/shp/migfj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/yqoyto' => [ + 'name' => '', + 'path' => '/goods/yqoyto', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /byybl/' => [ + 'name' => '', + 'path' => '/byybl/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /z/hnhkzxk/iqgrz/tvzyvi' => [ + 'name' => '', + 'path' => '/z/hnhkzxk/iqgrz/tvzyvi', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /o/lm/vkuwtbr/bvjqz/arbhs' => [ + 'name' => '', + 'path' => '/o/lm/vkuwtbr/bvjqz/arbhs', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /pj/zeagytasvyxz/vw' => [ + 'name' => '', + 'path' => '/pj/zeagytasvyxz/vw', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /wzrscys' => [ + 'name' => '', + 'path' => '/wzrscys', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /he/f/ffqlmvi/vdyeryf' => [ + 'name' => '', + 'path' => '/he/f/ffqlmvi/vdyeryf', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /elvkv/lg/lbk/ryq/nctk' => [ + 'name' => '', + 'path' => '/elvkv/lg/lbk/ryq/nctk', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /chluakwwi' => [ + 'name' => '', + 'path' => '/chluakwwi', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /ri/wd/zwyr' => [ + 'name' => '', + 'path' => '/ri/wd/zwyr', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /f/wxlakx/nkkvtz/a/scxun' => [ + 'name' => '', + 'path' => '/f/wxlakx/nkkvtz/a/scxun', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /v2/xqzpngupqumi' => [ + 'name' => '', + 'path' => '/v2/xqzpngupqumi', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ppdltfl' => [ + 'name' => '', + 'path' => '/ppdltfl', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /fzw/sfvlxq' => [ + 'name' => '', + 'path' => '/fzw/sfvlxq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /api/nuypogeejobl' => [ + 'name' => '', + 'path' => '/api/nuypogeejobl', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/zlrwnwinbxdj' => [ + 'name' => '', + 'path' => '/v2/zlrwnwinbxdj', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /hjbojeughxofxa/watym' => [ + 'name' => '', + 'path' => '/hjbojeughxofxa/watym', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /nfwvtfbmvbhvotoqe' => [ + 'name' => '', + 'path' => '/nfwvtfbmvbhvotoqe', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /v2/fafovb' => [ + 'name' => '', + 'path' => '/v2/fafovb', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /goods/nhfvjanxmxcozyl' => [ + 'name' => '', + 'path' => '/goods/nhfvjanxmxcozyl', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /bxrlzjoocl' => [ + 'name' => '', + 'path' => '/bxrlzjoocl', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /a/onwjosnbnjllcmyeut' => [ + 'name' => '', + 'path' => '/a/onwjosnbnjllcmyeut', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /jvoeudlzdmrdx' => [ + 'name' => '', + 'path' => '/jvoeudlzdmrdx', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /e/aqdbbma/svl/' => [ + 'name' => '', + 'path' => '/e/aqdbbma/svl/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /maufxhpiw' => [ + 'name' => '', + 'path' => '/maufxhpiw', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /goods/ftvdtwitpxptcecldu' => [ + 'name' => '', + 'path' => '/goods/ftvdtwitpxptcecldu', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /user/wuiplv' => [ + 'name' => '', + 'path' => '/user/wuiplv', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /yvnyrnzdf' => [ + 'name' => '', + 'path' => '/yvnyrnzdf', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /goods/ngggtwrwindvinn' => [ + 'name' => '', + 'path' => '/goods/ngggtwrwindvinn', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /q/erbckr/l/' => [ + 'name' => '', + 'path' => '/q/erbckr/l/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /api/kfhhsdecbhvrcbw' => [ + 'name' => '', + 'path' => '/api/kfhhsdecbhvrcbw', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /fyzoqwwwqeu/' => [ + 'name' => '', + 'path' => '/fyzoqwwwqeu/', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /d/zuvagkzmpl' => [ + 'name' => '', + 'path' => '/d/zuvagkzmpl', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /rouktba' => [ + 'name' => '', + 'path' => '/rouktba', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /mmctkfhqlpm/lbcapf' => [ + 'name' => '', + 'path' => '/mmctkfhqlpm/lbcapf', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /u/u/t/yltzdfcs/z/hpk/z/' => [ + 'name' => '', + 'path' => '/u/u/t/yltzdfcs/z/hpk/z/', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /eo/vs/yuegh' => [ + 'name' => '', + 'path' => '/eo/vs/yuegh', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /api/jpgurhmbcimi' => [ + 'name' => '', + 'path' => '/api/jpgurhmbcimi', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /vrqmstssa/zd' => [ + 'name' => '', + 'path' => '/vrqmstssa/zd', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /svxvm' => [ + 'name' => '', + 'path' => '/svxvm', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /cl/uqoid' => [ + 'name' => '', + 'path' => '/cl/uqoid', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /huuchba/gn/hqfi' => [ + 'name' => '', + 'path' => '/huuchba/gn/hqfi', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /kcsystfifmwosetvkif' => [ + 'name' => '', + 'path' => '/kcsystfifmwosetvkif', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /f/jumru/qj' => [ + 'name' => '', + 'path' => '/f/jumru/qj', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/kepyogvunojtxzc' => [ + 'name' => '', + 'path' => '/goods/kepyogvunojtxzc', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /miaumxsx' => [ + 'name' => '', + 'path' => '/miaumxsx', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /ezpruhlobrb/lanvv' => [ + 'name' => '', + 'path' => '/ezpruhlobrb/lanvv', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /api/xcbjpg' => [ + 'name' => '', + 'path' => '/api/xcbjpg', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /v2/cxcpgpygjvccmojegt' => [ + 'name' => '', + 'path' => '/v2/cxcpgpygjvccmojegt', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /irnjhhayds/quemph' => [ + 'name' => '', + 'path' => '/irnjhhayds/quemph', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /pygal/c/ha/ocfmd/ytfx' => [ + 'name' => '', + 'path' => '/pygal/c/ha/ocfmd/ytfx', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /itsuzkktpz' => [ + 'name' => '', + 'path' => '/itsuzkktpz', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /lq/j/op/xhlydfue' => [ + 'name' => '', + 'path' => '/lq/j/op/xhlydfue', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /t/hjjmwrynreha/' => [ + 'name' => '', + 'path' => '/t/hjjmwrynreha/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /goods/epjsiupvytkn' => [ + 'name' => '', + 'path' => '/goods/epjsiupvytkn', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /lld/uew/qmdxt/xmj/c/tz/' => [ + 'name' => '', + 'path' => '/lld/uew/qmdxt/xmj/c/tz/', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /wwfbonw/ypoflk' => [ + 'name' => '', + 'path' => '/wwfbonw/ypoflk', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /kaebhxo/viap' => [ + 'name' => '', + 'path' => '/kaebhxo/viap', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /rkp/ipsgmyff' => [ + 'name' => '', + 'path' => '/rkp/ipsgmyff', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/eizoxaklqflw' => [ + 'name' => '', + 'path' => '/goods/eizoxaklqflw', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /otcoflcnpns' => [ + 'name' => '', + 'path' => '/otcoflcnpns', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /wcxexwmz' => [ + 'name' => '', + 'path' => '/wcxexwmz', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /nffsxzfpbbz/muff/b/arb' => [ + 'name' => '', + 'path' => '/nffsxzfpbbz/muff/b/arb', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /vchl/subig/' => [ + 'name' => '', + 'path' => '/vchl/subig/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /bjvkqklnxohxz' => [ + 'name' => '', + 'path' => '/bjvkqklnxohxz', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /nifziogqj' => [ + 'name' => '', + 'path' => '/nifziogqj', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /user/agsgaq' => [ + 'name' => '', + 'path' => '/user/agsgaq', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /vqvbckr/pipzaozr/tbe/y' => [ + 'name' => '', + 'path' => '/vqvbckr/pipzaozr/tbe/y', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /user/ouvifcballqeemclmn' => [ + 'name' => '', + 'path' => '/user/ouvifcballqeemclmn', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PATCH /kg/x/ne/vstypenr' => [ + 'name' => '', + 'path' => '/kg/x/ne/vstypenr', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /goods/ljkhzl' => [ + 'name' => '', + 'path' => '/goods/ljkhzl', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'PUT /kdrddas/' => [ + 'name' => '', + 'path' => '/kdrddas/', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /jkvfezwndyey/anxbv' => [ + 'name' => '', + 'path' => '/jkvfezwndyey/anxbv', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /nqsfo/bk/j' => [ + 'name' => '', + 'path' => '/nqsfo/bk/j', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /ozs/calmk/ay' => [ + 'name' => '', + 'path' => '/ozs/calmk/ay', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'POST /fentih/srzcscb/bzeomh/v' => [ + 'name' => '', + 'path' => '/fentih/srzcscb/bzeomh/v', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'DELETE /bjyhbzwglsqpgmngg/xg' => [ + 'name' => '', + 'path' => '/bjyhbzwglsqpgmngg/xg', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], + 'GET /gzyeapeu' => [ + 'name' => '', + 'path' => '/gzyeapeu', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + ], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [ + ], + 'options' => [ + ], + ], +], +// regular routes +'regularRoutes' => [ + 'GET v2' => [ + 0 => [ + 'name' => '', + 'path' => '/v2/jwdhgwqeoyibhqf/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/jwdhgwqeoyibhqf/([^/]+)$#', + 'pathStart' => '/v2/jwdhgwqeoyibhqf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/v2/wojuqhiwqiopgqnjzs/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/wojuqhiwqiopgqnjzs/([^/]+)$#', + 'pathStart' => '/v2/wojuqhiwqiopgqnjzs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/v2/egeoztblyfan/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/egeoztblyfan/([^/]+)$#', + 'pathStart' => '/v2/egeoztblyfan/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/v2/opcllkfduwrczbwwaa/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/opcllkfduwrczbwwaa/([^/]+)$#', + 'pathStart' => '/v2/opcllkfduwrczbwwaa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/v2/zzlxwj/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/zzlxwj/([^/]+)$#', + 'pathStart' => '/v2/zzlxwj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/v2/iiokpjzwxddvfqa/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/iiokpjzwxddvfqa/([^/]+)$#', + 'pathStart' => '/v2/iiokpjzwxddvfqa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH nzmanetsxhgxx' => [ + 0 => [ + 'name' => '', + 'path' => '/nzmanetsxhgxx/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nzmanetsxhgxx/([^/]+)$#', + 'pathStart' => '/nzmanetsxhgxx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET 50be3774f6' => [ + 0 => [ + 'name' => '', + 'path' => '/50be3774f6/{arg1}/{arg2}/{arg3}/{arg4}/{arg5}/{arg6}/{arg7}/{arg8}/{arg9}/850726135a', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'arg1', + 1 => 'arg2', + 2 => 'arg3', + 3 => 'arg4', + 4 => 'arg5', + 5 => 'arg6', + 6 => 'arg7', + 7 => 'arg8', + 8 => 'arg9', + ], + 'pathRegex' => '#^/50be3774f6/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/850726135a$#', + 'pathStart' => '/50be3774f6/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET xyoz' => [ + 0 => [ + 'name' => '', + 'path' => '/xyoz/kgptpomrt/rm/w/r/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xyoz/kgptpomrt/rm/w/r/([^/]+)$#', + 'pathStart' => '/xyoz/kgptpomrt/rm/w/r/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET zdvdgdm' => [ + 0 => [ + 'name' => '', + 'path' => '/zdvdgdm/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zdvdgdm/([^/]+)$#', + 'pathStart' => '/zdvdgdm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH vs' => [ + 0 => [ + 'name' => '', + 'path' => '/vs/ssviv/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vs/ssviv/([^/]+)$#', + 'pathStart' => '/vs/ssviv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET xl' => [ + 0 => [ + 'name' => '', + 'path' => '/xl/bztzytrw/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xl/bztzytrw/([^/]+)$#', + 'pathStart' => '/xl/bztzytrw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET user' => [ + 0 => [ + 'name' => '', + 'path' => '/user/ibgqnl/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/ibgqnl/([^/]+)$#', + 'pathStart' => '/user/ibgqnl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/user/vjidfnxfaboxrcioxe/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/vjidfnxfaboxrcioxe/([^/]+)$#', + 'pathStart' => '/user/vjidfnxfaboxrcioxe/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/user/wublbbjzmrramokhju/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/wublbbjzmrramokhju/([^/]+)$#', + 'pathStart' => '/user/wublbbjzmrramokhju/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/user/dqjwzpazharz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/dqjwzpazharz/([^/]+)$#', + 'pathStart' => '/user/dqjwzpazharz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/user/neoweyrhursiayy/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/neoweyrhursiayy/([^/]+)$#', + 'pathStart' => '/user/neoweyrhursiayy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/user/qbtqin/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/qbtqin/([^/]+)$#', + 'pathStart' => '/user/qbtqin/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 6 => [ + 'name' => '', + 'path' => '/user/juashpjvfyllohvbyx/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/juashpjvfyllohvbyx/([^/]+)$#', + 'pathStart' => '/user/juashpjvfyllohvbyx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 7 => [ + 'name' => '', + 'path' => '/user/jqxgskgpvabqetjvsh/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/jqxgskgpvabqetjvsh/([^/]+)$#', + 'pathStart' => '/user/jqxgskgpvabqetjvsh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 8 => [ + 'name' => '', + 'path' => '/user/ywgdkr/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/ywgdkr/([^/]+)$#', + 'pathStart' => '/user/ywgdkr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 9 => [ + 'name' => '', + 'path' => '/user/euvmcubsdjrtfqgevm/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/euvmcubsdjrtfqgevm/([^/]+)$#', + 'pathStart' => '/user/euvmcubsdjrtfqgevm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 10 => [ + 'name' => '', + 'path' => '/user/qbczljbzmkjc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/qbczljbzmkjc/([^/]+)$#', + 'pathStart' => '/user/qbczljbzmkjc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 11 => [ + 'name' => '', + 'path' => '/user/zkfjdjzowklk/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/zkfjdjzowklk/([^/]+)$#', + 'pathStart' => '/user/zkfjdjzowklk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 12 => [ + 'name' => '', + 'path' => '/user/vovgloratoop/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/vovgloratoop/([^/]+)$#', + 'pathStart' => '/user/vovgloratoop/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 13 => [ + 'name' => '', + 'path' => '/user/yybyag/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/yybyag/([^/]+)$#', + 'pathStart' => '/user/yybyag/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 14 => [ + 'name' => '', + 'path' => '/user/spfbldkgvcvhdflomx/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/spfbldkgvcvhdflomx/([^/]+)$#', + 'pathStart' => '/user/spfbldkgvcvhdflomx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 15 => [ + 'name' => '', + 'path' => '/user/xrudzaqroasuetjjfg/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/xrudzaqroasuetjjfg/([^/]+)$#', + 'pathStart' => '/user/xrudzaqroasuetjjfg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE api' => [ + 0 => [ + 'name' => '', + 'path' => '/api/kuokxtsrnujy/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/kuokxtsrnujy/([^/]+)$#', + 'pathStart' => '/api/kuokxtsrnujy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/api/qyetovfaonkb/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/qyetovfaonkb/([^/]+)$#', + 'pathStart' => '/api/qyetovfaonkb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/api/pfafetchcnye/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/pfafetchcnye/([^/]+)$#', + 'pathStart' => '/api/pfafetchcnye/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/api/ansxml/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ansxml/([^/]+)$#', + 'pathStart' => '/api/ansxml/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/api/ztqwwjswvomizgz/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ztqwwjswvomizgz/([^/]+)$#', + 'pathStart' => '/api/ztqwwjswvomizgz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/api/ysemxy/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ysemxy/([^/]+)$#', + 'pathStart' => '/api/ysemxy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 6 => [ + 'name' => '', + 'path' => '/api/jmtreeiwygxdgmrlnt/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/jmtreeiwygxdgmrlnt/([^/]+)$#', + 'pathStart' => '/api/jmtreeiwygxdgmrlnt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 7 => [ + 'name' => '', + 'path' => '/api/jqbaiwmronqenyspvz/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/jqbaiwmronqenyspvz/([^/]+)$#', + 'pathStart' => '/api/jqbaiwmronqenyspvz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE xksdhqj' => [ + 0 => [ + 'name' => '', + 'path' => '/xksdhqj/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xksdhqj/([^/]+)$#', + 'pathStart' => '/xksdhqj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET zvu' => [ + 0 => [ + 'name' => '', + 'path' => '/zvu/mq/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zvu/mq/([^/]+)$#', + 'pathStart' => '/zvu/mq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT cfroxw' => [ + 0 => [ + 'name' => '', + 'path' => '/cfroxw/oir/txa/dgb/u/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cfroxw/oir/txa/dgb/u/([^/]+)$#', + 'pathStart' => '/cfroxw/oir/txa/dgb/u/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET eaqfxpc' => [ + 0 => [ + 'name' => '', + 'path' => '/eaqfxpc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/eaqfxpc/([^/]+)$#', + 'pathStart' => '/eaqfxpc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET r' => [ + 0 => [ + 'name' => '', + 'path' => '/r/kutlhmpstztwmituwl/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/r/kutlhmpstztwmituwl/([^/]+)$#', + 'pathStart' => '/r/kutlhmpstztwmituwl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/r/oofdopp/erbc/stdq/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/r/oofdopp/erbc/stdq/([^/]+)$#', + 'pathStart' => '/r/oofdopp/erbc/stdq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST ywxlupg' => [ + 0 => [ + 'name' => '', + 'path' => '/ywxlupg/eteppq/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ywxlupg/eteppq/([^/]+)$#', + 'pathStart' => '/ywxlupg/eteppq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST uvd' => [ + 0 => [ + 'name' => '', + 'path' => '/uvd/eqfuw/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/uvd/eqfuw/([^/]+)$#', + 'pathStart' => '/uvd/eqfuw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST nyevfudb' => [ + 0 => [ + 'name' => '', + 'path' => '/nyevfudb/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nyevfudb/([^/]+)$#', + 'pathStart' => '/nyevfudb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE bifgtdezjoo' => [ + 0 => [ + 'name' => '', + 'path' => '/bifgtdezjoo/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/bifgtdezjoo/([^/]+)$#', + 'pathStart' => '/bifgtdezjoo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH iuyqrf' => [ + 0 => [ + 'name' => '', + 'path' => '/iuyqrf/si/mhhmckyzs/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/iuyqrf/si/mhhmckyzs/([^/]+)$#', + 'pathStart' => '/iuyqrf/si/mhhmckyzs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT rrqoq' => [ + 0 => [ + 'name' => '', + 'path' => '/rrqoq/pfuszagqcgks/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rrqoq/pfuszagqcgks/([^/]+)$#', + 'pathStart' => '/rrqoq/pfuszagqcgks/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST ryhdmlp' => [ + 0 => [ + 'name' => '', + 'path' => '/ryhdmlp/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ryhdmlp/([^/]+)$#', + 'pathStart' => '/ryhdmlp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH kenusrw' => [ + 0 => [ + 'name' => '', + 'path' => '/kenusrw/nt/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/kenusrw/nt/([^/]+)$#', + 'pathStart' => '/kenusrw/nt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT vrxlnp' => [ + 0 => [ + 'name' => '', + 'path' => '/vrxlnp/limzvc/niht/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vrxlnp/limzvc/niht/([^/]+)$#', + 'pathStart' => '/vrxlnp/limzvc/niht/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET zevzkd' => [ + 0 => [ + 'name' => '', + 'path' => '/zevzkd/g/obcinwkxmyon/g/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zevzkd/g/obcinwkxmyon/g/([^/]+)$#', + 'pathStart' => '/zevzkd/g/obcinwkxmyon/g/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH v2' => [ + 0 => [ + 'name' => '', + 'path' => '/v2/rvphhlrbsrupumeoqd/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/rvphhlrbsrupumeoqd/([^/]+)$#', + 'pathStart' => '/v2/rvphhlrbsrupumeoqd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/v2/mgpukbxuqpcn/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/mgpukbxuqpcn/([^/]+)$#', + 'pathStart' => '/v2/mgpukbxuqpcn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/v2/ikkymmntgftktilgmb/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/ikkymmntgftktilgmb/([^/]+)$#', + 'pathStart' => '/v2/ikkymmntgftktilgmb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE rvwzffmj' => [ + 0 => [ + 'name' => '', + 'path' => '/rvwzffmj/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rvwzffmj/([^/]+)$#', + 'pathStart' => '/rvwzffmj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST goods' => [ + 0 => [ + 'name' => '', + 'path' => '/goods/sirvjm/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/sirvjm/([^/]+)$#', + 'pathStart' => '/goods/sirvjm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/goods/hkgrfjyxzvoa/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/hkgrfjyxzvoa/([^/]+)$#', + 'pathStart' => '/goods/hkgrfjyxzvoa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/goods/pbmntl/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/pbmntl/([^/]+)$#', + 'pathStart' => '/goods/pbmntl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/goods/ekpxypnvazyoccj/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/ekpxypnvazyoccj/([^/]+)$#', + 'pathStart' => '/goods/ekpxypnvazyoccj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/goods/tbhatnhrrwuboqfhqe/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/tbhatnhrrwuboqfhqe/([^/]+)$#', + 'pathStart' => '/goods/tbhatnhrrwuboqfhqe/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/goods/haqwrarcupmu/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/haqwrarcupmu/([^/]+)$#', + 'pathStart' => '/goods/haqwrarcupmu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 6 => [ + 'name' => '', + 'path' => '/goods/fqfsoz/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/fqfsoz/([^/]+)$#', + 'pathStart' => '/goods/fqfsoz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 7 => [ + 'name' => '', + 'path' => '/goods/iuzevn/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/iuzevn/([^/]+)$#', + 'pathStart' => '/goods/iuzevn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 8 => [ + 'name' => '', + 'path' => '/goods/eowkeuikpdakomb/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/eowkeuikpdakomb/([^/]+)$#', + 'pathStart' => '/goods/eowkeuikpdakomb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE lrwnkoj' => [ + 0 => [ + 'name' => '', + 'path' => '/lrwnkoj/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lrwnkoj/([^/]+)$#', + 'pathStart' => '/lrwnkoj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE p' => [ + 0 => [ + 'name' => '', + 'path' => '/p/dvyfziwuxgnffi/lqnf/i/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/p/dvyfziwuxgnffi/lqnf/i/([^/]+)$#', + 'pathStart' => '/p/dvyfziwuxgnffi/lqnf/i/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH cagctzzr' => [ + 0 => [ + 'name' => '', + 'path' => '/cagctzzr/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cagctzzr/([^/]+)$#', + 'pathStart' => '/cagctzzr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE mucccchbjoqdpwus' => [ + 0 => [ + 'name' => '', + 'path' => '/mucccchbjoqdpwus/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mucccchbjoqdpwus/([^/]+)$#', + 'pathStart' => '/mucccchbjoqdpwus/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST mnwxpthaxrlq' => [ + 0 => [ + 'name' => '', + 'path' => '/mnwxpthaxrlq/ipp/c/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mnwxpthaxrlq/ipp/c/([^/]+)$#', + 'pathStart' => '/mnwxpthaxrlq/ipp/c/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET qhsgc' => [ + 0 => [ + 'name' => '', + 'path' => '/qhsgc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qhsgc/([^/]+)$#', + 'pathStart' => '/qhsgc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH user' => [ + 0 => [ + 'name' => '', + 'path' => '/user/adgsqqfhyzikqlh/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/adgsqqfhyzikqlh/([^/]+)$#', + 'pathStart' => '/user/adgsqqfhyzikqlh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/user/dqgogt/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/dqgogt/([^/]+)$#', + 'pathStart' => '/user/dqgogt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH qu' => [ + 0 => [ + 'name' => '', + 'path' => '/qu/nquenyl/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qu/nquenyl/([^/]+)$#', + 'pathStart' => '/qu/nquenyl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE hbxqxzbup' => [ + 0 => [ + 'name' => '', + 'path' => '/hbxqxzbup/t/rlvdy/juubv/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hbxqxzbup/t/rlvdy/juubv/([^/]+)$#', + 'pathStart' => '/hbxqxzbup/t/rlvdy/juubv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET gldk' => [ + 0 => [ + 'name' => '', + 'path' => '/gldk/xunysimvrksoror/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gldk/xunysimvrksoror/([^/]+)$#', + 'pathStart' => '/gldk/xunysimvrksoror/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET kb' => [ + 0 => [ + 'name' => '', + 'path' => '/kb/goj/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/kb/goj/([^/]+)$#', + 'pathStart' => '/kb/goj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST user' => [ + 0 => [ + 'name' => '', + 'path' => '/user/cbcdypebzjbcbaqwsb/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/cbcdypebzjbcbaqwsb/([^/]+)$#', + 'pathStart' => '/user/cbcdypebzjbcbaqwsb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/user/cxmziebgcwsh/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/cxmziebgcwsh/([^/]+)$#', + 'pathStart' => '/user/cxmziebgcwsh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/user/gurcyo/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/gurcyo/([^/]+)$#', + 'pathStart' => '/user/gurcyo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/user/limlbpqmfkjaryhqlp/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/limlbpqmfkjaryhqlp/([^/]+)$#', + 'pathStart' => '/user/limlbpqmfkjaryhqlp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/user/stneaxlzlasdjhs/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/stneaxlzlasdjhs/([^/]+)$#', + 'pathStart' => '/user/stneaxlzlasdjhs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE rrr' => [ + 0 => [ + 'name' => '', + 'path' => '/rrr/pmtazlzl/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rrr/pmtazlzl/([^/]+)$#', + 'pathStart' => '/rrr/pmtazlzl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH rnzvhowwyio' => [ + 0 => [ + 'name' => '', + 'path' => '/rnzvhowwyio/vhn/k/bf/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rnzvhowwyio/vhn/k/bf/([^/]+)$#', + 'pathStart' => '/rnzvhowwyio/vhn/k/bf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET jbugfsmfk' => [ + 0 => [ + 'name' => '', + 'path' => '/jbugfsmfk/io/oelcebja/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jbugfsmfk/io/oelcebja/([^/]+)$#', + 'pathStart' => '/jbugfsmfk/io/oelcebja/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST mjubidzijs' => [ + 0 => [ + 'name' => '', + 'path' => '/mjubidzijs/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mjubidzijs/([^/]+)$#', + 'pathStart' => '/mjubidzijs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH jinqg' => [ + 0 => [ + 'name' => '', + 'path' => '/jinqg/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jinqg/([^/]+)$#', + 'pathStart' => '/jinqg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT ivkltwepjehhktonbjqo' => [ + 0 => [ + 'name' => '', + 'path' => '/ivkltwepjehhktonbjqo/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ivkltwepjehhktonbjqo/([^/]+)$#', + 'pathStart' => '/ivkltwepjehhktonbjqo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET api' => [ + 0 => [ + 'name' => '', + 'path' => '/api/hhtbswtmekqaoaembo/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/hhtbswtmekqaoaembo/([^/]+)$#', + 'pathStart' => '/api/hhtbswtmekqaoaembo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/api/ajnecqyqxxdulti/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ajnecqyqxxdulti/([^/]+)$#', + 'pathStart' => '/api/ajnecqyqxxdulti/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/api/afjokehphcqasxc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/afjokehphcqasxc/([^/]+)$#', + 'pathStart' => '/api/afjokehphcqasxc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/api/aejcpe/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/aejcpe/([^/]+)$#', + 'pathStart' => '/api/aejcpe/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/api/bmkswmsbpgjy/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/bmkswmsbpgjy/([^/]+)$#', + 'pathStart' => '/api/bmkswmsbpgjy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/api/ywdyqupzbqzjjoi/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ywdyqupzbqzjjoi/([^/]+)$#', + 'pathStart' => '/api/ywdyqupzbqzjjoi/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH rsdglfaaafg' => [ + 0 => [ + 'name' => '', + 'path' => '/rsdglfaaafg/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rsdglfaaafg/([^/]+)$#', + 'pathStart' => '/rsdglfaaafg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST v2' => [ + 0 => [ + 'name' => '', + 'path' => '/v2/ufitpcyoxgwfplw/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/ufitpcyoxgwfplw/([^/]+)$#', + 'pathStart' => '/v2/ufitpcyoxgwfplw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/v2/acifcayvlqqlgktrnw/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/acifcayvlqqlgktrnw/([^/]+)$#', + 'pathStart' => '/v2/acifcayvlqqlgktrnw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/v2/zjkwhgfchpddiqw/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/zjkwhgfchpddiqw/([^/]+)$#', + 'pathStart' => '/v2/zjkwhgfchpddiqw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/v2/wkxsoxqaxhuj/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/wkxsoxqaxhuj/([^/]+)$#', + 'pathStart' => '/v2/wkxsoxqaxhuj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/v2/amsnsjxywjnnwbx/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/amsnsjxywjnnwbx/([^/]+)$#', + 'pathStart' => '/v2/amsnsjxywjnnwbx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST yeawilq' => [ + 0 => [ + 'name' => '', + 'path' => '/yeawilq/mu/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yeawilq/mu/([^/]+)$#', + 'pathStart' => '/yeawilq/mu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT kfyipgnz' => [ + 0 => [ + 'name' => '', + 'path' => '/kfyipgnz/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/kfyipgnz/([^/]+)$#', + 'pathStart' => '/kfyipgnz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE xbjfhsqcuxj' => [ + 0 => [ + 'name' => '', + 'path' => '/xbjfhsqcuxj/gsr/ffg/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xbjfhsqcuxj/gsr/ffg/([^/]+)$#', + 'pathStart' => '/xbjfhsqcuxj/gsr/ffg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET goods' => [ + 0 => [ + 'name' => '', + 'path' => '/goods/vpexjnlrguge/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/vpexjnlrguge/([^/]+)$#', + 'pathStart' => '/goods/vpexjnlrguge/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/goods/jrigtlbdbysglzu/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/jrigtlbdbysglzu/([^/]+)$#', + 'pathStart' => '/goods/jrigtlbdbysglzu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/goods/xeaopurmtxxz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/xeaopurmtxxz/([^/]+)$#', + 'pathStart' => '/goods/xeaopurmtxxz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/goods/qpcgwezakaht/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/qpcgwezakaht/([^/]+)$#', + 'pathStart' => '/goods/qpcgwezakaht/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/goods/abherarletpt/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/abherarletpt/([^/]+)$#', + 'pathStart' => '/goods/abherarletpt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/goods/raaxek/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/raaxek/([^/]+)$#', + 'pathStart' => '/goods/raaxek/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 6 => [ + 'name' => '', + 'path' => '/goods/kqdbgbwfmdhcznjseh/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/kqdbgbwfmdhcznjseh/([^/]+)$#', + 'pathStart' => '/goods/kqdbgbwfmdhcznjseh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 7 => [ + 'name' => '', + 'path' => '/goods/xhbiyysewnktosy/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/xhbiyysewnktosy/([^/]+)$#', + 'pathStart' => '/goods/xhbiyysewnktosy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT o' => [ + 0 => [ + 'name' => '', + 'path' => '/o/pvjt/ckragwe/hdyspwe/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/o/pvjt/ckragwe/hdyspwe/([^/]+)$#', + 'pathStart' => '/o/pvjt/ckragwe/hdyspwe/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH ljwc' => [ + 0 => [ + 'name' => '', + 'path' => '/ljwc/z/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ljwc/z/([^/]+)$#', + 'pathStart' => '/ljwc/z/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET bzfzf' => [ + 0 => [ + 'name' => '', + 'path' => '/bzfzf/jzg/o/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/bzfzf/jzg/o/([^/]+)$#', + 'pathStart' => '/bzfzf/jzg/o/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT vjvc' => [ + 0 => [ + 'name' => '', + 'path' => '/vjvc/xoo/cuhpcuweji/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vjvc/xoo/cuhpcuweji/([^/]+)$#', + 'pathStart' => '/vjvc/xoo/cuhpcuweji/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT zngre' => [ + 0 => [ + 'name' => '', + 'path' => '/zngre/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zngre/([^/]+)$#', + 'pathStart' => '/zngre/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE goods' => [ + 0 => [ + 'name' => '', + 'path' => '/goods/imkces/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/imkces/([^/]+)$#', + 'pathStart' => '/goods/imkces/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/goods/oelrtyxgwefvuzg/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/oelrtyxgwefvuzg/([^/]+)$#', + 'pathStart' => '/goods/oelrtyxgwefvuzg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/goods/osqons/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/osqons/([^/]+)$#', + 'pathStart' => '/goods/osqons/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/goods/kjgiclsljbskwydbvn/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/kjgiclsljbskwydbvn/([^/]+)$#', + 'pathStart' => '/goods/kjgiclsljbskwydbvn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/goods/eqxjkl/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/eqxjkl/([^/]+)$#', + 'pathStart' => '/goods/eqxjkl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/goods/qjzrijounjrk/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/qjzrijounjrk/([^/]+)$#', + 'pathStart' => '/goods/qjzrijounjrk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH etkqmslwcpdedqiidvrb' => [ + 0 => [ + 'name' => '', + 'path' => '/etkqmslwcpdedqiidvrb/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/etkqmslwcpdedqiidvrb/([^/]+)$#', + 'pathStart' => '/etkqmslwcpdedqiidvrb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE b' => [ + 0 => [ + 'name' => '', + 'path' => '/b/chhspufp/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/b/chhspufp/([^/]+)$#', + 'pathStart' => '/b/chhspufp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE ol' => [ + 0 => [ + 'name' => '', + 'path' => '/ol/b/ustst/daquantk/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ol/b/ustst/daquantk/([^/]+)$#', + 'pathStart' => '/ol/b/ustst/daquantk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET enyv' => [ + 0 => [ + 'name' => '', + 'path' => '/enyv/ciy/r/eh/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/enyv/ciy/r/eh/([^/]+)$#', + 'pathStart' => '/enyv/ciy/r/eh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET hgchyhso' => [ + 0 => [ + 'name' => '', + 'path' => '/hgchyhso/gjzsxcbat/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hgchyhso/gjzsxcbat/([^/]+)$#', + 'pathStart' => '/hgchyhso/gjzsxcbat/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE s' => [ + 0 => [ + 'name' => '', + 'path' => '/s/iwdlgngz/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/s/iwdlgngz/([^/]+)$#', + 'pathStart' => '/s/iwdlgngz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/s/i/gqmdc/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/s/i/gqmdc/([^/]+)$#', + 'pathStart' => '/s/i/gqmdc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT goods' => [ + 0 => [ + 'name' => '', + 'path' => '/goods/gqziwpumgulk/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/gqziwpumgulk/([^/]+)$#', + 'pathStart' => '/goods/gqziwpumgulk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/goods/lgrvsh/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/lgrvsh/([^/]+)$#', + 'pathStart' => '/goods/lgrvsh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/goods/zqabxawmathfowtidw/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/zqabxawmathfowtidw/([^/]+)$#', + 'pathStart' => '/goods/zqabxawmathfowtidw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/goods/ovrkenvubjvtxmowkr/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/ovrkenvubjvtxmowkr/([^/]+)$#', + 'pathStart' => '/goods/ovrkenvubjvtxmowkr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE mkjk' => [ + 0 => [ + 'name' => '', + 'path' => '/mkjk/l/kejsdqpzxquwfw/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mkjk/l/kejsdqpzxquwfw/([^/]+)$#', + 'pathStart' => '/mkjk/l/kejsdqpzxquwfw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET dmzjkgqmfus' => [ + 0 => [ + 'name' => '', + 'path' => '/dmzjkgqmfus/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dmzjkgqmfus/([^/]+)$#', + 'pathStart' => '/dmzjkgqmfus/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH goods' => [ + 0 => [ + 'name' => '', + 'path' => '/goods/ykptjyzwxzmymet/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/ykptjyzwxzmymet/([^/]+)$#', + 'pathStart' => '/goods/ykptjyzwxzmymet/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/goods/foiwgv/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/foiwgv/([^/]+)$#', + 'pathStart' => '/goods/foiwgv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/goods/issmvonoctpyxse/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/issmvonoctpyxse/([^/]+)$#', + 'pathStart' => '/goods/issmvonoctpyxse/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/goods/kjkqgt/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/kjkqgt/([^/]+)$#', + 'pathStart' => '/goods/kjkqgt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/goods/yzsoauuiwpda/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/goods/yzsoauuiwpda/([^/]+)$#', + 'pathStart' => '/goods/yzsoauuiwpda/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT h' => [ + 0 => [ + 'name' => '', + 'path' => '/h/cqpr/qhmangmez/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/h/cqpr/qhmangmez/([^/]+)$#', + 'pathStart' => '/h/cqpr/qhmangmez/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH yx' => [ + 0 => [ + 'name' => '', + 'path' => '/yx/uxvqmr/sni/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yx/uxvqmr/sni/([^/]+)$#', + 'pathStart' => '/yx/uxvqmr/sni/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT w' => [ + 0 => [ + 'name' => '', + 'path' => '/w/f/uxhqblwenx/jpbqa/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/w/f/uxhqblwenx/jpbqa/([^/]+)$#', + 'pathStart' => '/w/f/uxhqblwenx/jpbqa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH vxlv' => [ + 0 => [ + 'name' => '', + 'path' => '/vxlv/nfsfx/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vxlv/nfsfx/([^/]+)$#', + 'pathStart' => '/vxlv/nfsfx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET qreinhixdn' => [ + 0 => [ + 'name' => '', + 'path' => '/qreinhixdn/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qreinhixdn/([^/]+)$#', + 'pathStart' => '/qreinhixdn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT ivt' => [ + 0 => [ + 'name' => '', + 'path' => '/ivt/vpilezgslfa/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ivt/vpilezgslfa/([^/]+)$#', + 'pathStart' => '/ivt/vpilezgslfa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT vol' => [ + 0 => [ + 'name' => '', + 'path' => '/vol/eucn/emri/auhazevy/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vol/eucn/emri/auhazevy/([^/]+)$#', + 'pathStart' => '/vol/eucn/emri/auhazevy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST lsbfb' => [ + 0 => [ + 'name' => '', + 'path' => '/lsbfb/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lsbfb/([^/]+)$#', + 'pathStart' => '/lsbfb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET itzbsojxxzh' => [ + 0 => [ + 'name' => '', + 'path' => '/itzbsojxxzh/yrj/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/itzbsojxxzh/yrj/([^/]+)$#', + 'pathStart' => '/itzbsojxxzh/yrj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE m' => [ + 0 => [ + 'name' => '', + 'path' => '/m/nr/spcnhg/buxeo/grb/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/m/nr/spcnhg/buxeo/grb/([^/]+)$#', + 'pathStart' => '/m/nr/spcnhg/buxeo/grb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST gslttkcrwzzzkweqw' => [ + 0 => [ + 'name' => '', + 'path' => '/gslttkcrwzzzkweqw/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gslttkcrwzzzkweqw/([^/]+)$#', + 'pathStart' => '/gslttkcrwzzzkweqw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE mtsrffpodbhuw' => [ + 0 => [ + 'name' => '', + 'path' => '/mtsrffpodbhuw/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mtsrffpodbhuw/([^/]+)$#', + 'pathStart' => '/mtsrffpodbhuw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST qyslyez' => [ + 0 => [ + 'name' => '', + 'path' => '/qyslyez/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qyslyez/([^/]+)$#', + 'pathStart' => '/qyslyez/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE vephzsijtwl' => [ + 0 => [ + 'name' => '', + 'path' => '/vephzsijtwl/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vephzsijtwl/([^/]+)$#', + 'pathStart' => '/vephzsijtwl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT coafsgxdpbxal' => [ + 0 => [ + 'name' => '', + 'path' => '/coafsgxdpbxal/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/coafsgxdpbxal/([^/]+)$#', + 'pathStart' => '/coafsgxdpbxal/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT vfpbr' => [ + 0 => [ + 'name' => '', + 'path' => '/vfpbr/bsliuavokcct/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vfpbr/bsliuavokcct/([^/]+)$#', + 'pathStart' => '/vfpbr/bsliuavokcct/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE imri' => [ + 0 => [ + 'name' => '', + 'path' => '/imri/pt/ncdmmabksob/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/imri/pt/ncdmmabksob/([^/]+)$#', + 'pathStart' => '/imri/pt/ncdmmabksob/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ivkqobkem' => [ + 0 => [ + 'name' => '', + 'path' => '/ivkqobkem/sdt/xf/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ivkqobkem/sdt/xf/([^/]+)$#', + 'pathStart' => '/ivkqobkem/sdt/xf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST mnrccybu' => [ + 0 => [ + 'name' => '', + 'path' => '/mnrccybu/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mnrccybu/([^/]+)$#', + 'pathStart' => '/mnrccybu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET dldiikxwf' => [ + 0 => [ + 'name' => '', + 'path' => '/dldiikxwf/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dldiikxwf/([^/]+)$#', + 'pathStart' => '/dldiikxwf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST gz' => [ + 0 => [ + 'name' => '', + 'path' => '/gz/uhylfelionio/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gz/uhylfelionio/([^/]+)$#', + 'pathStart' => '/gz/uhylfelionio/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET gry' => [ + 0 => [ + 'name' => '', + 'path' => '/gry/nbvyzpo/is/tisp/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gry/nbvyzpo/is/tisp/([^/]+)$#', + 'pathStart' => '/gry/nbvyzpo/is/tisp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET plr' => [ + 0 => [ + 'name' => '', + 'path' => '/plr/dcywtwm/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/plr/dcywtwm/([^/]+)$#', + 'pathStart' => '/plr/dcywtwm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET iyguamgmed' => [ + 0 => [ + 'name' => '', + 'path' => '/iyguamgmed/pf/xrfwxfxe/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/iyguamgmed/pf/xrfwxfxe/([^/]+)$#', + 'pathStart' => '/iyguamgmed/pf/xrfwxfxe/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST cp' => [ + 0 => [ + 'name' => '', + 'path' => '/cp/rpzjgcam/aumohc/y/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cp/rpzjgcam/aumohc/y/([^/]+)$#', + 'pathStart' => '/cp/rpzjgcam/aumohc/y/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH j' => [ + 0 => [ + 'name' => '', + 'path' => '/j/sjh/jodnz/xqvg/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/j/sjh/jodnz/xqvg/([^/]+)$#', + 'pathStart' => '/j/sjh/jodnz/xqvg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST csmkr' => [ + 0 => [ + 'name' => '', + 'path' => '/csmkr/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/csmkr/([^/]+)$#', + 'pathStart' => '/csmkr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE covojla' => [ + 0 => [ + 'name' => '', + 'path' => '/covojla/pvmy/hb/nlpo/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/covojla/pvmy/hb/nlpo/([^/]+)$#', + 'pathStart' => '/covojla/pvmy/hb/nlpo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST tnsyebqdlayxoewg' => [ + 0 => [ + 'name' => '', + 'path' => '/tnsyebqdlayxoewg/bd/xc/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/tnsyebqdlayxoewg/bd/xc/([^/]+)$#', + 'pathStart' => '/tnsyebqdlayxoewg/bd/xc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT uwdrn' => [ + 0 => [ + 'name' => '', + 'path' => '/uwdrn/yjn/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/uwdrn/yjn/([^/]+)$#', + 'pathStart' => '/uwdrn/yjn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE boikqeiqfz' => [ + 0 => [ + 'name' => '', + 'path' => '/boikqeiqfz/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/boikqeiqfz/([^/]+)$#', + 'pathStart' => '/boikqeiqfz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE qouimkmb' => [ + 0 => [ + 'name' => '', + 'path' => '/qouimkmb/ad/yxwgup/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qouimkmb/ad/yxwgup/([^/]+)$#', + 'pathStart' => '/qouimkmb/ad/yxwgup/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH xqowgsmgfydkizyab' => [ + 0 => [ + 'name' => '', + 'path' => '/xqowgsmgfydkizyab/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xqowgsmgfydkizyab/([^/]+)$#', + 'pathStart' => '/xqowgsmgfydkizyab/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE o' => [ + 0 => [ + 'name' => '', + 'path' => '/o/vqciinvdu/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/o/vqciinvdu/([^/]+)$#', + 'pathStart' => '/o/vqciinvdu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET sqmypwfz' => [ + 0 => [ + 'name' => '', + 'path' => '/sqmypwfz/c/yskihzry/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sqmypwfz/c/yskihzry/([^/]+)$#', + 'pathStart' => '/sqmypwfz/c/yskihzry/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST pad' => [ + 0 => [ + 'name' => '', + 'path' => '/pad/tu/ogx/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/pad/tu/ogx/([^/]+)$#', + 'pathStart' => '/pad/tu/ogx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH ia' => [ + 0 => [ + 'name' => '', + 'path' => '/ia/fycyf/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ia/fycyf/([^/]+)$#', + 'pathStart' => '/ia/fycyf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE rbq' => [ + 0 => [ + 'name' => '', + 'path' => '/rbq/tg/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rbq/tg/([^/]+)$#', + 'pathStart' => '/rbq/tg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET xixhzqryatjp' => [ + 0 => [ + 'name' => '', + 'path' => '/xixhzqryatjp/xwjs/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xixhzqryatjp/xwjs/([^/]+)$#', + 'pathStart' => '/xixhzqryatjp/xwjs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH nudjb' => [ + 0 => [ + 'name' => '', + 'path' => '/nudjb/yqqiarxe/wwl/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nudjb/yqqiarxe/wwl/([^/]+)$#', + 'pathStart' => '/nudjb/yqqiarxe/wwl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ag' => [ + 0 => [ + 'name' => '', + 'path' => '/ag/homgkn/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ag/homgkn/([^/]+)$#', + 'pathStart' => '/ag/homgkn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET lvov' => [ + 0 => [ + 'name' => '', + 'path' => '/lvov/pgobfnuafiiz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lvov/pgobfnuafiiz/([^/]+)$#', + 'pathStart' => '/lvov/pgobfnuafiiz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET wvoqjuo' => [ + 0 => [ + 'name' => '', + 'path' => '/wvoqjuo/tvsm/sa/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wvoqjuo/tvsm/sa/([^/]+)$#', + 'pathStart' => '/wvoqjuo/tvsm/sa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE jpgbjzqufwfnhh' => [ + 0 => [ + 'name' => '', + 'path' => '/jpgbjzqufwfnhh/fwccr/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jpgbjzqufwfnhh/fwccr/([^/]+)$#', + 'pathStart' => '/jpgbjzqufwfnhh/fwccr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT qhcv' => [ + 0 => [ + 'name' => '', + 'path' => '/qhcv/sgtyt/crsx/x/jgdia/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qhcv/sgtyt/crsx/x/jgdia/([^/]+)$#', + 'pathStart' => '/qhcv/sgtyt/crsx/x/jgdia/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT v2' => [ + 0 => [ + 'name' => '', + 'path' => '/v2/odabudztvjirwsspma/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/odabudztvjirwsspma/([^/]+)$#', + 'pathStart' => '/v2/odabudztvjirwsspma/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/v2/tptrelneqgzhenoerl/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/tptrelneqgzhenoerl/([^/]+)$#', + 'pathStart' => '/v2/tptrelneqgzhenoerl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/v2/ruylwpqrihozckvtgm/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/ruylwpqrihozckvtgm/([^/]+)$#', + 'pathStart' => '/v2/ruylwpqrihozckvtgm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/v2/durpuu/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/durpuu/([^/]+)$#', + 'pathStart' => '/v2/durpuu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ugryezf' => [ + 0 => [ + 'name' => '', + 'path' => '/ugryezf/tewj/yaqjzkwmu/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ugryezf/tewj/yaqjzkwmu/([^/]+)$#', + 'pathStart' => '/ugryezf/tewj/yaqjzkwmu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH e' => [ + 0 => [ + 'name' => '', + 'path' => '/e/qbktydngqlyqmuay/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/e/qbktydngqlyqmuay/([^/]+)$#', + 'pathStart' => '/e/qbktydngqlyqmuay/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST api' => [ + 0 => [ + 'name' => '', + 'path' => '/api/bcescnecpvwirefiwx/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/bcescnecpvwirefiwx/([^/]+)$#', + 'pathStart' => '/api/bcescnecpvwirefiwx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/api/dundcluhgzxv/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/dundcluhgzxv/([^/]+)$#', + 'pathStart' => '/api/dundcluhgzxv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/api/xqwmdjlhwczz/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/xqwmdjlhwczz/([^/]+)$#', + 'pathStart' => '/api/xqwmdjlhwczz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/api/ueffyjvdnuqapzf/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ueffyjvdnuqapzf/([^/]+)$#', + 'pathStart' => '/api/ueffyjvdnuqapzf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/api/rkjsjo/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/rkjsjo/([^/]+)$#', + 'pathStart' => '/api/rkjsjo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/api/dgturvdjvueb/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/dgturvdjvueb/([^/]+)$#', + 'pathStart' => '/api/dgturvdjvueb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET lvnysclgcyp' => [ + 0 => [ + 'name' => '', + 'path' => '/lvnysclgcyp/dn/apwo/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lvnysclgcyp/dn/apwo/([^/]+)$#', + 'pathStart' => '/lvnysclgcyp/dn/apwo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET oek' => [ + 0 => [ + 'name' => '', + 'path' => '/oek/qqjgvhw/weye/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/oek/qqjgvhw/weye/([^/]+)$#', + 'pathStart' => '/oek/qqjgvhw/weye/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ywdpizo' => [ + 0 => [ + 'name' => '', + 'path' => '/ywdpizo/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ywdpizo/([^/]+)$#', + 'pathStart' => '/ywdpizo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET yuibarhmmmdyhgwesm' => [ + 0 => [ + 'name' => '', + 'path' => '/yuibarhmmmdyhgwesm/g/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yuibarhmmmdyhgwesm/g/([^/]+)$#', + 'pathStart' => '/yuibarhmmmdyhgwesm/g/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET tcos' => [ + 0 => [ + 'name' => '', + 'path' => '/tcos/llqc/bb/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/tcos/llqc/bb/([^/]+)$#', + 'pathStart' => '/tcos/llqc/bb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET xxtfrakd' => [ + 0 => [ + 'name' => '', + 'path' => '/xxtfrakd/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xxtfrakd/([^/]+)$#', + 'pathStart' => '/xxtfrakd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET lijfptn' => [ + 0 => [ + 'name' => '', + 'path' => '/lijfptn/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lijfptn/([^/]+)$#', + 'pathStart' => '/lijfptn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET c' => [ + 0 => [ + 'name' => '', + 'path' => '/c/nfn/yhepq/iqyrlej/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/c/nfn/yhepq/iqyrlej/([^/]+)$#', + 'pathStart' => '/c/nfn/yhepq/iqyrlej/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH nhnqifgj' => [ + 0 => [ + 'name' => '', + 'path' => '/nhnqifgj/vned/yhcutfo/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nhnqifgj/vned/yhcutfo/([^/]+)$#', + 'pathStart' => '/nhnqifgj/vned/yhcutfo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH wwdponhbnx' => [ + 0 => [ + 'name' => '', + 'path' => '/wwdponhbnx/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wwdponhbnx/([^/]+)$#', + 'pathStart' => '/wwdponhbnx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ucle' => [ + 0 => [ + 'name' => '', + 'path' => '/ucle/gfsovejxpu/cffxp/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ucle/gfsovejxpu/cffxp/([^/]+)$#', + 'pathStart' => '/ucle/gfsovejxpu/cffxp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT npfmi' => [ + 0 => [ + 'name' => '', + 'path' => '/npfmi/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/npfmi/([^/]+)$#', + 'pathStart' => '/npfmi/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE k' => [ + 0 => [ + 'name' => '', + 'path' => '/k/nbwqlgyxd/mpdr/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/k/nbwqlgyxd/mpdr/([^/]+)$#', + 'pathStart' => '/k/nbwqlgyxd/mpdr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET jacethrwk' => [ + 0 => [ + 'name' => '', + 'path' => '/jacethrwk/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jacethrwk/([^/]+)$#', + 'pathStart' => '/jacethrwk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE glsr' => [ + 0 => [ + 'name' => '', + 'path' => '/glsr/w/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/glsr/w/([^/]+)$#', + 'pathStart' => '/glsr/w/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET optprhrs' => [ + 0 => [ + 'name' => '', + 'path' => '/optprhrs/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/optprhrs/([^/]+)$#', + 'pathStart' => '/optprhrs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE djeitkql' => [ + 0 => [ + 'name' => '', + 'path' => '/djeitkql/uage/lastv/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/djeitkql/uage/lastv/([^/]+)$#', + 'pathStart' => '/djeitkql/uage/lastv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT sfbqnm' => [ + 0 => [ + 'name' => '', + 'path' => '/sfbqnm/btoejplnwxh/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sfbqnm/btoejplnwxh/([^/]+)$#', + 'pathStart' => '/sfbqnm/btoejplnwxh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET cni' => [ + 0 => [ + 'name' => '', + 'path' => '/cni/qjssodudxyg/ie/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cni/qjssodudxyg/ie/([^/]+)$#', + 'pathStart' => '/cni/qjssodudxyg/ie/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE ficcdkqgwups' => [ + 0 => [ + 'name' => '', + 'path' => '/ficcdkqgwups/kamc/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ficcdkqgwups/kamc/([^/]+)$#', + 'pathStart' => '/ficcdkqgwups/kamc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST yfvtz' => [ + 0 => [ + 'name' => '', + 'path' => '/yfvtz/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yfvtz/([^/]+)$#', + 'pathStart' => '/yfvtz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT evrxfaokmh' => [ + 0 => [ + 'name' => '', + 'path' => '/evrxfaokmh/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/evrxfaokmh/([^/]+)$#', + 'pathStart' => '/evrxfaokmh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE t' => [ + 0 => [ + 'name' => '', + 'path' => '/t/afgsjrwzw/lnia/m/v/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/t/afgsjrwzw/lnia/m/v/([^/]+)$#', + 'pathStart' => '/t/afgsjrwzw/lnia/m/v/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/t/uzkfq/uu/vgamgxrcic/d/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/t/uzkfq/uu/vgamgxrcic/d/([^/]+)$#', + 'pathStart' => '/t/uzkfq/uu/vgamgxrcic/d/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET h' => [ + 0 => [ + 'name' => '', + 'path' => '/h/gndquhhyq/h/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/h/gndquhhyq/h/([^/]+)$#', + 'pathStart' => '/h/gndquhhyq/h/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET veemy' => [ + 0 => [ + 'name' => '', + 'path' => '/veemy/okpiz/xmd/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/veemy/okpiz/xmd/([^/]+)$#', + 'pathStart' => '/veemy/okpiz/xmd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH w' => [ + 0 => [ + 'name' => '', + 'path' => '/w/px/sinqb/xajqg/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/w/px/sinqb/xajqg/([^/]+)$#', + 'pathStart' => '/w/px/sinqb/xajqg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE qhvibg' => [ + 0 => [ + 'name' => '', + 'path' => '/qhvibg/bg/koyovovlneh/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qhvibg/bg/koyovovlneh/([^/]+)$#', + 'pathStart' => '/qhvibg/bg/koyovovlneh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST fruvt' => [ + 0 => [ + 'name' => '', + 'path' => '/fruvt/fcrmwho/zuogxguj/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/fruvt/fcrmwho/zuogxguj/([^/]+)$#', + 'pathStart' => '/fruvt/fcrmwho/zuogxguj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT s' => [ + 0 => [ + 'name' => '', + 'path' => '/s/qdejkuueasftgvxsd/a/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/s/qdejkuueasftgvxsd/a/([^/]+)$#', + 'pathStart' => '/s/qdejkuueasftgvxsd/a/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE v2' => [ + 0 => [ + 'name' => '', + 'path' => '/v2/okpsbo/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/okpsbo/([^/]+)$#', + 'pathStart' => '/v2/okpsbo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/v2/idnanpeflzzcrkeglr/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/idnanpeflzzcrkeglr/([^/]+)$#', + 'pathStart' => '/v2/idnanpeflzzcrkeglr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/v2/dpshcrphvbwk/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/v2/dpshcrphvbwk/([^/]+)$#', + 'pathStart' => '/v2/dpshcrphvbwk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE mzt' => [ + 0 => [ + 'name' => '', + 'path' => '/mzt/qylev/akodq/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mzt/qylev/akodq/([^/]+)$#', + 'pathStart' => '/mzt/qylev/akodq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH hyujquvl' => [ + 0 => [ + 'name' => '', + 'path' => '/hyujquvl/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hyujquvl/([^/]+)$#', + 'pathStart' => '/hyujquvl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET zynnxuhjhf' => [ + 0 => [ + 'name' => '', + 'path' => '/zynnxuhjhf/uev/e/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zynnxuhjhf/uev/e/([^/]+)$#', + 'pathStart' => '/zynnxuhjhf/uev/e/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST zawgttjnnwlhybumirf' => [ + 0 => [ + 'name' => '', + 'path' => '/zawgttjnnwlhybumirf/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zawgttjnnwlhybumirf/([^/]+)$#', + 'pathStart' => '/zawgttjnnwlhybumirf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET bj' => [ + 0 => [ + 'name' => '', + 'path' => '/bj/ve/salslr/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/bj/ve/salslr/([^/]+)$#', + 'pathStart' => '/bj/ve/salslr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ccytmtz' => [ + 0 => [ + 'name' => '', + 'path' => '/ccytmtz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ccytmtz/([^/]+)$#', + 'pathStart' => '/ccytmtz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET mgofppqcbsrya' => [ + 0 => [ + 'name' => '', + 'path' => '/mgofppqcbsrya/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mgofppqcbsrya/([^/]+)$#', + 'pathStart' => '/mgofppqcbsrya/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET gezzognyftyj' => [ + 0 => [ + 'name' => '', + 'path' => '/gezzognyftyj/houyslke/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gezzognyftyj/houyslke/([^/]+)$#', + 'pathStart' => '/gezzognyftyj/houyslke/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST n' => [ + 0 => [ + 'name' => '', + 'path' => '/n/qckux/memkm/vxbox/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/n/qckux/memkm/vxbox/([^/]+)$#', + 'pathStart' => '/n/qckux/memkm/vxbox/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET pjsq' => [ + 0 => [ + 'name' => '', + 'path' => '/pjsq/p/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/pjsq/p/([^/]+)$#', + 'pathStart' => '/pjsq/p/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST i' => [ + 0 => [ + 'name' => '', + 'path' => '/i/vzcut/qlvnfz/w/zjn/z/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/i/vzcut/qlvnfz/w/zjn/z/([^/]+)$#', + 'pathStart' => '/i/vzcut/qlvnfz/w/zjn/z/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET f' => [ + 0 => [ + 'name' => '', + 'path' => '/f/yxy/vtup/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/f/yxy/vtup/([^/]+)$#', + 'pathStart' => '/f/yxy/vtup/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/f/v/uclj/ckc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/f/v/uclj/ckc/([^/]+)$#', + 'pathStart' => '/f/v/uclj/ckc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST tiobowyl' => [ + 0 => [ + 'name' => '', + 'path' => '/tiobowyl/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/tiobowyl/([^/]+)$#', + 'pathStart' => '/tiobowyl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH luysnqo' => [ + 0 => [ + 'name' => '', + 'path' => '/luysnqo/h/yfuxmh/p/n/vws/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/luysnqo/h/yfuxmh/p/n/vws/([^/]+)$#', + 'pathStart' => '/luysnqo/h/yfuxmh/p/n/vws/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE kpizb' => [ + 0 => [ + 'name' => '', + 'path' => '/kpizb/sbaxjp/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/kpizb/sbaxjp/([^/]+)$#', + 'pathStart' => '/kpizb/sbaxjp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE u' => [ + 0 => [ + 'name' => '', + 'path' => '/u/efzodug/ua/jtx/vnwb/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/u/efzodug/ua/jtx/vnwb/([^/]+)$#', + 'pathStart' => '/u/efzodug/ua/jtx/vnwb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST cpk' => [ + 0 => [ + 'name' => '', + 'path' => '/cpk/zmj/su/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cpk/zmj/su/([^/]+)$#', + 'pathStart' => '/cpk/zmj/su/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT lf' => [ + 0 => [ + 'name' => '', + 'path' => '/lf/iwsybgq/xezv/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lf/iwsybgq/xezv/([^/]+)$#', + 'pathStart' => '/lf/iwsybgq/xezv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT mlddwbqxpt' => [ + 0 => [ + 'name' => '', + 'path' => '/mlddwbqxpt/ln/l/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mlddwbqxpt/ln/l/([^/]+)$#', + 'pathStart' => '/mlddwbqxpt/ln/l/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE lj' => [ + 0 => [ + 'name' => '', + 'path' => '/lj/jmycftjxwer/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lj/jmycftjxwer/([^/]+)$#', + 'pathStart' => '/lj/jmycftjxwer/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH b' => [ + 0 => [ + 'name' => '', + 'path' => '/b/t/p/u/vpmte/jzwc/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/b/t/p/u/vpmte/jzwc/([^/]+)$#', + 'pathStart' => '/b/t/p/u/vpmte/jzwc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT hkvv' => [ + 0 => [ + 'name' => '', + 'path' => '/hkvv/gyxwwnsartgaoeh/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hkvv/gyxwwnsartgaoeh/([^/]+)$#', + 'pathStart' => '/hkvv/gyxwwnsartgaoeh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT mdmrz' => [ + 0 => [ + 'name' => '', + 'path' => '/mdmrz/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mdmrz/([^/]+)$#', + 'pathStart' => '/mdmrz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET uqontc' => [ + 0 => [ + 'name' => '', + 'path' => '/uqontc/cblmso/gw/pjtb/o/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/uqontc/cblmso/gw/pjtb/o/([^/]+)$#', + 'pathStart' => '/uqontc/cblmso/gw/pjtb/o/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST usxg' => [ + 0 => [ + 'name' => '', + 'path' => '/usxg/grr/vj/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/usxg/grr/vj/([^/]+)$#', + 'pathStart' => '/usxg/grr/vj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT xmeh' => [ + 0 => [ + 'name' => '', + 'path' => '/xmeh/q/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xmeh/q/([^/]+)$#', + 'pathStart' => '/xmeh/q/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET wpcq' => [ + 0 => [ + 'name' => '', + 'path' => '/wpcq/wdtyiubbbrmwu/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wpcq/wdtyiubbbrmwu/([^/]+)$#', + 'pathStart' => '/wpcq/wdtyiubbbrmwu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET wiylvdsi' => [ + 0 => [ + 'name' => '', + 'path' => '/wiylvdsi/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wiylvdsi/([^/]+)$#', + 'pathStart' => '/wiylvdsi/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE whaiekqsqgqgcjmhu' => [ + 0 => [ + 'name' => '', + 'path' => '/whaiekqsqgqgcjmhu/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/whaiekqsqgqgcjmhu/([^/]+)$#', + 'pathStart' => '/whaiekqsqgqgcjmhu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET dzsiufj' => [ + 0 => [ + 'name' => '', + 'path' => '/dzsiufj/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dzsiufj/([^/]+)$#', + 'pathStart' => '/dzsiufj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH diuzoe' => [ + 0 => [ + 'name' => '', + 'path' => '/diuzoe/fmtkmanwkt/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/diuzoe/fmtkmanwkt/([^/]+)$#', + 'pathStart' => '/diuzoe/fmtkmanwkt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH rfsynyejfcrt' => [ + 0 => [ + 'name' => '', + 'path' => '/rfsynyejfcrt/kcvbqzm/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rfsynyejfcrt/kcvbqzm/([^/]+)$#', + 'pathStart' => '/rfsynyejfcrt/kcvbqzm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT hgs' => [ + 0 => [ + 'name' => '', + 'path' => '/hgs/fkvhq/ysx/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hgs/fkvhq/ysx/([^/]+)$#', + 'pathStart' => '/hgs/fkvhq/ysx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET n' => [ + 0 => [ + 'name' => '', + 'path' => '/n/wec/htzi/a/hjtfughv/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/n/wec/htzi/a/hjtfughv/([^/]+)$#', + 'pathStart' => '/n/wec/htzi/a/hjtfughv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/n/lieoby/gc/ydbx/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/n/lieoby/gc/ydbx/([^/]+)$#', + 'pathStart' => '/n/lieoby/gc/ydbx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET i' => [ + 0 => [ + 'name' => '', + 'path' => '/i/jnkazj/qiz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/i/jnkazj/qiz/([^/]+)$#', + 'pathStart' => '/i/jnkazj/qiz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH dblmcvpfc' => [ + 0 => [ + 'name' => '', + 'path' => '/dblmcvpfc/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dblmcvpfc/([^/]+)$#', + 'pathStart' => '/dblmcvpfc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT xeogjtkr' => [ + 0 => [ + 'name' => '', + 'path' => '/xeogjtkr/j/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xeogjtkr/j/([^/]+)$#', + 'pathStart' => '/xeogjtkr/j/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST glbln' => [ + 0 => [ + 'name' => '', + 'path' => '/glbln/vsguc/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/glbln/vsguc/([^/]+)$#', + 'pathStart' => '/glbln/vsguc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET jfwptkkptolxjexhppt' => [ + 0 => [ + 'name' => '', + 'path' => '/jfwptkkptolxjexhppt/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jfwptkkptolxjexhppt/([^/]+)$#', + 'pathStart' => '/jfwptkkptolxjexhppt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ozjbi' => [ + 0 => [ + 'name' => '', + 'path' => '/ozjbi/ufx/qzrqoodvldq/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ozjbi/ufx/qzrqoodvldq/([^/]+)$#', + 'pathStart' => '/ozjbi/ufx/qzrqoodvldq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET b' => [ + 0 => [ + 'name' => '', + 'path' => '/b/vzkls/vkzhzlu/pv/z/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/b/vzkls/vkzhzlu/pv/z/([^/]+)$#', + 'pathStart' => '/b/vzkls/vkzhzlu/pv/z/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE user' => [ + 0 => [ + 'name' => '', + 'path' => '/user/xmglzwrgssvl/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/xmglzwrgssvl/([^/]+)$#', + 'pathStart' => '/user/xmglzwrgssvl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/user/nauyetcguqop/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/nauyetcguqop/([^/]+)$#', + 'pathStart' => '/user/nauyetcguqop/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/user/zcpylajcwrevveh/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/zcpylajcwrevveh/([^/]+)$#', + 'pathStart' => '/user/zcpylajcwrevveh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/user/olrnin/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/olrnin/([^/]+)$#', + 'pathStart' => '/user/olrnin/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET w' => [ + 0 => [ + 'name' => '', + 'path' => '/w/ugjau/w/vtevhscitgfk/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/w/ugjau/w/vtevhscitgfk/([^/]+)$#', + 'pathStart' => '/w/ugjau/w/vtevhscitgfk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE x' => [ + 0 => [ + 'name' => '', + 'path' => '/x/qmipihlsr/bub/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/x/qmipihlsr/bub/([^/]+)$#', + 'pathStart' => '/x/qmipihlsr/bub/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT odwjvxczx' => [ + 0 => [ + 'name' => '', + 'path' => '/odwjvxczx/d/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/odwjvxczx/d/([^/]+)$#', + 'pathStart' => '/odwjvxczx/d/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET j' => [ + 0 => [ + 'name' => '', + 'path' => '/j/erlejds/sj/ozz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/j/erlejds/sj/ozz/([^/]+)$#', + 'pathStart' => '/j/erlejds/sj/ozz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/j/io/nijvehe/p/uuvdz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/j/io/nijvehe/p/uuvdz/([^/]+)$#', + 'pathStart' => '/j/io/nijvehe/p/uuvdz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET lsljhgathmn' => [ + 0 => [ + 'name' => '', + 'path' => '/lsljhgathmn/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lsljhgathmn/([^/]+)$#', + 'pathStart' => '/lsljhgathmn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT user' => [ + 0 => [ + 'name' => '', + 'path' => '/user/dlxmnagmgmoqjkahhe/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/dlxmnagmgmoqjkahhe/([^/]+)$#', + 'pathStart' => '/user/dlxmnagmgmoqjkahhe/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/user/plldocmvntoiryj/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/plldocmvntoiryj/([^/]+)$#', + 'pathStart' => '/user/plldocmvntoiryj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/user/yppejgcrxjbhlcqbnh/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/yppejgcrxjbhlcqbnh/([^/]+)$#', + 'pathStart' => '/user/yppejgcrxjbhlcqbnh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/user/hevccjyauunzxucnvq/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/hevccjyauunzxucnvq/([^/]+)$#', + 'pathStart' => '/user/hevccjyauunzxucnvq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/user/cpugssjxoyua/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/cpugssjxoyua/([^/]+)$#', + 'pathStart' => '/user/cpugssjxoyua/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/user/ampjbyamgbbd/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/user/ampjbyamgbbd/([^/]+)$#', + 'pathStart' => '/user/ampjbyamgbbd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH mgylrdswtnw' => [ + 0 => [ + 'name' => '', + 'path' => '/mgylrdswtnw/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mgylrdswtnw/([^/]+)$#', + 'pathStart' => '/mgylrdswtnw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH gyfflwlhfkdzjtlzs' => [ + 0 => [ + 'name' => '', + 'path' => '/gyfflwlhfkdzjtlzs/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gyfflwlhfkdzjtlzs/([^/]+)$#', + 'pathStart' => '/gyfflwlhfkdzjtlzs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE eg' => [ + 0 => [ + 'name' => '', + 'path' => '/eg/nvpjm/w/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/eg/nvpjm/w/([^/]+)$#', + 'pathStart' => '/eg/nvpjm/w/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH xhqm' => [ + 0 => [ + 'name' => '', + 'path' => '/xhqm/q/cm/uafplaw/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xhqm/q/cm/uafplaw/([^/]+)$#', + 'pathStart' => '/xhqm/q/cm/uafplaw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET mlp' => [ + 0 => [ + 'name' => '', + 'path' => '/mlp/sjstrnr/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mlp/sjstrnr/([^/]+)$#', + 'pathStart' => '/mlp/sjstrnr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST wfmpp' => [ + 0 => [ + 'name' => '', + 'path' => '/wfmpp/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wfmpp/([^/]+)$#', + 'pathStart' => '/wfmpp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH yffuec' => [ + 0 => [ + 'name' => '', + 'path' => '/yffuec/ahvwmwg/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yffuec/ahvwmwg/([^/]+)$#', + 'pathStart' => '/yffuec/ahvwmwg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE hvddfj' => [ + 0 => [ + 'name' => '', + 'path' => '/hvddfj/z/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hvddfj/z/([^/]+)$#', + 'pathStart' => '/hvddfj/z/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE ndlbcfphelyaqfki' => [ + 0 => [ + 'name' => '', + 'path' => '/ndlbcfphelyaqfki/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ndlbcfphelyaqfki/([^/]+)$#', + 'pathStart' => '/ndlbcfphelyaqfki/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE f' => [ + 0 => [ + 'name' => '', + 'path' => '/f/dwqeux/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/f/dwqeux/([^/]+)$#', + 'pathStart' => '/f/dwqeux/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT ku' => [ + 0 => [ + 'name' => '', + 'path' => '/ku/ij/o/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ku/ij/o/([^/]+)$#', + 'pathStart' => '/ku/ij/o/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET faowuout' => [ + 0 => [ + 'name' => '', + 'path' => '/faowuout/wrtptb/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/faowuout/wrtptb/([^/]+)$#', + 'pathStart' => '/faowuout/wrtptb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH ajj' => [ + 0 => [ + 'name' => '', + 'path' => '/ajj/ei/hyz/pdjurm/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ajj/ei/hyz/pdjurm/([^/]+)$#', + 'pathStart' => '/ajj/ei/hyz/pdjurm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE scdeftrlvok' => [ + 0 => [ + 'name' => '', + 'path' => '/scdeftrlvok/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/scdeftrlvok/([^/]+)$#', + 'pathStart' => '/scdeftrlvok/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE xibd' => [ + 0 => [ + 'name' => '', + 'path' => '/xibd/hromy/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xibd/hromy/([^/]+)$#', + 'pathStart' => '/xibd/hromy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET qmqvuqpqi' => [ + 0 => [ + 'name' => '', + 'path' => '/qmqvuqpqi/w/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qmqvuqpqi/w/([^/]+)$#', + 'pathStart' => '/qmqvuqpqi/w/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE me' => [ + 0 => [ + 'name' => '', + 'path' => '/me/gunzor/qzdvs/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/me/gunzor/qzdvs/([^/]+)$#', + 'pathStart' => '/me/gunzor/qzdvs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE xiaaipgzo' => [ + 0 => [ + 'name' => '', + 'path' => '/xiaaipgzo/zyfc/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xiaaipgzo/zyfc/([^/]+)$#', + 'pathStart' => '/xiaaipgzo/zyfc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE mb' => [ + 0 => [ + 'name' => '', + 'path' => '/mb/gjuxygkyr/ebsxdwdzy/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mb/gjuxygkyr/ebsxdwdzy/([^/]+)$#', + 'pathStart' => '/mb/gjuxygkyr/ebsxdwdzy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET lqcme' => [ + 0 => [ + 'name' => '', + 'path' => '/lqcme/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lqcme/([^/]+)$#', + 'pathStart' => '/lqcme/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET jepagheeipeivjch' => [ + 0 => [ + 'name' => '', + 'path' => '/jepagheeipeivjch/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jepagheeipeivjch/([^/]+)$#', + 'pathStart' => '/jepagheeipeivjch/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET dxyilfvyp' => [ + 0 => [ + 'name' => '', + 'path' => '/dxyilfvyp/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dxyilfvyp/([^/]+)$#', + 'pathStart' => '/dxyilfvyp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT exdktclciulxkm' => [ + 0 => [ + 'name' => '', + 'path' => '/exdktclciulxkm/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/exdktclciulxkm/([^/]+)$#', + 'pathStart' => '/exdktclciulxkm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET aimim' => [ + 0 => [ + 'name' => '', + 'path' => '/aimim/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/aimim/([^/]+)$#', + 'pathStart' => '/aimim/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET cwwiqrbqwkxyymqk' => [ + 0 => [ + 'name' => '', + 'path' => '/cwwiqrbqwkxyymqk/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cwwiqrbqwkxyymqk/([^/]+)$#', + 'pathStart' => '/cwwiqrbqwkxyymqk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET kq' => [ + 0 => [ + 'name' => '', + 'path' => '/kq/dpi/paaja/bidoucs/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/kq/dpi/paaja/bidoucs/([^/]+)$#', + 'pathStart' => '/kq/dpi/paaja/bidoucs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET smgyitjvafh' => [ + 0 => [ + 'name' => '', + 'path' => '/smgyitjvafh/o/podzyjkx/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/smgyitjvafh/o/podzyjkx/([^/]+)$#', + 'pathStart' => '/smgyitjvafh/o/podzyjkx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH bavmbfcewx' => [ + 0 => [ + 'name' => '', + 'path' => '/bavmbfcewx/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/bavmbfcewx/([^/]+)$#', + 'pathStart' => '/bavmbfcewx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT cww' => [ + 0 => [ + 'name' => '', + 'path' => '/cww/h/azmuacl/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cww/h/azmuacl/([^/]+)$#', + 'pathStart' => '/cww/h/azmuacl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET vm' => [ + 0 => [ + 'name' => '', + 'path' => '/vm/mlatikmw/h/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vm/mlatikmw/h/([^/]+)$#', + 'pathStart' => '/vm/mlatikmw/h/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST hmjqhqcs' => [ + 0 => [ + 'name' => '', + 'path' => '/hmjqhqcs/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hmjqhqcs/([^/]+)$#', + 'pathStart' => '/hmjqhqcs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET qobi' => [ + 0 => [ + 'name' => '', + 'path' => '/qobi/tebjuey/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qobi/tebjuey/([^/]+)$#', + 'pathStart' => '/qobi/tebjuey/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH otisezzlqiylmkmkr' => [ + 0 => [ + 'name' => '', + 'path' => '/otisezzlqiylmkmkr/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/otisezzlqiylmkmkr/([^/]+)$#', + 'pathStart' => '/otisezzlqiylmkmkr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT f' => [ + 0 => [ + 'name' => '', + 'path' => '/f/klvgcyzxsyhjdjzglf/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/f/klvgcyzxsyhjdjzglf/([^/]+)$#', + 'pathStart' => '/f/klvgcyzxsyhjdjzglf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ftgzcaecjnetejo' => [ + 0 => [ + 'name' => '', + 'path' => '/ftgzcaecjnetejo/k/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ftgzcaecjnetejo/k/([^/]+)$#', + 'pathStart' => '/ftgzcaecjnetejo/k/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT jf' => [ + 0 => [ + 'name' => '', + 'path' => '/jf/aqbodvap/s/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jf/aqbodvap/s/([^/]+)$#', + 'pathStart' => '/jf/aqbodvap/s/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH worsjex' => [ + 0 => [ + 'name' => '', + 'path' => '/worsjex/w/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/worsjex/w/([^/]+)$#', + 'pathStart' => '/worsjex/w/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH nyrzqljpesbm' => [ + 0 => [ + 'name' => '', + 'path' => '/nyrzqljpesbm/calss/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nyrzqljpesbm/calss/([^/]+)$#', + 'pathStart' => '/nyrzqljpesbm/calss/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ny' => [ + 0 => [ + 'name' => '', + 'path' => '/ny/frouawymqrt/odgfrb/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ny/frouawymqrt/odgfrb/([^/]+)$#', + 'pathStart' => '/ny/frouawymqrt/odgfrb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST qvuh' => [ + 0 => [ + 'name' => '', + 'path' => '/qvuh/iy/wvfy/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qvuh/iy/wvfy/([^/]+)$#', + 'pathStart' => '/qvuh/iy/wvfy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET s' => [ + 0 => [ + 'name' => '', + 'path' => '/s/bhgd/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/s/bhgd/([^/]+)$#', + 'pathStart' => '/s/bhgd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE fp' => [ + 0 => [ + 'name' => '', + 'path' => '/fp/bbnae/vlduwc/dpzers/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/fp/bbnae/vlduwc/dpzers/([^/]+)$#', + 'pathStart' => '/fp/bbnae/vlduwc/dpzers/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH exvh' => [ + 0 => [ + 'name' => '', + 'path' => '/exvh/tdp/oolkpzisvcdpt/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/exvh/tdp/oolkpzisvcdpt/([^/]+)$#', + 'pathStart' => '/exvh/tdp/oolkpzisvcdpt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH znux' => [ + 0 => [ + 'name' => '', + 'path' => '/znux/i/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/znux/i/([^/]+)$#', + 'pathStart' => '/znux/i/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET z' => [ + 0 => [ + 'name' => '', + 'path' => '/z/mvsrssudc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/z/mvsrssudc/([^/]+)$#', + 'pathStart' => '/z/mvsrssudc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET hfmxkutq' => [ + 0 => [ + 'name' => '', + 'path' => '/hfmxkutq/rtvqft/tbi/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hfmxkutq/rtvqft/tbi/([^/]+)$#', + 'pathStart' => '/hfmxkutq/rtvqft/tbi/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST jdmvlce' => [ + 0 => [ + 'name' => '', + 'path' => '/jdmvlce/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jdmvlce/([^/]+)$#', + 'pathStart' => '/jdmvlce/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT k' => [ + 0 => [ + 'name' => '', + 'path' => '/k/n/kp/ohaw/f/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/k/n/kp/ohaw/f/([^/]+)$#', + 'pathStart' => '/k/n/kp/ohaw/f/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST rzzconffh' => [ + 0 => [ + 'name' => '', + 'path' => '/rzzconffh/lcqgkwy/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rzzconffh/lcqgkwy/([^/]+)$#', + 'pathStart' => '/rzzconffh/lcqgkwy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST fy' => [ + 0 => [ + 'name' => '', + 'path' => '/fy/ezunq/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/fy/ezunq/([^/]+)$#', + 'pathStart' => '/fy/ezunq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST czf' => [ + 0 => [ + 'name' => '', + 'path' => '/czf/h/nhmwapzraaex/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/czf/h/nhmwapzraaex/([^/]+)$#', + 'pathStart' => '/czf/h/nhmwapzraaex/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET fuknmpa' => [ + 0 => [ + 'name' => '', + 'path' => '/fuknmpa/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/fuknmpa/([^/]+)$#', + 'pathStart' => '/fuknmpa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH hcsgdnlrwkplv' => [ + 0 => [ + 'name' => '', + 'path' => '/hcsgdnlrwkplv/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hcsgdnlrwkplv/([^/]+)$#', + 'pathStart' => '/hcsgdnlrwkplv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT oqjrfft' => [ + 0 => [ + 'name' => '', + 'path' => '/oqjrfft/kop/iwbv/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/oqjrfft/kop/iwbv/([^/]+)$#', + 'pathStart' => '/oqjrfft/kop/iwbv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST ihovdzw' => [ + 0 => [ + 'name' => '', + 'path' => '/ihovdzw/jqcmyafmui/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ihovdzw/jqcmyafmui/([^/]+)$#', + 'pathStart' => '/ihovdzw/jqcmyafmui/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE xnrnw' => [ + 0 => [ + 'name' => '', + 'path' => '/xnrnw/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xnrnw/([^/]+)$#', + 'pathStart' => '/xnrnw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH che' => [ + 0 => [ + 'name' => '', + 'path' => '/che/wxst/hxhsrqa/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/che/wxst/hxhsrqa/([^/]+)$#', + 'pathStart' => '/che/wxst/hxhsrqa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE sz' => [ + 0 => [ + 'name' => '', + 'path' => '/sz/cxqlzioighmu/uy/a/fg/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sz/cxqlzioighmu/uy/a/fg/([^/]+)$#', + 'pathStart' => '/sz/cxqlzioighmu/uy/a/fg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST zqhcdozaivyfhuy' => [ + 0 => [ + 'name' => '', + 'path' => '/zqhcdozaivyfhuy/iwyj/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zqhcdozaivyfhuy/iwyj/([^/]+)$#', + 'pathStart' => '/zqhcdozaivyfhuy/iwyj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST zkkft' => [ + 0 => [ + 'name' => '', + 'path' => '/zkkft/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zkkft/([^/]+)$#', + 'pathStart' => '/zkkft/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ohurw' => [ + 0 => [ + 'name' => '', + 'path' => '/ohurw/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ohurw/([^/]+)$#', + 'pathStart' => '/ohurw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE cchd' => [ + 0 => [ + 'name' => '', + 'path' => '/cchd/q/mbqaa/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cchd/q/mbqaa/([^/]+)$#', + 'pathStart' => '/cchd/q/mbqaa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET cdlqwwlu' => [ + 0 => [ + 'name' => '', + 'path' => '/cdlqwwlu/jdapukxrv/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cdlqwwlu/jdapukxrv/([^/]+)$#', + 'pathStart' => '/cdlqwwlu/jdapukxrv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET krwog' => [ + 0 => [ + 'name' => '', + 'path' => '/krwog/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/krwog/([^/]+)$#', + 'pathStart' => '/krwog/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET yibublqswrdotyhfcooy' => [ + 0 => [ + 'name' => '', + 'path' => '/yibublqswrdotyhfcooy/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yibublqswrdotyhfcooy/([^/]+)$#', + 'pathStart' => '/yibublqswrdotyhfcooy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ziiqx' => [ + 0 => [ + 'name' => '', + 'path' => '/ziiqx/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ziiqx/([^/]+)$#', + 'pathStart' => '/ziiqx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET owfxa' => [ + 0 => [ + 'name' => '', + 'path' => '/owfxa/sxm/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/owfxa/sxm/([^/]+)$#', + 'pathStart' => '/owfxa/sxm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET tq' => [ + 0 => [ + 'name' => '', + 'path' => '/tq/fy/iqgky/mkzgjcq/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/tq/fy/iqgky/mkzgjcq/([^/]+)$#', + 'pathStart' => '/tq/fy/iqgky/mkzgjcq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH zgtpnl' => [ + 0 => [ + 'name' => '', + 'path' => '/zgtpnl/xqlylblggjmu/x/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zgtpnl/xqlylblggjmu/x/([^/]+)$#', + 'pathStart' => '/zgtpnl/xqlylblggjmu/x/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST gunyihcww' => [ + 0 => [ + 'name' => '', + 'path' => '/gunyihcww/vufwym/eelj/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gunyihcww/vufwym/eelj/([^/]+)$#', + 'pathStart' => '/gunyihcww/vufwym/eelj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH dbx' => [ + 0 => [ + 'name' => '', + 'path' => '/dbx/wads/w/g/r/uob/hban/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dbx/wads/w/g/r/uob/hban/([^/]+)$#', + 'pathStart' => '/dbx/wads/w/g/r/uob/hban/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH api' => [ + 0 => [ + 'name' => '', + 'path' => '/api/jkltcsmztigqjlspqq/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/jkltcsmztigqjlspqq/([^/]+)$#', + 'pathStart' => '/api/jkltcsmztigqjlspqq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/api/jhliqwhcpxmk/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/jhliqwhcpxmk/([^/]+)$#', + 'pathStart' => '/api/jhliqwhcpxmk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/api/usmdxhcntodiyyq/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/usmdxhcntodiyyq/([^/]+)$#', + 'pathStart' => '/api/usmdxhcntodiyyq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE soljt' => [ + 0 => [ + 'name' => '', + 'path' => '/soljt/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/soljt/([^/]+)$#', + 'pathStart' => '/soljt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH femtx' => [ + 0 => [ + 'name' => '', + 'path' => '/femtx/ntkzh/kppj/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/femtx/ntkzh/kppj/([^/]+)$#', + 'pathStart' => '/femtx/ntkzh/kppj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET rizd' => [ + 0 => [ + 'name' => '', + 'path' => '/rizd/xgyt/vq/s/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rizd/xgyt/vq/s/([^/]+)$#', + 'pathStart' => '/rizd/xgyt/vq/s/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH jcvb' => [ + 0 => [ + 'name' => '', + 'path' => '/jcvb/nbsuxj/hx/ezwr/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jcvb/nbsuxj/hx/ezwr/([^/]+)$#', + 'pathStart' => '/jcvb/nbsuxj/hx/ezwr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE llbas' => [ + 0 => [ + 'name' => '', + 'path' => '/llbas/uin/wulrkor/fo/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/llbas/uin/wulrkor/fo/([^/]+)$#', + 'pathStart' => '/llbas/uin/wulrkor/fo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET hzxxsflcd' => [ + 0 => [ + 'name' => '', + 'path' => '/hzxxsflcd/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hzxxsflcd/([^/]+)$#', + 'pathStart' => '/hzxxsflcd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST msonk' => [ + 0 => [ + 'name' => '', + 'path' => '/msonk/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/msonk/([^/]+)$#', + 'pathStart' => '/msonk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST jqtni' => [ + 0 => [ + 'name' => '', + 'path' => '/jqtni/jvg/mfffs/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jqtni/jvg/mfffs/([^/]+)$#', + 'pathStart' => '/jqtni/jvg/mfffs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH bidssbj' => [ + 0 => [ + 'name' => '', + 'path' => '/bidssbj/jqlv/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/bidssbj/jqlv/([^/]+)$#', + 'pathStart' => '/bidssbj/jqlv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH gmjvnxye' => [ + 0 => [ + 'name' => '', + 'path' => '/gmjvnxye/jsi/zq/eef/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gmjvnxye/jsi/zq/eef/([^/]+)$#', + 'pathStart' => '/gmjvnxye/jsi/zq/eef/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE shupe' => [ + 0 => [ + 'name' => '', + 'path' => '/shupe/ntq/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/shupe/ntq/([^/]+)$#', + 'pathStart' => '/shupe/ntq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE exf' => [ + 0 => [ + 'name' => '', + 'path' => '/exf/bpgn/f/j/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/exf/bpgn/f/j/([^/]+)$#', + 'pathStart' => '/exf/bpgn/f/j/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE vznldezwg' => [ + 0 => [ + 'name' => '', + 'path' => '/vznldezwg/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vznldezwg/([^/]+)$#', + 'pathStart' => '/vznldezwg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH owbww' => [ + 0 => [ + 'name' => '', + 'path' => '/owbww/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/owbww/([^/]+)$#', + 'pathStart' => '/owbww/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH ialyl' => [ + 0 => [ + 'name' => '', + 'path' => '/ialyl/rd/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ialyl/rd/([^/]+)$#', + 'pathStart' => '/ialyl/rd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH f' => [ + 0 => [ + 'name' => '', + 'path' => '/f/jksiv/dwgintcc/kujqn/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/f/jksiv/dwgintcc/kujqn/([^/]+)$#', + 'pathStart' => '/f/jksiv/dwgintcc/kujqn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET zy' => [ + 0 => [ + 'name' => '', + 'path' => '/zy/bvsawcvi/o/iaanizyo/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zy/bvsawcvi/o/iaanizyo/([^/]+)$#', + 'pathStart' => '/zy/bvsawcvi/o/iaanizyo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET lvdrymc' => [ + 0 => [ + 'name' => '', + 'path' => '/lvdrymc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lvdrymc/([^/]+)$#', + 'pathStart' => '/lvdrymc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH gz' => [ + 0 => [ + 'name' => '', + 'path' => '/gz/stu/huwusipb/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gz/stu/huwusipb/([^/]+)$#', + 'pathStart' => '/gz/stu/huwusipb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT xu' => [ + 0 => [ + 'name' => '', + 'path' => '/xu/bqgbldya/tcsqe/ao/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xu/bqgbldya/tcsqe/ao/([^/]+)$#', + 'pathStart' => '/xu/bqgbldya/tcsqe/ao/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST nhidyffovpmdcmjlq' => [ + 0 => [ + 'name' => '', + 'path' => '/nhidyffovpmdcmjlq/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nhidyffovpmdcmjlq/([^/]+)$#', + 'pathStart' => '/nhidyffovpmdcmjlq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE n' => [ + 0 => [ + 'name' => '', + 'path' => '/n/f/snusgy/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/n/f/snusgy/([^/]+)$#', + 'pathStart' => '/n/f/snusgy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST kwknanu' => [ + 0 => [ + 'name' => '', + 'path' => '/kwknanu/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/kwknanu/([^/]+)$#', + 'pathStart' => '/kwknanu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH wwxevvdaohufoh' => [ + 0 => [ + 'name' => '', + 'path' => '/wwxevvdaohufoh/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wwxevvdaohufoh/([^/]+)$#', + 'pathStart' => '/wwxevvdaohufoh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT daisoyma' => [ + 0 => [ + 'name' => '', + 'path' => '/daisoyma/pxfgrjbzryqa/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/daisoyma/pxfgrjbzryqa/([^/]+)$#', + 'pathStart' => '/daisoyma/pxfgrjbzryqa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET silxrrnv' => [ + 0 => [ + 'name' => '', + 'path' => '/silxrrnv/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/silxrrnv/([^/]+)$#', + 'pathStart' => '/silxrrnv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH ytmubgxxqwvfddwar' => [ + 0 => [ + 'name' => '', + 'path' => '/ytmubgxxqwvfddwar/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ytmubgxxqwvfddwar/([^/]+)$#', + 'pathStart' => '/ytmubgxxqwvfddwar/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET oz' => [ + 0 => [ + 'name' => '', + 'path' => '/oz/qsfveftu/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/oz/qsfveftu/([^/]+)$#', + 'pathStart' => '/oz/qsfveftu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST dkcs' => [ + 0 => [ + 'name' => '', + 'path' => '/dkcs/hq/w/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dkcs/hq/w/([^/]+)$#', + 'pathStart' => '/dkcs/hq/w/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET pxnnitv' => [ + 0 => [ + 'name' => '', + 'path' => '/pxnnitv/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/pxnnitv/([^/]+)$#', + 'pathStart' => '/pxnnitv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT api' => [ + 0 => [ + 'name' => '', + 'path' => '/api/ioztodybpmmc/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ioztodybpmmc/([^/]+)$#', + 'pathStart' => '/api/ioztodybpmmc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/api/sppgatanzwps/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/sppgatanzwps/([^/]+)$#', + 'pathStart' => '/api/sppgatanzwps/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 2 => [ + 'name' => '', + 'path' => '/api/qghidcmiruwqnoi/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/qghidcmiruwqnoi/([^/]+)$#', + 'pathStart' => '/api/qghidcmiruwqnoi/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 3 => [ + 'name' => '', + 'path' => '/api/ctadbu/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/ctadbu/([^/]+)$#', + 'pathStart' => '/api/ctadbu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 4 => [ + 'name' => '', + 'path' => '/api/whxsggiuexvhljz/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/whxsggiuexvhljz/([^/]+)$#', + 'pathStart' => '/api/whxsggiuexvhljz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 5 => [ + 'name' => '', + 'path' => '/api/jchcormgding/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/jchcormgding/([^/]+)$#', + 'pathStart' => '/api/jchcormgding/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 6 => [ + 'name' => '', + 'path' => '/api/xkbvrfgmkmxo/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/api/xkbvrfgmkmxo/([^/]+)$#', + 'pathStart' => '/api/xkbvrfgmkmxo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST cszctcirmavisgfgg' => [ + 0 => [ + 'name' => '', + 'path' => '/cszctcirmavisgfgg/q/vv/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cszctcirmavisgfgg/q/vv/([^/]+)$#', + 'pathStart' => '/cszctcirmavisgfgg/q/vv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT xmolfzqelex' => [ + 0 => [ + 'name' => '', + 'path' => '/xmolfzqelex/vbqsotlk/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xmolfzqelex/vbqsotlk/([^/]+)$#', + 'pathStart' => '/xmolfzqelex/vbqsotlk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET sjey' => [ + 0 => [ + 'name' => '', + 'path' => '/sjey/d/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sjey/d/([^/]+)$#', + 'pathStart' => '/sjey/d/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT jpw' => [ + 0 => [ + 'name' => '', + 'path' => '/jpw/o/lllw/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/jpw/o/lllw/([^/]+)$#', + 'pathStart' => '/jpw/o/lllw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT tpbcssmmzif' => [ + 0 => [ + 'name' => '', + 'path' => '/tpbcssmmzif/hov/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/tpbcssmmzif/hov/([^/]+)$#', + 'pathStart' => '/tpbcssmmzif/hov/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH rkr' => [ + 0 => [ + 'name' => '', + 'path' => '/rkr/ygon/bn/txwwcmudlyb/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/rkr/ygon/bn/txwwcmudlyb/([^/]+)$#', + 'pathStart' => '/rkr/ygon/bn/txwwcmudlyb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET umnqwjjaj' => [ + 0 => [ + 'name' => '', + 'path' => '/umnqwjjaj/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/umnqwjjaj/([^/]+)$#', + 'pathStart' => '/umnqwjjaj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT m' => [ + 0 => [ + 'name' => '', + 'path' => '/m/htybivzcebzq/cgdc/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/m/htybivzcebzq/cgdc/([^/]+)$#', + 'pathStart' => '/m/htybivzcebzq/cgdc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT nepqiy' => [ + 0 => [ + 'name' => '', + 'path' => '/nepqiy/h/wdfbpy/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nepqiy/h/wdfbpy/([^/]+)$#', + 'pathStart' => '/nepqiy/h/wdfbpy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET nuuzupbltth' => [ + 0 => [ + 'name' => '', + 'path' => '/nuuzupbltth/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nuuzupbltth/([^/]+)$#', + 'pathStart' => '/nuuzupbltth/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH sdcmo' => [ + 0 => [ + 'name' => '', + 'path' => '/sdcmo/x/orzqvh/hcouufv/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sdcmo/x/orzqvh/hcouufv/([^/]+)$#', + 'pathStart' => '/sdcmo/x/orzqvh/hcouufv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH frg' => [ + 0 => [ + 'name' => '', + 'path' => '/frg/xht/sbhf/avvbxdf/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/frg/xht/sbhf/avvbxdf/([^/]+)$#', + 'pathStart' => '/frg/xht/sbhf/avvbxdf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE bizxtymuld' => [ + 0 => [ + 'name' => '', + 'path' => '/bizxtymuld/zefptc/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/bizxtymuld/zefptc/([^/]+)$#', + 'pathStart' => '/bizxtymuld/zefptc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH dyiwqvtv' => [ + 0 => [ + 'name' => '', + 'path' => '/dyiwqvtv/s/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dyiwqvtv/s/([^/]+)$#', + 'pathStart' => '/dyiwqvtv/s/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT gpkviok' => [ + 0 => [ + 'name' => '', + 'path' => '/gpkviok/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gpkviok/([^/]+)$#', + 'pathStart' => '/gpkviok/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE hfinhap' => [ + 0 => [ + 'name' => '', + 'path' => '/hfinhap/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hfinhap/([^/]+)$#', + 'pathStart' => '/hfinhap/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET vk' => [ + 0 => [ + 'name' => '', + 'path' => '/vk/tsmuzmuq/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vk/tsmuzmuq/([^/]+)$#', + 'pathStart' => '/vk/tsmuzmuq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH ddnjner' => [ + 0 => [ + 'name' => '', + 'path' => '/ddnjner/bkin/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ddnjner/bkin/([^/]+)$#', + 'pathStart' => '/ddnjner/bkin/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH otlu' => [ + 0 => [ + 'name' => '', + 'path' => '/otlu/oqzn/m/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/otlu/oqzn/m/([^/]+)$#', + 'pathStart' => '/otlu/oqzn/m/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET nrxf' => [ + 0 => [ + 'name' => '', + 'path' => '/nrxf/ksd/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nrxf/ksd/([^/]+)$#', + 'pathStart' => '/nrxf/ksd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST hdpcl' => [ + 0 => [ + 'name' => '', + 'path' => '/hdpcl/koifodupgs/s/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hdpcl/koifodupgs/s/([^/]+)$#', + 'pathStart' => '/hdpcl/koifodupgs/s/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT mcptvfcc' => [ + 0 => [ + 'name' => '', + 'path' => '/mcptvfcc/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mcptvfcc/([^/]+)$#', + 'pathStart' => '/mcptvfcc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH zxro' => [ + 0 => [ + 'name' => '', + 'path' => '/zxro/pvh/ji/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zxro/pvh/ji/([^/]+)$#', + 'pathStart' => '/zxro/pvh/ji/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE vt' => [ + 0 => [ + 'name' => '', + 'path' => '/vt/p/vjztyc/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vt/p/vjztyc/([^/]+)$#', + 'pathStart' => '/vt/p/vjztyc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH zugmoct' => [ + 0 => [ + 'name' => '', + 'path' => '/zugmoct/hepxbaihrmkxl/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zugmoct/hepxbaihrmkxl/([^/]+)$#', + 'pathStart' => '/zugmoct/hepxbaihrmkxl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST vilqgu' => [ + 0 => [ + 'name' => '', + 'path' => '/vilqgu/p/lcjxkgiqcbfb/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vilqgu/p/lcjxkgiqcbfb/([^/]+)$#', + 'pathStart' => '/vilqgu/p/lcjxkgiqcbfb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET sjskrtkub' => [ + 0 => [ + 'name' => '', + 'path' => '/sjskrtkub/bpxknpofwc/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sjskrtkub/bpxknpofwc/([^/]+)$#', + 'pathStart' => '/sjskrtkub/bpxknpofwc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET zrmlgsykex' => [ + 0 => [ + 'name' => '', + 'path' => '/zrmlgsykex/vbj/nv/tvghn/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zrmlgsykex/vbj/nv/tvghn/([^/]+)$#', + 'pathStart' => '/zrmlgsykex/vbj/nv/tvghn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT hklqorlgkw' => [ + 0 => [ + 'name' => '', + 'path' => '/hklqorlgkw/jnsb/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hklqorlgkw/jnsb/([^/]+)$#', + 'pathStart' => '/hklqorlgkw/jnsb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT hazb' => [ + 0 => [ + 'name' => '', + 'path' => '/hazb/bpzdqr/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hazb/bpzdqr/([^/]+)$#', + 'pathStart' => '/hazb/bpzdqr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE eunzqcaxswb' => [ + 0 => [ + 'name' => '', + 'path' => '/eunzqcaxswb/wswkz/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/eunzqcaxswb/wswkz/([^/]+)$#', + 'pathStart' => '/eunzqcaxswb/wswkz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST ihwlkkn' => [ + 0 => [ + 'name' => '', + 'path' => '/ihwlkkn/m/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ihwlkkn/m/([^/]+)$#', + 'pathStart' => '/ihwlkkn/m/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST qohgt' => [ + 0 => [ + 'name' => '', + 'path' => '/qohgt/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qohgt/([^/]+)$#', + 'pathStart' => '/qohgt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH vroz' => [ + 0 => [ + 'name' => '', + 'path' => '/vroz/rryip/bpxez/mn/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vroz/rryip/bpxez/mn/([^/]+)$#', + 'pathStart' => '/vroz/rryip/bpxez/mn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT lspsrgbdol' => [ + 0 => [ + 'name' => '', + 'path' => '/lspsrgbdol/eaxk/eab/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lspsrgbdol/eaxk/eab/([^/]+)$#', + 'pathStart' => '/lspsrgbdol/eaxk/eab/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET aumke' => [ + 0 => [ + 'name' => '', + 'path' => '/aumke/smumjzo/oszjrj/pz/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/aumke/smumjzo/oszjrj/pz/([^/]+)$#', + 'pathStart' => '/aumke/smumjzo/oszjrj/pz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET flekhtsmoprq' => [ + 0 => [ + 'name' => '', + 'path' => '/flekhtsmoprq/mupfk/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/flekhtsmoprq/mupfk/([^/]+)$#', + 'pathStart' => '/flekhtsmoprq/mupfk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH wizzuye' => [ + 0 => [ + 'name' => '', + 'path' => '/wizzuye/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wizzuye/([^/]+)$#', + 'pathStart' => '/wizzuye/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH umcvhgfhu' => [ + 0 => [ + 'name' => '', + 'path' => '/umcvhgfhu/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/umcvhgfhu/([^/]+)$#', + 'pathStart' => '/umcvhgfhu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET uetljhrz' => [ + 0 => [ + 'name' => '', + 'path' => '/uetljhrz/yk/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/uetljhrz/yk/([^/]+)$#', + 'pathStart' => '/uetljhrz/yk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST qdxsks' => [ + 0 => [ + 'name' => '', + 'path' => '/qdxsks/fbsebysgkyuji/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qdxsks/fbsebysgkyuji/([^/]+)$#', + 'pathStart' => '/qdxsks/fbsebysgkyuji/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT ntpexw' => [ + 0 => [ + 'name' => '', + 'path' => '/ntpexw/nqa/vq/q/n/tpcjqqd/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ntpexw/nqa/vq/q/n/tpcjqqd/([^/]+)$#', + 'pathStart' => '/ntpexw/nqa/vq/q/n/tpcjqqd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET g' => [ + 0 => [ + 'name' => '', + 'path' => '/g/m/jvxhtustv/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/g/m/jvxhtustv/([^/]+)$#', + 'pathStart' => '/g/m/jvxhtustv/', + 'chains' => [ + ], + 'options' => [ + ], + ], + 1 => [ + 'name' => '', + 'path' => '/g/vi/e/mo/jso/yz/jhzxk/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/g/vi/e/mo/jso/yz/jhzxk/([^/]+)$#', + 'pathStart' => '/g/vi/e/mo/jso/yz/jhzxk/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET cwhbl' => [ + 0 => [ + 'name' => '', + 'path' => '/cwhbl/kwbp/zo/ql/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cwhbl/kwbp/zo/ql/([^/]+)$#', + 'pathStart' => '/cwhbl/kwbp/zo/ql/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET t' => [ + 0 => [ + 'name' => '', + 'path' => '/t/negubbnbk/onrdevheo/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/t/negubbnbk/onrdevheo/([^/]+)$#', + 'pathStart' => '/t/negubbnbk/onrdevheo/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET nwaxx' => [ + 0 => [ + 'name' => '', + 'path' => '/nwaxx/mncf/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nwaxx/mncf/([^/]+)$#', + 'pathStart' => '/nwaxx/mncf/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT etmoimkp' => [ + 0 => [ + 'name' => '', + 'path' => '/etmoimkp/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/etmoimkp/([^/]+)$#', + 'pathStart' => '/etmoimkp/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT exulcojsm' => [ + 0 => [ + 'name' => '', + 'path' => '/exulcojsm/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/exulcojsm/([^/]+)$#', + 'pathStart' => '/exulcojsm/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT dornauvgtbs' => [ + 0 => [ + 'name' => '', + 'path' => '/dornauvgtbs/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dornauvgtbs/([^/]+)$#', + 'pathStart' => '/dornauvgtbs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT z' => [ + 0 => [ + 'name' => '', + 'path' => '/z/gqjbadlnp/towsjt/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/z/gqjbadlnp/towsjt/([^/]+)$#', + 'pathStart' => '/z/gqjbadlnp/towsjt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET lzmsgf' => [ + 0 => [ + 'name' => '', + 'path' => '/lzmsgf/g/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lzmsgf/g/([^/]+)$#', + 'pathStart' => '/lzmsgf/g/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST memn' => [ + 0 => [ + 'name' => '', + 'path' => '/memn/fic/ow/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/memn/fic/ow/([^/]+)$#', + 'pathStart' => '/memn/fic/ow/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE mj' => [ + 0 => [ + 'name' => '', + 'path' => '/mj/entbl/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mj/entbl/([^/]+)$#', + 'pathStart' => '/mj/entbl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET p' => [ + 0 => [ + 'name' => '', + 'path' => '/p/hlhjlshdh/jxvy/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/p/hlhjlshdh/jxvy/([^/]+)$#', + 'pathStart' => '/p/hlhjlshdh/jxvy/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE qleuqih' => [ + 0 => [ + 'name' => '', + 'path' => '/qleuqih/ido/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qleuqih/ido/([^/]+)$#', + 'pathStart' => '/qleuqih/ido/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET sb' => [ + 0 => [ + 'name' => '', + 'path' => '/sb/kmbal/hteshhebeuqh/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sb/kmbal/hteshhebeuqh/([^/]+)$#', + 'pathStart' => '/sb/kmbal/hteshhebeuqh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE cocxaax' => [ + 0 => [ + 'name' => '', + 'path' => '/cocxaax/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cocxaax/([^/]+)$#', + 'pathStart' => '/cocxaax/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT xi' => [ + 0 => [ + 'name' => '', + 'path' => '/xi/yiqscwev/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xi/yiqscwev/([^/]+)$#', + 'pathStart' => '/xi/yiqscwev/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST ozrhu' => [ + 0 => [ + 'name' => '', + 'path' => '/ozrhu/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ozrhu/([^/]+)$#', + 'pathStart' => '/ozrhu/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET mekzam' => [ + 0 => [ + 'name' => '', + 'path' => '/mekzam/apy/alogysm/hzdx/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/mekzam/apy/alogysm/hzdx/([^/]+)$#', + 'pathStart' => '/mekzam/apy/alogysm/hzdx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH emaul' => [ + 0 => [ + 'name' => '', + 'path' => '/emaul/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/emaul/([^/]+)$#', + 'pathStart' => '/emaul/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST pakmoub' => [ + 0 => [ + 'name' => '', + 'path' => '/pakmoub/hpwe/inoiuwk/x/b/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/pakmoub/hpwe/inoiuwk/x/b/([^/]+)$#', + 'pathStart' => '/pakmoub/hpwe/inoiuwk/x/b/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET uk' => [ + 0 => [ + 'name' => '', + 'path' => '/uk/uiutjrh/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/uk/uiutjrh/([^/]+)$#', + 'pathStart' => '/uk/uiutjrh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET vqqwjg' => [ + 0 => [ + 'name' => '', + 'path' => '/vqqwjg/rhy/ryckwv/yil/j/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/vqqwjg/rhy/ryckwv/yil/j/([^/]+)$#', + 'pathStart' => '/vqqwjg/rhy/ryckwv/yil/j/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET ajzeglvbyosubbp' => [ + 0 => [ + 'name' => '', + 'path' => '/ajzeglvbyosubbp/e/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ajzeglvbyosubbp/e/([^/]+)$#', + 'pathStart' => '/ajzeglvbyosubbp/e/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET adsxmwgd' => [ + 0 => [ + 'name' => '', + 'path' => '/adsxmwgd/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/adsxmwgd/([^/]+)$#', + 'pathStart' => '/adsxmwgd/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT anu' => [ + 0 => [ + 'name' => '', + 'path' => '/anu/fyydmyqzqgbctnryr/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/anu/fyydmyqzqgbctnryr/([^/]+)$#', + 'pathStart' => '/anu/fyydmyqzqgbctnryr/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE nzydmurj' => [ + 0 => [ + 'name' => '', + 'path' => '/nzydmurj/aiwksdosrjs/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/nzydmurj/aiwksdosrjs/([^/]+)$#', + 'pathStart' => '/nzydmurj/aiwksdosrjs/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH xep' => [ + 0 => [ + 'name' => '', + 'path' => '/xep/cmjb/urz/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xep/cmjb/urz/([^/]+)$#', + 'pathStart' => '/xep/cmjb/urz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT uzc' => [ + 0 => [ + 'name' => '', + 'path' => '/uzc/msn/m/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/uzc/msn/m/([^/]+)$#', + 'pathStart' => '/uzc/msn/m/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PUT ipwwoo' => [ + 0 => [ + 'name' => '', + 'path' => '/ipwwoo/c/{name}', + 'method' => 'PUT', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/ipwwoo/c/([^/]+)$#', + 'pathStart' => '/ipwwoo/c/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET yjzhkmgcswlwwt' => [ + 0 => [ + 'name' => '', + 'path' => '/yjzhkmgcswlwwt/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yjzhkmgcswlwwt/([^/]+)$#', + 'pathStart' => '/yjzhkmgcswlwwt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH pdpv' => [ + 0 => [ + 'name' => '', + 'path' => '/pdpv/oscm/jrt/bl/g/jt/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/pdpv/oscm/jrt/bl/g/jt/([^/]+)$#', + 'pathStart' => '/pdpv/oscm/jrt/bl/g/jt/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET yqz' => [ + 0 => [ + 'name' => '', + 'path' => '/yqz/yqvezjwnqhq/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/yqz/yqvezjwnqhq/([^/]+)$#', + 'pathStart' => '/yqz/yqvezjwnqhq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH znvfof' => [ + 0 => [ + 'name' => '', + 'path' => '/znvfof/h/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/znvfof/h/([^/]+)$#', + 'pathStart' => '/znvfof/h/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST t' => [ + 0 => [ + 'name' => '', + 'path' => '/t/dlbsawmoatbwzkz/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/t/dlbsawmoatbwzkz/([^/]+)$#', + 'pathStart' => '/t/dlbsawmoatbwzkz/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET cprueecxrz' => [ + 0 => [ + 'name' => '', + 'path' => '/cprueecxrz/gyufduzvhj/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/cprueecxrz/gyufduzvhj/([^/]+)$#', + 'pathStart' => '/cprueecxrz/gyufduzvhj/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH skjlrgn' => [ + 0 => [ + 'name' => '', + 'path' => '/skjlrgn/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/skjlrgn/([^/]+)$#', + 'pathStart' => '/skjlrgn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'PATCH qprkhocgb' => [ + 0 => [ + 'name' => '', + 'path' => '/qprkhocgb/{name}', + 'method' => 'PATCH', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/qprkhocgb/([^/]+)$#', + 'pathStart' => '/qprkhocgb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE pesbmx' => [ + 0 => [ + 'name' => '', + 'path' => '/pesbmx/hg/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/pesbmx/hg/([^/]+)$#', + 'pathStart' => '/pesbmx/hg/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET sdswsgacg' => [ + 0 => [ + 'name' => '', + 'path' => '/sdswsgacg/kufceek/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sdswsgacg/kufceek/([^/]+)$#', + 'pathStart' => '/sdswsgacg/kufceek/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET kqtxdoxik' => [ + 0 => [ + 'name' => '', + 'path' => '/kqtxdoxik/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/kqtxdoxik/([^/]+)$#', + 'pathStart' => '/kqtxdoxik/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET zkwumlfppjn' => [ + 0 => [ + 'name' => '', + 'path' => '/zkwumlfppjn/loh/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/zkwumlfppjn/loh/([^/]+)$#', + 'pathStart' => '/zkwumlfppjn/loh/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE lpkidgqq' => [ + 0 => [ + 'name' => '', + 'path' => '/lpkidgqq/nilf/hysddpzw/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/lpkidgqq/nilf/hysddpzw/([^/]+)$#', + 'pathStart' => '/lpkidgqq/nilf/hysddpzw/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE xhrefsc' => [ + 0 => [ + 'name' => '', + 'path' => '/xhrefsc/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xhrefsc/([^/]+)$#', + 'pathStart' => '/xhrefsc/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST hz' => [ + 0 => [ + 'name' => '', + 'path' => '/hz/ah/mftb/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/hz/ah/mftb/([^/]+)$#', + 'pathStart' => '/hz/ah/mftb/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE xohxbjghx' => [ + 0 => [ + 'name' => '', + 'path' => '/xohxbjghx/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xohxbjghx/([^/]+)$#', + 'pathStart' => '/xohxbjghx/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET chtz' => [ + 0 => [ + 'name' => '', + 'path' => '/chtz/hddhmj/amdlazy/bq/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/chtz/hddhmj/amdlazy/bq/([^/]+)$#', + 'pathStart' => '/chtz/hddhmj/amdlazy/bq/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET xgdbgah' => [ + 0 => [ + 'name' => '', + 'path' => '/xgdbgah/y/t/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/xgdbgah/y/t/([^/]+)$#', + 'pathStart' => '/xgdbgah/y/t/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE dg' => [ + 0 => [ + 'name' => '', + 'path' => '/dg/ewn/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/dg/ewn/([^/]+)$#', + 'pathStart' => '/dg/ewn/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST wk' => [ + 0 => [ + 'name' => '', + 'path' => '/wk/msqo/xzdaw/xa/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wk/msqo/xzdaw/xa/([^/]+)$#', + 'pathStart' => '/wk/msqo/xzdaw/xa/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'POST wgegghqbzohkee' => [ + 0 => [ + 'name' => '', + 'path' => '/wgegghqbzohkee/{name}', + 'method' => 'POST', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/wgegghqbzohkee/([^/]+)$#', + 'pathStart' => '/wgegghqbzohkee/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET fjuosgmzwokao' => [ + 0 => [ + 'name' => '', + 'path' => '/fjuosgmzwokao/d/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/fjuosgmzwokao/d/([^/]+)$#', + 'pathStart' => '/fjuosgmzwokao/d/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'GET gthgwsnpwd' => [ + 0 => [ + 'name' => '', + 'path' => '/gthgwsnpwd/pmt/is/z/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/gthgwsnpwd/pmt/is/z/([^/]+)$#', + 'pathStart' => '/gthgwsnpwd/pmt/is/z/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], + 'DELETE sifyfl' => [ + 0 => [ + 'name' => '', + 'path' => '/sifyfl/gowrdioqbafnyl/{name}', + 'method' => 'DELETE', + 'handler' => 'handler_func', + 'bindVars' => [ + ], + 'params' => [ + ], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/sifyfl/gowrdioqbafnyl/([^/]+)$#', + 'pathStart' => '/sifyfl/gowrdioqbafnyl/', + 'chains' => [ + ], + 'options' => [ + ], + ], + ], +], +// vague routes +'vagueRoutes' => [ +], +]; diff --git a/example/cached/routes-cache.php b/example/cached/routes-cache.php new file mode 100644 index 0000000..f46b24f --- /dev/null +++ b/example/cached/routes-cache.php @@ -0,0 +1,645 @@ + [ + 'GET /routes' => [ + 'path' => '/routes', + 'method' => 'GET', + 'handler' => 'dump_routes', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'GET /*' => [ + 'path' => '/*', + 'method' => 'GET', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'POST /*' => [ + 'path' => '/*', + 'method' => 'POST', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'PUT /*' => [ + 'path' => '/*', + 'method' => 'PUT', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'PATCH /*' => [ + 'path' => '/*', + 'method' => 'PATCH', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'DELETE /*' => [ + 'path' => '/*', + 'method' => 'DELETE', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'OPTIONS /*' => [ + 'path' => '/*', + 'method' => 'OPTIONS', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'HEAD /*' => [ + 'path' => '/*', + 'method' => 'HEAD', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'CONNECT /*' => [ + 'path' => '/*', + 'method' => 'CONNECT', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'GET /' => [ + 'path' => '/', + 'method' => 'GET', + 'handler' => 'handler0', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'GET /home' => [ + 'path' => '/home', + 'method' => 'GET', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController@index', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'POST /post' => [ + 'path' => '/post', + 'method' => 'POST', + 'handler' => 'post_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'PUT /put' => [ + 'path' => '/put', + 'method' => 'PUT', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'DELETE /del' => [ + 'path' => '/del', + 'method' => 'DELETE', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'POST /pd' => [ + 'path' => '/pd', + 'method' => 'POST', + 'handler' => 'multi_method_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'DELETE /pd' => [ + 'path' => '/pd', + 'method' => 'DELETE', + 'handler' => 'multi_method_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'GET /user/login' => [ + 'path' => '/user/login', + 'method' => 'GET', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 'POST /user/login' => [ + 'path' => '/user/login', + 'method' => 'POST', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + ], +// regular routes + 'regularRoutes' => [ + 'GET 50be3774f6' => [ + 0 => [ + 'path' => '/50be3774f6/{arg1}/{arg2}/{arg3}/{arg4}/{arg5}/{arg6}/{arg7}/{arg8}/{arg9}/850726135a', + 'method' => 'GET', + 'handler' => 'handler0', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'arg1', + 1 => 'arg2', + 2 => 'arg3', + 3 => 'arg4', + 4 => 'arg5', + 5 => 'arg6', + 6 => 'arg7', + 7 => 'arg8', + 8 => 'arg9', + ], + 'pathRegex' => '#^/50be3774f6/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/850726135a$#', + 'pathStart' => '/50be3774f6/', + 'chains' => [], + 'options' => [], + ], + ], + 'GET user' => [ + 0 => [ + 'path' => '/user/{id}/followers', + 'method' => 'GET', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'id', + ], + 'pathRegex' => '#^/user/([^/]+)/followers$#', + 'pathStart' => '/user/', + 'chains' => [], + 'options' => [], + ], + 1 => [ + 'path' => '/user/detail/{id}', + 'method' => 'GET', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'id', + ], + 'pathRegex' => '#^/user/detail/([^/]+)$#', + 'pathStart' => '/user/detail/', + 'chains' => [], + 'options' => [], + ], + 2 => [ + 'path' => '/user/{id}', + 'method' => 'GET', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'id', + ], + 'pathRegex' => '#^/user/([^/]+)$#', + 'pathStart' => '/user/', + 'chains' => [], + 'options' => [], + ], + 3 => [ + 'path' => '/user/{some}', + 'method' => 'GET', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'some', + ], + 'pathRegex' => '#^/user/([^/]+)$#', + 'pathStart' => '/user/', + 'chains' => [], + 'options' => [], + ], + ], + 'PUT user' => [ + 0 => [ + 'path' => '/user/detail/{id}', + 'method' => 'PUT', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'id', + ], + 'pathRegex' => '#^/user/detail/([^/]+)$#', + 'pathStart' => '/user/detail/', + 'chains' => [], + 'options' => [], + ], + 1 => [ + 'path' => '/user/{id}', + 'method' => 'PUT', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'id', + ], + 'pathRegex' => '#^/user/([^/]+)$#', + 'pathStart' => '/user/', + 'chains' => [], + 'options' => [], + ], + ], + 'POST user' => [ + 0 => [ + 'path' => '/user/{id}', + 'method' => 'POST', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'id', + ], + 'pathRegex' => '#^/user/([^/]+)$#', + 'pathStart' => '/user/', + 'chains' => [], + 'options' => [], + ], + ], + 'DELETE user' => [ + 0 => [ + 'path' => '/user/{id}', + 'method' => 'DELETE', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'id', + ], + 'pathRegex' => '#^/user/([^/]+)$#', + 'pathStart' => '/user/', + 'chains' => [], + 'options' => [], + ], + ], + 'DELETE del' => [ + 0 => [ + 'path' => '/del/{uid}', + 'method' => 'DELETE', + 'handler' => 'main_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'uid', + ], + 'pathRegex' => '#^/del/([^/]+)$#', + 'pathStart' => '/del/', + 'chains' => [], + 'options' => [], + ], + ], + 'GET admin' => [ + 0 => [ + 'path' => '/admin/manage/getInfo[/id/{int}]', + 'method' => 'GET', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'int', + ], + 'pathRegex' => '#^/admin/manage/getInfo(?:/id/(\\d+))?$#', + 'pathStart' => '/admin/manage/getInfo', + 'chains' => [], + 'options' => [], + ], + ], + 'POST admin' => [ + 0 => [ + 'path' => '/admin/manage/getInfo[/id/{int}]', + 'method' => 'POST', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'int', + ], + 'pathRegex' => '#^/admin/manage/getInfo(?:/id/(\\d+))?$#', + 'pathStart' => '/admin/manage/getInfo', + 'chains' => [], + 'options' => [], + ], + ], + 'GET home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'GET', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + 'POST home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'POST', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + 'PUT home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'PUT', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + 'PATCH home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'PATCH', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + 'DELETE home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'DELETE', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + 'OPTIONS home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'OPTIONS', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + 'HEAD home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'HEAD', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + 'CONNECT home' => [ + 0 => [ + 'path' => '/home/{act}', + 'method' => 'CONNECT', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'act', + ], + 'pathRegex' => '#^/home/([a-zA-Z][\\w-]+)$#', + 'pathStart' => '/home/', + 'chains' => [], + 'options' => [], + ], + ], + ], +// vague routes + 'vagueRoutes' => [ + 'GET' => [ + 0 => [ + 'path' => '/{name}', + 'method' => 'GET', + 'handler' => 'default_handler', + 'bindVars' => [ + 'name' => 'blog|saying', + ], + 'params' => [], + 'pathVars' => [ + 0 => 'name', + ], + 'pathRegex' => '#^/(blog|saying)$#', + 'pathStart' => '', + 'chains' => [], + 'options' => [], + ], + 1 => [ + 'path' => '/about[.html]', + 'method' => 'GET', + 'handler' => 'Inhere\\Route\\Example\\Controllers\\HomeController@about', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '#^/about(?:\\.html)?$#', + 'pathStart' => '/about', + 'chains' => [], + 'options' => [], + ], + 2 => [ + 'path' => '/test[/optional]', + 'method' => 'GET', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '#^/test(?:/optional)?$#', + 'pathStart' => '/test', + 'chains' => [], + 'options' => [], + ], + 3 => [ + 'path' => '/blog-{post}', + 'method' => 'GET', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [ + 0 => 'post', + ], + 'pathRegex' => '#^/blog-([^/]+)$#', + 'pathStart' => '/blog-', + 'chains' => [], + 'options' => [], + ], + 4 => [ + 'path' => '/blog[/index]', + 'method' => 'GET', + 'handler' => 'default_handler', + 'bindVars' => [], + 'params' => [], + 'pathVars' => [], + 'pathRegex' => '#^/blog(?:/index)?$#', + 'pathStart' => '/blog', + 'chains' => [], + 'options' => [], + ], + 5 => [ + 'path' => '/my[/{name}[/{age}]]', + 'method' => 'GET', + 'handler' => 'my_handler', + 'bindVars' => [ + 'age' => '\\d+', + ], + 'params' => [], + 'pathVars' => [ + 0 => 'name', + 1 => 'age', + ], + 'pathRegex' => '#^/my(?:/([^/]+)(?:/(\\d+))?)?$#', + 'pathStart' => '/my', + 'chains' => [], + 'options' => [ + 'defaults' => [ + 'name' => 'God', + 'age' => 25, + ], + ], + ], + ], + ], +]; diff --git a/example/object.php b/example/object.php new file mode 100644 index 0000000..6b7834c --- /dev/null +++ b/example/object.php @@ -0,0 +1,83 @@ +config([ + // 'ignoreLastSlash' => true, + // 'tmpCacheNumber' => 100, + + // enable autoRoute + // you can access '/demo' '/admin/user/info', Don't need to configure any route + 'autoRoute' => 1, + 'controllerNamespace' => 'Inhere\RouteTest\Controllers', + 'controllerSuffix' => 'Controller', +]); + +$router->get('/routes', function () { + global $router; + echo "
{$router->__toString()}
"; +}); + +$hasRouter = true; +require __DIR__ . '/some-routes.php'; + +// $router->rest('/rest', RestController::class); + +// $router->any('*', function () { +// echo "This is fallback handler\n"; +// }); + +// var_dump($router);die; + +$dispatcher = new Dispatcher([ + 'dynamicAction' => true, + // on notFound, output a message. + Dispatcher::ON_NOT_FOUND => function ($path) { + echo "the page $path not found!"; + } +]); + +// OR register event by `Dispatcher::on()` +// $dispatcher->on(Dispatcher::ON_NOT_FOUND, function ($path) { +// echo "the page $path not found!"; +// }); + +/* +method 1 + +$dispatcher->setRouter($router); +$dispatcher->dispatch(); + */ + +/* +method 2 + */ +$router->dispatch($dispatcher); + +/* +method 3 + +$router->dispatch([ + 'dynamicAction' => true, + Dispatcher::ON_NOT_FOUND => function ($path) { + echo "the page $path not found!"; + } +]); + */ diff --git a/example/pre-match.php b/example/pre-match.php new file mode 100644 index 0000000..2a5c41b --- /dev/null +++ b/example/pre-match.php @@ -0,0 +1,84 @@ +setRequest(); + +// set config +$router->config([ + // 'ignoreLastSlash' => true, + // 'tmpCacheNumber' => 100, + + // enable autoRoute + // you can access '/demo' '/admin/user/info', Don't need to configure any route + 'autoRoute' => 1, + 'controllerNamespace' => 'Inhere\RouteTest\Controllers', + 'controllerSuffix' => 'Controller', +]); + +$router->get('/routes', function () { + global $router; + echo "
{$router->toString()}
"; +}); + +$hasRouter = true; +require __DIR__ . '/some-routes.php'; + +// $router->rest('/rest', RestController::class); + +$router->any('*', function () { + echo "This is fallback handler\n"; +}); + +// var_dump($router);die; + +$dispatcher = new Dispatcher([ + 'dynamicAction' => true, + // on notFound, output a message. + Dispatcher::ON_NOT_FOUND => function ($path) { + echo "the page $path not found!"; + } +]); + +// OR register event by `Dispatcher::on()` +// $dispatcher->on(Dispatcher::ON_NOT_FOUND, function ($path) { +// echo "the page $path not found!"; +// }); + +/* +method 1 + +$dispatcher->setRouter($router); +$dispatcher->dispatch(); + */ + +/* +method 2 + */ +$router->dispatch($dispatcher); + +/* +method 3 + +$router->dispatch([ + 'dynamicAction' => true, + Dispatcher::ON_NOT_FOUND => function ($path) { + echo "the page $path not found!"; + } +]); + */ diff --git a/examples/some-routes.php b/example/some-routes.php similarity index 65% rename from examples/some-routes.php rename to example/some-routes.php index 871a466..947539d 100644 --- a/examples/some-routes.php +++ b/example/some-routes.php @@ -1,4 +1,4 @@ - [ - 'name' => 'blog|saying' - ] + 'name' => 'blog|saying' ] ], // optional param + [ + 'GET', + '/about[.html]', + HomeController::class . '@about' + ], [ 'GET', '/test[/optional]', @@ -112,7 +157,7 @@ function my_handler(array $args) { ], [ 'GET', - '/blog[index]', + '/blog[/index]', 'default_handler' ], /* @@ -126,9 +171,9 @@ function my_handler(array $args) { '/my[/{name}[/{age}]]', 'my_handler', [ - 'params' => [ - 'age' => '\d+' - ], + 'age' => '\d+' + ], + [ 'defaults' => [ 'name' => 'God', 'age' => 25, @@ -144,16 +189,11 @@ function my_handler(array $args) { 'GET', '/hello[/{name}]', function ($args) { - $n = isset($args['name']) ? $args['name'] : 'NO'; + $n = $args['name'] ?? 'NO'; echo "hello, {$n}"; // 'john' }, [ - 'params' => [ - 'name' => '\w+' - ], - 'defaults' => [ - 'name' => 'default val' - ] + 'name' => '\w+' ] ], // can match '/home/test', but not match '/home' @@ -191,4 +231,23 @@ function () { ]; -return $routes; +// has router instance +if (isset($hasRouter) && $hasRouter) { + foreach ($routes as $route) { + // group + if (is_array($route[1])) { + $rs = $route[1]; + $router->group($route[0], function (RouterInterface $router) use ($rs) { + foreach ($rs as $r) { + $router->map($r[0], $r[1], $r[2], $r[3] ?? [], $r[4] ?? []); + } + }); + + continue; + } + + $router->map($route[0], $route[1], $route[2], $route[3] ?? [], $route[4] ?? []); + } +} else { + return $routes; +} diff --git a/examples/static.php b/example/static.php similarity index 57% rename from examples/static.php rename to example/static.php index 27964cf..2ee75a5 100644 --- a/examples/static.php +++ b/example/static.php @@ -1,4 +1,4 @@ - true, - -// 'matchAll' => '/', // a route path -// 'matchAll' => function () { -// echo 'System Maintaining ... ...'; -// }, - +SRouter::config([ + 'ignoreLastSlash' => true, // enable autoRoute // you can access '/demo' '/admin/user/info', Don't need to configure any route - 'autoRoute' => 1, - 'controllerNamespace' => 'Inhere\Route\Examples\Controllers', + 'autoRoute' => 1, + 'controllerNamespace' => 'Inhere\RouteTest\Controllers', 'controllerSuffix' => 'Controller', ]); @@ -39,18 +33,23 @@ // group if (is_array($route[1])) { $rs = $route[1]; - $router->group($route[0], function () use($rs){ + SRouter::group($route[0], function () use ($rs) { foreach ($rs as $r) { - SRouter::map($r[0], $r[1], $r[2], isset($r[3]) ? $r[3] : []); + SRouter::map($r[0], $r[1], $r[2], $r[3] ?? [], $r[4] ?? []); } }); continue; } - SRouter::map($route[0], $route[1], $route[2], isset($route[3]) ? $route[3] : []); + SRouter::map($route[0], $route[1], $route[2], $route[3] ?? [], $route[4] ?? []); } +SRouter::get('routes', function () { + $string = SRouter::getRouter()->__toString(); + echo "
{$string}
"; +}); + $dispatcher = new Dispatcher([ 'dynamicAction' => true, ]); diff --git a/example/swoole-server.php b/example/swoole-server.php new file mode 100644 index 0000000..133c4cf --- /dev/null +++ b/example/swoole-server.php @@ -0,0 +1,73 @@ +config([ + 'ignoreLastSlash' => true, + + 'tmpCacheNumber' => 100, + + // enable autoRoute + // you can access '/demo' '/admin/user/info', Don't need to configure any route + 'autoRoute' => 1, + 'controllerNamespace' => 'Inhere\RouteTest\Controllers', + 'controllerSuffix' => 'Controller', +]); + +$router->get('/routes', function () use ($router) { + return $router->toString(); +}); + +/** @var array $routes */ +$hasRouter = true; +$routes = require __DIR__ . '/some-routes.php'; + +$dispatcher = new Dispatcher([ + 'dynamicAction' => true, +]); +$dispatcher->setRouter($router); + +// on notFound, output a message. +$dispatcher->on(Dispatcher::ON_NOT_FOUND, function ($path) { + echo "the page $path not found!"; +}); + +$server = new \Swoole\Http\Server('127.0.0.1', '5675', SWOOLE_BASE); +$server->set([ + // +]); + +$server->on('request', function ($request, $response) use ($dispatcher) { + /** @var \Swoole\Http\Response $response */ + $uri = $request->server['request_uri']; + $method = $request->server['request_method']; + + // fwrite(STDOUT, "request $method $uri\n"); + + ob_start(); + $ret = $dispatcher->dispatchUri($uri, $method); + $content = ob_get_clean(); + + if (!$ret) { + $ret = $content; + } + + $response->end($ret); +}); + +echo "http server listen on http://127.0.0.1:5675\n"; +$server->start(); diff --git a/example/tests/compare_exec.php b/example/tests/compare_exec.php new file mode 100644 index 0000000..0e69694 --- /dev/null +++ b/example/tests/compare_exec.php @@ -0,0 +1,95 @@ + 0 ? 'Sample 2' : 'Sample 1'; + + printf( + "\n\t Speed Test Results(Faster is: %s)\n%s\n", + $faster, + str_repeat('---', 29) + ); + + $template = "%-12s %-22s %-25s %-20s\n"; + $results = [ + ['Test Name', 'Number of executions', 'Total time-consuming(us)', 'Average time-consuming(us)'], + ['Sample 1', $times, $total1, $average1], + ['Sample 2', $times, $total2, $average2], + ]; + + foreach ($results as $items) { + printf($template, ...$items); + } + + echo "\n"; +} diff --git a/example/tests/find_start_first.php b/example/tests/find_start_first.php new file mode 100644 index 0000000..01befa1 --- /dev/null +++ b/example/tests/find_start_first.php @@ -0,0 +1,12 @@ +get('/', function() { +$router->get('/', function () { echo 'hello, welcome'; }); $router->get('/test', 'test_handler'); -$router->get('/routes', function() use($router) { +$router->get('/routes', function () use ($router) { var_dump( $router->getStaticRoutes() ); @@ -28,6 +28,7 @@ ] ]); +// PHP Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed $encoded = serialize($router->getStaticRoutes()); var_dump($encoded); diff --git a/example/tests/test.php b/example/tests/test.php new file mode 100644 index 0000000..18c6986 --- /dev/null +++ b/example/tests/test.php @@ -0,0 +1,15 @@ + array ( - '/routes' => - array ( - 0 => - array ( - 'methods' => 'GET,', - 'handler' => 'dump_routes', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - '/' => - array ( - 0 => - array ( - 'methods' => 'GET,', - 'handler' => 'handler0', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - '/home' => - array ( - 0 => - array ( - 'methods' => 'GET,', - 'handler' => 'Inhere\\Route\\Examples\\Controllers\\HomeController@index', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - '/post' => - array ( - 0 => - array ( - 'methods' => 'POST,', - 'handler' => 'post_handler', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - '/pd' => - array ( - 0 => - array ( - 'methods' => 'POST,DELETE,', - 'handler' => 'multi_method_handler', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - '/user/login' => - array ( - 0 => - array ( - 'methods' => 'GET,POST,', - 'handler' => 'default_handler', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), -), - 'regularRoutes' => array ( - '50be3774f6' => - array ( - 0 => - array ( - 'regex' => '#^/50be3774f6/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/850726135a$#', - 'start' => '/50be3774f6/', - 'methods' => 'GET,', - 'handler' => 'handler0', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - 'about' => - array ( - 0 => - array ( - 'regex' => '#^/about(?:\\.html)?$#', - 'start' => '/about', - 'methods' => 'GET,', - 'handler' => 'Inhere\\Route\\Examples\\Controllers\\HomeController@about', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - 'test' => - array ( - 0 => - array ( - 'regex' => '#^/test(?:/optional)?$#', - 'start' => '/test', - 'methods' => 'GET,', - 'handler' => 'default_handler', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), - 'my' => - array ( - 0 => - array ( - 'regex' => '#^/my(?:/(?P[^/]+)(?:/(?P\\d+))?)?$#', - 'start' => '/my', - 'methods' => 'GET,', - 'handler' => 'my_handler', - 'option' => - array ( - 'params' => - array ( - 'age' => '\\d+', - ), - 'domains' => NULL, - 'defaults' => - array ( - 'name' => 'God', - 'age' => 25, - ), - ), - ), - ), - 'home' => - array ( - 0 => - array ( - 'regex' => '#^/home/(?P[a-zA-Z][\\w-]+)$#', - 'start' => '/home/', - 'methods' => 'ANY,GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD,SEARCH,CONNECT,TRACE,', - 'handler' => 'Inhere\\Route\\Examples\\Controllers\\HomeController', - 'option' => - array ( - 'params' => NULL, - 'domains' => NULL, - ), - ), - ), -), - 'vagueRoutes' => array ( - 0 => - array ( - 'regex' => '#^/(?Pblog|saying)$#', - 'include' => NULL, - 'methods' => 'GET,', - 'handler' => 'default_handler', - 'option' => - array ( - 'params' => - array ( - 'name' => 'blog|saying', - ), - 'domains' => NULL, - ), - ), -), -]; \ No newline at end of file diff --git a/examples/object.php b/examples/object.php deleted file mode 100644 index 0b00337..0000000 --- a/examples/object.php +++ /dev/null @@ -1,103 +0,0 @@ -setConfig([ - // 'ignoreLastSep' => true, - // 'tmpCacheNumber' => 100, - -// 'matchAll' => '/', // a route path -// 'matchAll' => function () { // a callback -// echo 'System Maintaining ... ...'; -// }, - - // enable autoRoute - // you can access '/demo' '/admin/user/info', Don't need to configure any route - 'autoRoute' => 1, - 'controllerNamespace' => 'Inhere\Route\Examples\Controllers', - 'controllerSuffix' => 'Controller', -]); - -$router->get('/routes', function() use($router) { - var_dump( - $router->getStaticRoutes(), - $router->getVagueRoutes() - ); - var_dump($router->getRegularRoutes()); -}); - -/** @var array $routes */ -$routes = require __DIR__ . '/some-routes.php'; - -foreach ($routes as $route) { - // group - if (is_array($route[1])) { - $rs = $route[1]; - $router->group($route[0], function (ORouter $router) use($rs){ - foreach ($rs as $r) { - $router->map($r[0], $r[1], $r[2], isset($r[3]) ? $r[3] : []); - } - }); - - continue; - } - - $router->map($route[0], $route[1], $route[2], isset($route[3]) ? $route[3] : []); -} - -// var_dump($router);die; - -$dispatcher = new Dispatcher([ - 'dynamicAction' => true, - // on notFound, output a message. - Dispatcher::ON_NOT_FOUND => function ($path) { - echo "the page $path not found!"; - } -]); - -// OR register event by `Dispatcher::on()` -// $dispatcher->on(Dispatcher::ON_NOT_FOUND, function ($path) { -// echo "the page $path not found!"; -// }); - -/* -method 1 - -$dispatcher->setMatcher(function ($path, $method) use($router) { - return $router->match($path, $method); -}); -$dispatcher->dispatch(); - */ - -/* -method 2 - */ -$router->dispatch($dispatcher); - -/* -method 3 - -$router->dispatch([ - 'dynamicAction' => true, - Dispatcher::ON_NOT_FOUND => function ($path) { - echo "the page $path not found!"; - } -]); - */ diff --git a/examples/simple-bench.php b/examples/simple-bench.php deleted file mode 100644 index 0035d39..0000000 --- a/examples/simple-bench.php +++ /dev/null @@ -1,33 +0,0 @@ -setConfig([ - 'ignoreLastSep' => true, - 'dynamicAction' => true, - - 'tmpCacheNumber' => 100, - -// 'matchAll' => '/', // a route path -// 'matchAll' => function () { -// echo 'System Maintaining ... ...'; -// }, - - // enable autoRoute - // you can access '/demo' '/admin/user/info', Don't need to configure any route - 'autoRoute' => 1, - 'controllerNamespace' => 'Inhere\Route\Examples\Controllers', - 'controllerSuffix' => 'Controller', -]); - - -$router->get('/routes', function() use($router) { - var_dump( - $router->getStaticRoutes(), - $router->getRegularRoutes(), - $router->getVagueRoutes() - ); -}); - -/** @var array $routes */ -$routes = require __DIR__ . '/some-routes.php'; - -foreach ($routes as $route) { - // group - if (is_array($route[1])) { - $rs = $route[1]; - $router->group($route[0], function (ORouter $router) use($rs){ - foreach ($rs as $r) { - $router->map($r[0], $r[1], $r[2], isset($r[3]) ? $r[3] : []); - } - }); - - continue; - } - - $router->map($route[0], $route[1], $route[2], isset($route[3]) ? $route[3] : []); -} - -$dispatcher = new Dispatcher([ - 'dynamicAction' => true, -], function ($path, $method) use ($router) { - return $router->match($path, $method); -}); - -// on notFound, output a message. -$dispatcher->on(Dispatcher::ON_NOT_FOUND, function ($path) { - echo "the page $path not found!"; -}); - -$server = new \Swoole\Http\Server('127.0.0.1', '5675', SWOOLE_BASE); -$server->set([ - -]); - -$server->on('request', function($request, $response) use($dispatcher) { - /** @var \Swoole\Http\Response $response */ - $uri = $request->server['request_uri']; - $method = $request->server['request_method']; - - fwrite(STDOUT, "request $method $uri\n"); - - ob_start(); - $ret = $dispatcher->dispatch($uri, $method); - $content = ob_get_clean(); - - if (!$ret) { - $ret = $content; - } - - $response->end($ret); -}); - -echo "http server listen on http://127.0.0.1:5675\n"; -$server->start(); diff --git a/examples/tests/quick_find.php b/examples/tests/quick_find.php deleted file mode 100644 index 35651d8..0000000 --- a/examples/tests/quick_find.php +++ /dev/null @@ -1,163 +0,0 @@ - '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), - array( - 'first' => '/hallo', - 'regex' => '#^/hello(?:/(\\w+))?$#', - 'method' => 'GET', - 'handler' => 'handler1', - 'option' => array( - 'params' => array( - 'name' => '\\w+', - ), - 'domains' => null, - 'schema' => null, - ), - ), -); - -foreach (gen($ary, 'hallo') as $key => $value) { - # code... -} - -function gen($ary, $path) -{ - if (($num = count($ary)) <= 30) { - return find($ary); - } - - array_chunk($ary, ceil($num/2)); - yield find($path); - yield find($path); -} - -function find($arr, $path) -{ - foreach ((array)$arr as $conf) { - if (0 === strpos($path, $conf['first']) && preg_match($conf['regex'], $path, $matches)) { - // method not allowed - if ($method !== $conf['method'] && self::ANY_METHOD !== $conf['method']) { - return false; - } - - $conf['matches'] = $matches; - - // cache latest $number routes. - if ($number > 0) { - if (count($this->routeCaches) === $number) { - array_shift($this->routeCaches); - } - - $this->routeCaches[$path][$conf['method']] = $conf; - } - - return [$path, $conf]; - } - } - - return false; -} diff --git a/php-run-with-debug.sh b/php-run-with-debug.sh new file mode 100644 index 0000000..05f50cd --- /dev/null +++ b/php-run-with-debug.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# profiler_enable - profiler功能的开关,默认值0,如果设为1,则每次请求都会生成一个性能报告文件。 +# export XDEBUG_CONFIG="profiler_enable=1" + +# xdebug.profiler_enable_trigger 默认值也是0,如果设为1 则当我们的请求中包含 XDEBUG_PROFILE 参数时才会生成性能报告文件 +export XDEBUG_CONFIG="profiler_enable_trigger=1" + +php $@ diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..750b37b --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,13 @@ + + + + + test/ + + + + + src + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 20b9c3f..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - ./tests/ - - - - - - ./examples - - - \ No newline at end of file diff --git a/public/README.md b/public/README.md new file mode 100644 index 0000000..1622deb --- /dev/null +++ b/public/README.md @@ -0,0 +1,9 @@ +# 示例 + +使用php启动一个测试server: + +```bash +php -S 127.0.0.1:8080 -t ./public +``` + +好了,现在你可以访问 http://127.0.0.1:8080 可以看到输出 `hello` diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..fd1da2f --- /dev/null +++ b/public/index.php @@ -0,0 +1,18 @@ +get('/', function() { + echo 'hello'; +}); + +// 开始调度运行 +$router->dispatch(); diff --git a/src/AbstractRouter.php b/src/AbstractRouter.php deleted file mode 100644 index 1ac64c9..0000000 --- a/src/AbstractRouter.php +++ /dev/null @@ -1,373 +0,0 @@ -get('/user/{num}', 'handler'); - * @var array - */ - protected static $globalParams = [ - 'any' => '[^/]+', // match any except '/' - 'num' => '[0-9]+', // match a number - 'id' => '[1-9][0-9]*', // match a ID number - 'act' => '[a-zA-Z][\w-]+', // match a action name - 'all' => '.*' - ]; - - /** - * validate and format arguments - * @param string|array $methods - * @param mixed $handler - * @return string - * @throws \InvalidArgumentException - */ - public static function validateArguments($methods, $handler) - { - if (!$methods || !$handler) { - throw new \InvalidArgumentException('The method and route handler is not allow empty.'); - } - - $allow = implode(',', self::SUPPORTED_METHODS) . ','; - $methods = array_map(function ($m) use($allow) { - $m = strtoupper(trim($m)); - - if (!$m || false === strpos($allow, $m . ',')) { - throw new \InvalidArgumentException("The method [$m] is not supported, Allow: $allow"); - } - - return $m; - }, (array)$methods); - - if (!\is_string($handler) && !\is_object($handler)) { - throw new \InvalidArgumentException('The route handler is not empty and type only allow: string,object'); - } - - if (\is_object($handler) && !\is_callable($handler)) { - throw new \InvalidArgumentException('The route object handler must be is callable'); - } - - $methods = implode(',', $methods) . ','; - - if (false !== strpos($methods, self::ANY)) { - return trim($allow, ','); - } - - return trim($methods, ','); - } - - /** - * has dynamic param - * @param string $route - * @return bool - */ - protected static function isNoDynamicParam($route) - { - return strpos($route, '{') === false && strpos($route, '[') === false; - } - - /** - * @param string $path - * @return string - */ - protected static function getFirstFromPath($path) - { - $tmp = trim($path, '/'); // clear first,end '/' - - // eg '/article/12' - if (strpos($tmp, '/')) { - return strstr($tmp, '/', true); - } - - // eg '/about.html' - if (strpos($tmp, '.')) { - return strstr($tmp, '.', true); - } - - return $tmp; - } - - /** - * @param array $matches - * @param array $conf - * @return array - */ - protected static function filterMatches(array $matches, array $conf) - { - // clear all int key - $matches = array_filter($matches, '\is_string', ARRAY_FILTER_USE_KEY); - - // apply some default param value - if (isset($conf['option']['defaults'])) { - $matches = array_merge($conf['option']['defaults'], $matches); - } - - // decode ... - // foreach ($matches as $k => $v) { - // $matches[$k] = urldecode($v); - // } - - return $matches; - } - - /** - * @param string $route - * @param array $params - * @param array $conf - * @return array - * @throws \LogicException - */ - public static function parseParamRoute($route, array $params, array $conf) - { - $tmp = $route; - - // 解析可选参数位 - // '/hello[/{name}]' match: /hello/tom /hello - // '/my[/{name}[/{age}]]' match: /my/tom/78 /my/tom - if (false !== strpos($route, ']')) { - $withoutClosingOptionals = rtrim($route, ']'); - $optionalNum = \strlen($route) - \strlen($withoutClosingOptionals); - - if ($optionalNum !== substr_count($withoutClosingOptionals, '[')) { - throw new \LogicException('Optional segments can only occur at the end of a route'); - } - - // '/hello[/{name}]' -> '/hello(?:/{name})?' - $route = str_replace(['[', ']'], ['(?:', ')?'], $route); - } - - // quote '.','/' to '\.','\/' - // $route = preg_quote($route, '/'); - $route = str_replace('.', '\.', $route); - - // 解析参数,替换为对应的 正则 - if (preg_match_all('#\{([a-zA-Z_][a-zA-Z0-9_-]*)\}#', $route, $m)) { - /** @var array[] $m */ - $replacePairs = []; - - foreach ($m[1] as $name) { - $key = '{' . $name . '}'; - // 匹配定义的 param , 未匹配到的使用默认 self::DEFAULT_REGEX - $regex = isset($params[$name]) ? $params[$name] : self::DEFAULT_REGEX; - - // 将匹配结果命名 (?P[^/]+) - $replacePairs[$key] = '(?P<' . $name . '>' . $regex . ')'; - // $replacePairs[$key] = '(' . $regex . ')'; - } - - $route = strtr($route, $replacePairs); - } - - // 分析路由字符串是否是有规律的 - $first = null; - $regex = '#^' . $route . '$#'; - - // e.g '/hello[/{name}]' first: 'hello', '/user/{id}' first: 'user', '/a/{post}' first: 'a' - // first node is a normal string - // if (preg_match('#^/([\w-]+)#', $tmp, $m)) { - // if (preg_match('#^/([\w-]+)/?[\w-]*#', $tmp, $m)) { - if (preg_match('#^/([\w-]+)/[\w-]*#', $tmp, $m)) { - $first = $m[1]; - $info = [ - 'regex' => $regex, - 'start' => $m[0], - 'original' => $tmp, - ]; - // first node contain regex param '/{some}/{some2}/xyz' - } else { - $include = null; - - if (preg_match('#/([\w-]+)/?[\w-]*#', $tmp, $m)) { - $include = $m[0]; - } - - $info = [ - 'regex' => $regex, - 'include' => $include, - 'original' => $tmp, - ]; - } - - return [$first, array_merge($info, $conf)]; - } - - /** - * @param array $routes - * [ - * 'GET,POST' => [ - * 'handler' => 'handler', - * 'methods' => 'GET,POST', - * 'option' => [...], - * ], - * 'PUT' => [ - * 'handler' => 'handler', - * 'methods' => 'PUT', - * 'option' => [...], - * ], - * ... - * ] - * @param string $path - * @param string $method - * @return array - */ - public static function findInStaticRoutes(array $routes, $path, $method) - { - $methods = null; - - foreach ($routes as $conf) { - if (false !== strpos($conf['methods'] . ',', $method . ',')) { - return [self::FOUND, $path, $conf]; - } - - $methods .= $conf['methods'] . ','; - } - - // method not allowed - return [self::METHOD_NOT_ALLOWED, $path, array_unique(explode(',', trim($methods, ',')))]; - } - - /** - * handle auto route match, when config `'autoRoute' => true` - * @param string $path The route path - * @param string $controllerNamespace controller namespace. eg: 'app\\controllers' - * @param string $controllerSuffix controller suffix. eg: 'Controller' - * @return bool|callable - */ - public static function matchAutoRoute($path, $controllerNamespace, $controllerSuffix = '') - { - $cnp = trim($controllerNamespace); - $sfx = trim($controllerSuffix); - $tmp = trim($path, '/- '); - - // one node. eg: 'home' - if (!strpos($tmp, '/')) { - $tmp = self::convertNodeStr($tmp); - $class = "$cnp\\" . ucfirst($tmp) . $sfx; - - return class_exists($class) ? $class : false; - } - - $ary = array_map([self::class, 'convertNodeStr'], explode('/', $tmp)); - $cnt = \count($ary); - - // two nodes. eg: 'home/test' 'admin/user' - if ($cnt === 2) { - list($n1, $n2) = $ary; - - // last node is an controller class name. eg: 'admin/user' - $class = "$cnp\\$n1\\" . ucfirst($n2) . $sfx; - - if (class_exists($class)) { - return $class; - } - - // first node is an controller class name, second node is a action name, - $class = "$cnp\\" . ucfirst($n1) . $sfx; - - return class_exists($class) ? "$class@$n2" : false; - } - - // max allow 5 nodes - if ($cnt > 5) { - return false; - } - - // last node is an controller class name - $n2 = array_pop($ary); - $class = sprintf('%s\\%s\\%s', $cnp, implode('\\', $ary), ucfirst($n2) . $sfx); - - if (class_exists($class)) { - return $class; - } - - // last second is an controller class name, last node is a action name, - $n1 = array_pop($ary); - $class = sprintf('%s\\%s\\%s', $cnp, implode('\\', $ary), ucfirst($n1) . $sfx); - - return class_exists($class) ? "$class@$n2" : false; - } - - /** - * @param array $params - * @param array $tmpParams - * @return array - */ - public static function getAvailableParams(array $params, $tmpParams) - { - if ($tmpParams) { - foreach ($tmpParams as $name => $pattern) { - $key = trim($name, '{}'); - $params[$key] = $pattern; - } - } - - return $params; - } - - /** - * convert 'first-second' to 'firstSecond' - * @param $str - * @return mixed|string - */ - public static function convertNodeStr($str) - { - $str = trim($str, '-'); - - // convert 'first-second' to 'firstSecond' - if (strpos($str, '-')) { - $str = preg_replace_callback('/-+([a-z])/', function ($c) { - return strtoupper($c[1]); - }, trim($str, '- ')); - } - - return $str; - } - - /** - * @param array $params - */ - public function addGlobalParams(array $params) - { - foreach ($params as $name => $pattern) { - $this->addGlobalParam($name, $pattern); - } - } - - /** - * @param $name - * @param $pattern - */ - public function addGlobalParam($name, $pattern) - { - $name = trim($name, '{} '); - self::$globalParams[$name] = $pattern; - } - - /** - * @return array - */ - public static function getGlobalParams() - { - return self::$globalParams; - } - - /** - * @return array - */ - public static function getSupportedMethods() - { - return self::SUPPORTED_METHODS; - } -} diff --git a/src/CachedRouter.php b/src/CachedRouter.php index bc7a8f2..c2566ca 100644 --- a/src/CachedRouter.php +++ b/src/CachedRouter.php @@ -1,4 +1,4 @@ -config = array_merge($this->config,[ - 'cacheFile' => '', - 'cacheEnable' => true, - ]); - parent::__construct($config); + if (isset($config['cacheFile'])) { + $this->setCacheFile($config['cacheFile']); + } + + if (isset($config['cacheEnable'])) { + $this->setCacheEnable($config['cacheEnable']); + } + // read route caches from cache file $this->loadRoutesCache(); } - private $indexId = 0; - /** - * generate index id - * @return int + * talk to me routes collect completed. */ - protected function generateId() + public function completed(): void { - return ++$this->indexId; + $this->dumpRoutesCache(); } /** * {@inheritdoc} */ - public function map($method, $route, $handler, array $opts = []) + public function add(string $method, string $path, $handler, array $binds = [], array $opts = []): Route { // file cache exists check. if ($this->cacheLoaded) { - return $this; + return Route::createFromArray(); } - return parent::map($method, $route, $handler, $opts); + return parent::add($method, $path, $handler, $binds, $opts); } /** * {@inheritdoc} */ - public function match($path, $method = self::GET) + public function addRoute(Route $route): Route { - // dump routes to cache file - $this->dumpRoutesCache(); + // file cache exists check. + if ($this->cacheLoaded) { + return $route; + } - return parent::match($path, $method); + return parent::addRoute($route); } /******************************************************************************* @@ -83,90 +111,144 @@ public function match($path, $method = self::GET) * load route caches from the cache file * @return bool */ - public function loadRoutesCache() + public function loadRoutesCache(): bool { - if (!$this->isCacheEnabled()) { + if (!$this->isCacheEnable()) { return false; } - $file = $this->config['cacheFile']; - + $file = $this->cacheFile; if (!$file || !file_exists($file)) { return false; } // load routes - $map = include $file; + $map = require $file; + if (!is_array($map) && !isset($map['staticRoutes'])) { + throw new RuntimeException('Invalid cache routes data'); + } + + $staticRoutes = $regularRoutes = $vagueRoutes = []; - $this->setStaticRoutes($map['staticRoutes']); - $this->setRegularRoutes($map['regularRoutes']); - $this->setVagueRoutes($map['vagueRoutes']); - $this->cacheLoaded = true; + $this->routeCounter = 0; + foreach ($map['staticRoutes'] as $key => $info) { + $this->routeCounter++; + $staticRoutes[$key] = Route::createFromArray($info); + } + + foreach ($map['regularRoutes'] as $key => $routes) { + foreach ($routes as $info) { + $this->routeCounter++; + $regularRoutes[$key][] = Route::createFromArray($info); + } + } + + foreach ($map['vagueRoutes'] as $key => $routes) { + foreach ($routes as $info) { + $this->routeCounter++; + $vagueRoutes[$key][] = Route::createFromArray($info); + } + } + + $this->staticRoutes = $staticRoutes; + $this->regularRoutes = $regularRoutes; + $this->vagueRoutes = $vagueRoutes; + $this->cacheLoaded = true; return true; } /** * dump routes to cache file - * @return bool|int + * @return int */ - public function dumpRoutesCache() + protected function dumpRoutesCache(): int { - if (!$file = $this->config['cacheFile']) { - return false; + if (!$file = $this->cacheFile) { + return 0; } - if ($this->isCacheEnabled() && file_exists($file)) { - return true; + if ($this->isCacheEnable() && file_exists($file)) { + return 1; } - $date = date('Y-m-d H:i:s'); + $date = date('Y-m-d H:i:s'); $class = static::class; - $staticRoutes = var_export($this->getStaticRoutes(), true); - $regularRoutes = var_export($this->getRegularRoutes(), true); - $vagueRoutes = var_export($this->getVagueRoutes(), true); + $count = $this->count(); + + $staticRoutes = var_export($this->staticRoutes, true); + $regularRoutes = var_export($this->regularRoutes, true); + $vagueRoutes = var_export($this->vagueRoutes, true); $code = << $staticRoutes, - // regular routes - 'regularRoutes' => $regularRoutes, - // vague routes - 'vagueRoutes' => $vagueRoutes, -]; +return array ( +// static routes +'staticRoutes' => $staticRoutes, +// regular routes +'regularRoutes' => $regularRoutes, +// vague routes +'vagueRoutes' => $vagueRoutes, +);\n EOF; - - return file_put_contents($file, $code); + return file_put_contents($file, preg_replace( + ['/\s+\n\s+[\\\\]?Inhere\\\\Route\\\\Route::__set_state\(/', '/\)\),/', '/=>\s+\n\s+array \(/'], + [' ', '),', '=> array ('], + $code + )); } /** * @return bool */ - public function isCacheEnabled() + public function isCacheEnable(): bool + { + return $this->cacheEnable; + } + + /** + * @param bool $cacheEnable + */ + public function setCacheEnable(bool|int|string $cacheEnable): void + { + $this->cacheEnable = (bool)$cacheEnable; + } + + /** + * @return string + */ + public function getCacheFile(): string + { + return $this->cacheFile; + } + + /** + * @param string $cacheFile + */ + public function setCacheFile(string $cacheFile): void { - return (bool)$this->getConfig('cacheEnable'); + $this->cacheFile = trim($cacheFile); } /** * @return bool */ - public function isCacheExists() + public function isCacheExists(): bool { - return ($file = $this->config['cacheFile']) && file_exists($file); + return ($file = $this->cacheFile) && file_exists($file); } /** * @return bool */ - public function isCacheLoaded() + public function isCacheLoaded(): bool { return $this->cacheLoaded; } diff --git a/src/Dispatcher.php b/src/Dispatcher.php deleted file mode 100644 index 463b69d..0000000 --- a/src/Dispatcher.php +++ /dev/null @@ -1,530 +0,0 @@ - false, - - // default action method name - 'defaultAction' => 'index', - - 'actionPrefix' => '', - - 'actionSuffix' => 'Action', - - // enable dynamic action. - // e.g - // if set True; - // $router->any('/demo/{act}', app\controllers\Demo::class); - // you access '/demo/test' will call 'app\controllers\Demo::test()' - 'dynamicAction' => false, - // @see ORouter::$globalParams['act'] - 'dynamicActionVar' => 'act', - - // action executor. will auto call controller's executor method to run all action. - // e.g: 'actionExecutor' => 'run'` - // $router->any('/demo/{act}', app\controllers\Demo::class); - // you access `/demo/test` will call `app\controllers\Demo::run('test')` - 'actionExecutor' => '', // 'run' - ]; - - /** @var \Closure */ - private $matcher; - - /** @var bool */ - private $initialized; - - /** - * object creator. - * @param \Closure $matcher - * @param array $config - * @return self - * @throws \LogicException - */ - public static function make(array $config = [], \Closure $matcher = null) - { - return new self($config, $matcher); - } - - /** - * object constructor. - * @param \Closure $matcher - * @param array $config - * @throws \LogicException - */ - public function __construct(array $config = [], \Closure $matcher = null) - { - $this->initialized = false; - $this->setConfig($config); - - if ($matcher) { - $this->setMatcher($matcher); - } - } - - /** - * @param array $config - * @throws \LogicException - */ - public function setConfig(array $config) - { - if ($this->initialized) { - throw new \LogicException('Has already started to distributed routing, and configuration is not allowed!'); - } - - foreach ($config as $name => $value) { - if (isset($this->config[$name])) { - $this->config[$name] = $value; - } else { - // maybe it is a event - $this->on($name, $value); - } - } - } - - /******************************************************************************* - * route callback handler dispatch - ******************************************************************************/ - - /** - * @see ORouter::match() - * @param string $path - * @param string $method - * @return array|null - */ - protected function matchRoutePath($path, $method) - { - if (!$matcher = $this->matcher) { - throw new \RuntimeException('Must be setting the property [matcher] before call dispatch().'); - } - - if (!$this->initialized) { - $this->initialized = true; - } - - return $matcher($path, $method); - } - - /** - * Runs the callback for the given request - * @param string $path - * @param null|string $method - * @param array $args - * @return mixed - * @throws \Throwable - */ - public function dispatch($path = null, $method = null, array $args = []) - { - $path = $path ?: parse_url(http://github.com/$_SERVER['REQUEST_URI'],%20PHP_URL_PATH); - - // if 'filterFavicon' setting is TRUE - if ($path === self::FAV_ICON && $this->config['filterFavicon']) { - return null; - } - - $method = $method ?: $_SERVER['REQUEST_METHOD']; - list($status, $path, $route) = $this->matchRoutePath($path, $method); - - // not found || method not allowed - if ($status === RouterInterface::NOT_FOUND) { - return $this->handleNotFound($path, $method); - } - - if ($status === RouterInterface::METHOD_NOT_ALLOWED) { - return $this->handleNotAllowed($path, $method, $route); - } - - // trigger route found event - $this->fire(self::ON_FOUND, [$path, $route]); - - $result = null; - $options = $route['option']; - unset($route['option']); - - // fire enter event - // schema,domains ... metadata validate - if (isset($options['enter']) && false === $this->fireCallback($options['enter'], [$options, $path])) { - return $result; - } - - $handler = $route['handler']; - $args['matches'] = isset($route['matches']) ? $route['matches'] : []; - - try { - // trigger route exec_start event - $this->fire(self::ON_EXEC_START, [$path, $route]); - - $result = $this->callRouteHandler($path, $method, $handler, $args); - - // fire leave event - if (isset($options['leave'])) { - $this->fireCallback($options['leave'], [$options, $path]); - } - - // trigger route exec_end event - $this->fire(self::ON_EXEC_END, [$path, $route]); - } catch (\Exception $e) { - // trigger route exec_error event - if (self::hasEventHandler(self::ON_EXEC_ERROR)) { - return $this->fire(self::ON_EXEC_ERROR, [$e, $path, $route]); - } - - throw $e; - } catch (\Throwable $e) { - if (self::hasEventHandler(self::ON_EXEC_ERROR)) { - // trigger route exec_error event - return $this->fire(self::ON_EXEC_ERROR, [$e, $path, $route]); - } - - throw $e; - } - - return $result; - } - - /** - * @param array $options - * [ - * 'domains' => [ 'a-domain.com', '*.b-domain.com'], - * 'schemes' => ['https'], - * ] - */ - protected function validateMetadata(array $options) - { - // 1. validate Schema - - // 2. validate validateDomains - // $serverName = $_SERVER['SERVER_NAME']; - - // 3. more something ... - } - - /** - * execute the matched Route Handler - * @param string $path The route path - * @param string $method The request method - * @param callable $handler The route path handler - * @param array $args Matched param from path - * [ - * 'matches' => [] - * ] - * @return mixed - * @throws \Throwable - */ - protected function callRouteHandler($path, $method, $handler, array $args = []) - { - $vars = $args['matches']; - $args = array_values($args); - - // is a \Closure or a callable object - if (\is_object($handler)) { - return $handler(...$args); - } - - //// $handler is string - - // is array ['controller', 'action'] - if (\is_array($handler)) { - $segments = $handler; - } elseif (\is_string($handler)) { - if (strpos($handler, '@') === false && \function_exists($handler)) { - return $handler(...$args); - } - - // e.g `controllers\Home@index` Or only `controllers\Home` - $segments = explode('@', trim($handler)); - } else { - throw new \InvalidArgumentException('Invalid route handler'); - } - - // Instantiation controller - $controller = new $segments[0](); - - // Already assign action - if (isset($segments[1])) { - $action = $segments[1]; - - // use dynamic action - } elseif ($this->config['dynamicAction'] && ($var = $this->config['dynamicActionVar'])) { - $action = isset($vars[$var]) ? trim($vars[$var], '/') : $this->config['defaultAction']; - - // defined default action - } elseif (!$action = $this->config['defaultAction']) { - throw new \RuntimeException("please config the route path [$path] controller action to call"); - } - - $action = ORouter::convertNodeStr($action); - $actionMethod = $action . $this->config['actionSuffix']; - - // if set the 'actionExecutor', the action handle logic by it. - if ($executor = $this->config['actionExecutor']) { - return $controller->$executor($actionMethod, $args); - } - - // action method is not exist - if (!$action || !method_exists($controller, $actionMethod)) { - return $this->handleNotFound($path, $method, true); - } - - // call controller's action method - return $controller->$actionMethod(...$args); - } - - /** - * @param string $path Request uri path - * @param string $method - * @param bool $actionNotExist - * True: The `$path` is matched success, but action not exist on route parser - * False: The `$path` is matched fail - * @return bool|mixed - * @throws \Throwable - */ - protected function handleNotFound($path, $method, $actionNotExist = false) - { - // Run the 'notFound' callback if the route was not found - if (!isset(self::$events[self::ON_NOT_FOUND])) { - $notFoundHandler = $this->defaultNotFoundHandler(); - - $this->on(self::ON_NOT_FOUND, $notFoundHandler); - } else { - $notFoundHandler = self::$events[self::ON_NOT_FOUND]; - - // is a route path. like '/site/notFound' - if (\is_string($notFoundHandler) && '/' === $notFoundHandler{0}) { - $_GET['_src_path'] = $path; - - if ($path === $notFoundHandler) { - unset(self::$events[self::ON_NOT_FOUND]); - $handler = $this->defaultNotFoundHandler(); - - return $handler($path, $method); - } - - return $this->dispatch($notFoundHandler, $method); - } - } - - // trigger notFound event - return $this->fireCallback($notFoundHandler, [$path, $method, $actionNotExist]); - } - - /** - * @param string $path - * @param string $method - * @param array $methods The allowed methods - * @return mixed - * @throws \Throwable - */ - protected function handleNotAllowed($path, $method, array $methods) - { - // Run the 'NotAllowed' callback if the route was not found - if (!isset(self::$events[self::ON_METHOD_NOT_ALLOWED])) { - $handler = $this->defaultNotAllowedHandler(); - - $this->on(self::ON_METHOD_NOT_ALLOWED, $handler); - } else { - $handler = self::$events[self::ON_METHOD_NOT_ALLOWED]; - - // is a route path. like '/site/notFound' - if (\is_string($handler) && '/' === $handler{0}) { - $_GET['_src_path'] = $path; - - if ($path === $handler) { - unset(self::$events[self::ON_METHOD_NOT_ALLOWED]); - $handler = $this->defaultNotAllowedHandler(); - - return $handler($path, $method, $methods); - } - - return $this->dispatch($handler, $method); - } - } - - // trigger methodNotAllowed event - return $this->fireCallback($handler, [$path, $method, $methods]); - } - - /** - * @return \Closure - */ - protected function defaultNotFoundHandler() - { - return function ($path) { - $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; - header($protocol . ' 404 Not Found'); - echo "

:( 404
Page Not Found $path

"; - }; - } - - /** - * @return \Closure - */ - protected function defaultNotAllowedHandler() - { - return function ($path, $method, $methods) { - $allow = implode(',', $methods); - $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; - header($protocol . ' 405 Method Not Allowed'); - - echo "

:( Method not allowed $method: $path

", - "

Method not allowed. Must be one of: $allow

"; - }; - } - - /** - * @param null $key - * @param null $default - * @return array|mixed - */ - public function getConfig($key = null, $default = null) - { - if ($key) { - return isset($this->config[$key]) ? $this->config[$key] : $default; - } - - return $this->config; - } - - /** - * Defines callback on happen event - * @param $event - * @param callable $handler - */ - public function on($event, $handler) - { - if (self::isSupportedEvent($event)) { - self::$events[$event] = $handler; - } - } - - /** - * Trigger event - * @param $event - * @param array $args - * @return mixed - */ - protected function fire($event, array $args = []) - { - if (isset(self::$events[$event]) && ($cb = self::$events[$event])) { - return $this->fireCallback($cb, $args); - } - - return null; - } - - /** - * @param callable $cb - * string - func name, class name - * array - [class, method] - * object - Closure, Object - * - * @param array $args - * @return mixed - */ - protected function fireCallback($cb, array $args = []) - { - if (!$cb) { - return true; - } - - if (\is_array($cb)) { - // return call_user_func($cb, $path); - list($obj, $mhd) = $cb; - - return \is_object($obj) ? $obj->$mhd(...$args) : $obj::$mhd(...$args); - } - - if (\is_string($cb)) { - if (\function_exists($cb)) { - return $cb(...$args); - } - - // a class name - if (class_exists($cb)) { - $cb = new $cb; - } - } - - // a \Closure or Object implement '__invoke' - if (\is_object($cb) && method_exists($cb, '__invoke')) { - return $cb(...$args); - } - - throw new \InvalidArgumentException('the callback handler is not callable!'); - } - - /** - * @param $event - * @return bool - */ - public static function hasEventHandler($event) - { - return isset(self::$events[$event]); - } - - /** - * @return array - */ - public static function getSupportedEvents() - { - return [ - self::ON_FOUND, - self::ON_NOT_FOUND, - self::ON_METHOD_NOT_ALLOWED, - self::ON_EXEC_START, - self::ON_EXEC_END, - self::ON_EXEC_ERROR - ]; - } - - /** - * @param $name - * @return array - */ - public static function isSupportedEvent($name) - { - return \in_array($name, static::getSupportedEvents(), true); - } - - /** - * @return \Closure - */ - public function getMatcher() - { - return $this->matcher; - } - - /** - * @param \Closure $matcher - * @return $this - */ - public function setMatcher(\Closure $matcher) - { - $this->matcher = $matcher; - - return $this; - } -} diff --git a/src/Dispatcher/Dispatcher.php b/src/Dispatcher/Dispatcher.php new file mode 100644 index 0000000..ed90dc4 --- /dev/null +++ b/src/Dispatcher/Dispatcher.php @@ -0,0 +1,88 @@ +getOptions(); + + // fire enter event + // schema,domains ... metadata validate + if (isset($options['enter']) && false === RouteHelper::call($options['enter'], [$options, $path])) { + return null; + } + + $handler = $route->getHandler(); + $params = $route->getParams(); + + try { + // trigger route exec_start event + $this->fire(self::ON_EXEC_START, [$path, $route]); + $result = $this->callHandler($path, $method, $handler, $params); + + // fire leave event + if (isset($options['leave'])) { + RouteHelper::call($options['leave'], [$options, $path]); + } + + // trigger route exec_end event + $this->fire(self::ON_EXEC_END, [$path, $route, $result]); + } catch (Throwable $e) { + // trigger route exec_error event + if ($cb = $this->getOption(self::ON_EXEC_ERROR)) { + return RouteHelper::call($cb, [$e, $path, $route]); + } + + throw $e; + } + + return $result; + } + + /** + * @param array $options + * [ + * 'domains' => [ 'a-domain.com', '*.b-domain.com'], + * 'schemes' => ['https'], + * ] + */ + protected function validateMetadata(array $options): void + { + // 1. validate Schema + + // 2. validate validateDomains + // $serverName = $_SERVER['SERVER_NAME']; + + // 3. more something ... + } +} diff --git a/src/Dispatcher/DispatcherInterface.php b/src/Dispatcher/DispatcherInterface.php new file mode 100644 index 0000000..0cb3bfa --- /dev/null +++ b/src/Dispatcher/DispatcherInterface.php @@ -0,0 +1,87 @@ +getUri()->getPath(); + $method = $request->getMethod(); + + /** @var Route $route */ + [$status, $path, $route] = $this->getRouter()->match($path, $method); + + $chains = $this->getRouter()->getChains(); + + switch ($status) { + case RouterInterface::FOUND: + $chains = array_merge($chains, $route->getChains()); + break; + case RouterInterface::NOT_FOUND: + + break; + case RouterInterface::METHOD_NOT_ALLOWED: + + break; + } + } + + /** + * Dispatch route handler for the given route info. + * {@inheritdoc} + * @throws Exception + * @throws Throwable + */ + public function dispatch(int $status, string $path, string $method, $route) + { + // not found + if ($status === RouterInterface::NOT_FOUND) { + return $this->handleNotFound($path, $method); + } + + // method not allowed + if ($status === RouterInterface::METHOD_NOT_ALLOWED) { + return $this->handleNotAllowed($path, $method, $route); + } + + // trigger route found event + $this->fire(self::ON_FOUND, [$path, $route]); + + $result = null; + $options = $route->getOptions(); + + // fire enter event + // schema,domains ... metadata validate + if (isset($options['enter']) && false === RouteHelper::call($options['enter'], [$options, $path])) { + return $result; + } + + $handler = $route->getHandler(); + $args = $route->getParams(); + + try { + // trigger route exec_start event + $this->fire(self::ON_EXEC_START, [$path, $route]); + + $globChains = $this->getRouter()->getChains(); + $chains = $route->getChains(); + + $result = $this->callHandler($path, $method, $handler, $args); + + // fire leave event + if (isset($options['leave'])) { + RouteHelper::call($options['leave'], [$options, $path]); + } + + // trigger route exec_end event + $this->fire(self::ON_EXEC_END, [$path, $route, $result]); + } catch (Throwable $e) { + // trigger route exec_error event + if ($cb = $this->getOption(self::ON_EXEC_ERROR)) { + return RouteHelper::call($cb, [$e, $path, $route]); + } + + throw $e; + } + + return $result; + } +} diff --git a/src/Dispatcher/SimpleDispatcher.php b/src/Dispatcher/SimpleDispatcher.php new file mode 100644 index 0000000..b3ca80a --- /dev/null +++ b/src/Dispatcher/SimpleDispatcher.php @@ -0,0 +1,504 @@ + false, + + // default action method name + 'defaultAction' => 'index', + + 'actionPrefix' => '', + 'actionSuffix' => 'Action', + + // enable dynamic action. + // e.g + // if set True; + // $router->any('/demo/{act}', App\Controllers\Demo::class); + // you access '/demo/test' will call 'App\Controllers\Demo::test()' + 'dynamicAction' => false, + // @see Router::$globalParams['act'] + 'dynamicActionVar' => 'act', + + // action executor. will auto call controller's executor method to run all action. + // e.g: 'actionExecutor' => 'run'` + // $router->any('/demo/{act}', App\Controllers\Demo::class); + // you access `/demo/test` will call `App\Controllers\Demo::run('test')` + 'actionExecutor' => '', // 'run' + + // events: please @see DispatcherInterface::ON_* + // 'event name' => callback + // SimpleDispatcher::ON_FOUND => function(){ ... }, + ]; + + /** + * Object creator. + * + * @param RouterInterface|null $router + * @param array $options + * + * @return self + * @throws LogicException + */ + public static function create(array $options = [], ?RouterInterface $router = null): DispatcherInterface + { + return new static($options, $router); + } + + /** + * Class constructor. + * + * @param RouterInterface|null $router + * @param array $options + * + * @throws LogicException + */ + public function __construct(array $options = [], ?RouterInterface $router = null) + { + $this->initialized = false; + $this->initOptions($options); + + if ($router) { + $this->setRouter($router); + } + } + + /** + * @param array $options + * + * @throws LogicException + */ + public function initOptions(array $options): void + { + if ($this->initialized) { + throw new LogicException('Has already started to distributed routing, and configuration is not allowed!'); + } + + foreach ($options as $name => $value) { + if (isset($this->options[$name])) { + $this->options[$name] = $value; + } else { + // maybe it is a event + $this->on($name, $value); + } + } + } + + /** + * Runs the callback for the given path and method. + * + * @param string $path + * @param string $method + * + * @return mixed + * @throws Throwable + */ + public function dispatchUri(string $path = '', string $method = ''): mixed + { + $path = $path ?: $_SERVER['REQUEST_URI']; + + if (strpos($path, '?')) { + $path = (string)parse_url(http://github.com/$path,%20PHP_URL_PATH); + } + + // if 'filterFavicon' setting is TRUE + if ($path === self::FAV_ICON && $this->options['filterFavicon']) { + return null; + } + + $method = $method ?: $_SERVER['REQUEST_METHOD']; + $method = strtoupper($method); + + /** @var Route $route */ + [$status, $path, $route] = $this->router->match($path, $method); + + return $this->dispatch($status, $path, $method, $route); + } + + /** + * Dispatch route handler for the given route info. + * {@inheritdoc} + * + * @throws Throwable + */ + public function dispatch(int $status, string $path, string $method, $route): mixed + { + // not found + if ($status === RouterInterface::NOT_FOUND) { + return $this->handleNotFound($path, $method); + } + + // method not allowed. $route is methods array. + if ($status === RouterInterface::METHOD_NOT_ALLOWED) { + return $this->handleNotAllowed($path, $method, $route); + } + + return $this->doDispatch($path, $method, $route); + } + + /** + * @param string $path + * @param string $method + * @param Route $route + * + * @return bool|mixed|null + * @throws Throwable + */ + protected function doDispatch(string $path, string $method, $route): mixed + { + // trigger route found event + $this->fire(self::ON_FOUND, [$path, $route]); + + try { + // trigger route exec_start event + $this->fire(self::ON_EXEC_START, [$path, $route]); + + $result = $this->callHandler($path, $method, $route->getHandler(), $route->getParams()); + + // trigger route exec_end event + $this->fire(self::ON_EXEC_END, [$path, $route, $result]); + } catch (Throwable $e) { + // trigger route exec_error event + if ($cb = $this->getOption(self::ON_EXEC_ERROR)) { + return RouteHelper::call($cb, [$e, $path, $route]); + } + + throw $e; + } + + return $result; + } + + /** + * execute the matched Route Handler + * + * @param string $path The route path + * @param string $method The request method + * @param callable|mixed $handler The route path handler + * @param array $args Matched param from path + * [ + * 'name' => value + * ] + * + * @return mixed + * @throws Throwable + */ + protected function callHandler(string $path, string $method, $handler, array $args = []) + { + // is a \Closure or a callable object + if (is_object($handler)) { + return $handler($args); + } + + //// $handler is string + + // is array ['controller', 'action'] + if (is_array($handler)) { + $segments = $handler; + } elseif (is_string($handler)) { + // is function + if (!str_contains($handler, '@') && function_exists($handler)) { + return $handler($args); + } + + // e.g `Controllers\Home@index` Or only `Controllers\Home` + $segments = explode('@', trim($handler)); + } else { + throw new InvalidArgumentException("Invalid route handler for route '$path'"); + } + + // Instantiation controller + $controller = new $segments[0](); + + // Already assign action + if (!empty($segments[1])) { + $action = $segments[1]; + + // use dynamic action + } elseif ($this->options['dynamicAction'] && ($var = $this->options['dynamicActionVar'])) { + $action = isset($args[$var]) ? trim($args[$var], '/') : $this->options['defaultAction']; + + // defined default action + } elseif (!$action = $this->options['defaultAction']) { + throw new RuntimeException("please config the route path [$path] controller action to call"); + } + + $actionName = RouteHelper::str2Camel($action); + $actionMethod = $actionName . $this->options['actionSuffix']; + + // if set the 'actionExecutor', the action handle logic by it. + if ($executor = $this->options['actionExecutor']) { + return $controller->$executor($actionMethod, $args); + } + + // action method is not exist + if (!method_exists($controller, $actionMethod)) { + return $this->handleNotFound($path, $method, true); + } + + // call controller's action method + return $controller->$actionMethod($args); + } + + /** + * @param string $path Request uri path + * @param string $method + * @param bool $actionNotExist + * True: The `$path` is matched success, but action not exist on route parser + * False: The `$path` is matched fail + * + * @return bool|mixed + * @throws Throwable + */ + protected function handleNotFound(string $path, string $method, bool $actionNotExist = false): mixed + { + // Run the 'notFound' callback if the route was not found + if (!$handler = $this->getOption(self::ON_NOT_FOUND)) { + $handler = $this->defaultNotFoundHandler(); + + $this->setOption(self::ON_NOT_FOUND, $handler); + // is a route path. like '/site/notFound' + } elseif (is_string($handler) && str_starts_with($handler, '/')) { + $_GET['_src_path'] = $path; + + if ($path === $handler) { + $defaultHandler = $this->defaultNotFoundHandler(); + return $defaultHandler($path, $method); + } + + return $this->dispatchUri($handler, $method); + } + + // trigger notFound event + return RouteHelper::call($handler, [$path, $method, $actionNotExist]); + } + + /** + * @param string $path + * @param string $method + * @param array $methods The allowed methods + * + * @return mixed + * @throws Throwable + */ + protected function handleNotAllowed(string $path, string $method, array $methods): mixed + { + // Run the 'NotAllowed' callback if the route was not found + if (!$handler = $this->getOption(self::ON_METHOD_NOT_ALLOWED)) { + $handler = $this->defaultNotAllowedHandler(); + $this->setOption(self::ON_METHOD_NOT_ALLOWED, $handler); + + // is a route path. like '/site/notFound' + } elseif (is_string($handler) && str_starts_with($handler, '/')) { + $_GET['_src_path'] = $path; + + if ($path === $handler) { + $defaultHandler = $this->defaultNotAllowedHandler(); + + return $defaultHandler($path, $method, $methods); + } + + return $this->dispatchUri($handler, $method); + } + + // trigger methodNotAllowed event + return RouteHelper::call($handler, [$path, $method, $methods]); + } + + /** + * @return Closure + */ + protected function defaultNotFoundHandler(): Closure + { + return static function ($path) { + $protocol = $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1'; + header($protocol . ' 404 Not Found'); + echo "

:( 404
Page Not Found $path

"; + }; + } + + /** + * @return Closure + */ + protected function defaultNotAllowedHandler(): Closure + { + return static function ($path, $method, $methods) { + $allow = implode(',', $methods); + $protocol = $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1'; + header($protocol . ' 405 Method Not Allowed'); + + echo << +

:( Method not allowed

+

Method not allowed for $method $path

+

The request method must be one of $allow

+ +HTML; + }; + } + + /** + * Defines callback on happen event + * + * @param string $event + * @param callable $handler + */ + public function on(string $event, $handler): void + { + if (self::isSupportedEvent($event)) { + $this->options[$event] = $handler; + } + } + + /** + * Trigger event + * + * @param string $event + * @param array $args + * + * @return mixed + * @throws InvalidArgumentException + */ + protected function fire(string $event, array $args = []): mixed + { + if (!$cb = $this->getOption($event)) { + return null; + } + + return RouteHelper::call($cb, $args); + } + + /** + * @param string $name + * @param mixed $value + */ + public function setOption(string $name, mixed $value): void + { + $this->options[$name] = $value; + } + + /** + * @param string $name + * @param mixed|null $default + * + * @return mixed + */ + public function getOption(string $name, mixed $default = null): mixed + { + return $this->options[$name] ?? $default; + } + + /** + * @return array + */ + public static function getSupportedEvents(): array + { + return [ + self::ON_FOUND, + self::ON_NOT_FOUND, + self::ON_METHOD_NOT_ALLOWED, + self::ON_EXEC_START, + self::ON_EXEC_END, + self::ON_EXEC_ERROR + ]; + } + + /** + * @param string $name + * + * @return bool + */ + public static function isSupportedEvent(string $name): bool + { + return in_array($name, static::getSupportedEvents(), true); + } + + /** + * @return bool + */ + public function hasRouter(): bool + { + return $this->router !== null; + } + + /** + * @return RouterInterface + */ + public function getRouter(): RouterInterface + { + return $this->router; + } + + /** + * @param RouterInterface $router + */ + public function setRouter(RouterInterface $router): void + { + $this->router = $router; + } + + /** + * @return array + */ + public function getOptions(): array + { + return $this->options; + } + + /** + * @param array $options + */ + public function setOptions(array $options): void + { + $this->options = array_merge($this->options, $options); + } +} diff --git a/src/DispatcherInterface.php b/src/DispatcherInterface.php deleted file mode 100644 index 787be41..0000000 --- a/src/DispatcherInterface.php +++ /dev/null @@ -1,44 +0,0 @@ - '/' + if (false !== strpos($path, '//')) { + $path = preg_replace('#\/\/+#', '/', $path); + } + + // Must be start withs '/' + if (strpos($path, '/') !== 0) { + $path = '/' . $path; + } + + // Decode + $path = rawurldecode($path); + + return $ignoreLastSlash ? rtrim($path, '/') : $path; + } + + /** + * convert 'first-second' to 'firstSecond' + * + * @param string $str + * @param bool $ucFirst + * + * @return string + */ + public static function str2Camel(string $str, bool $ucFirst = false): string + { + $str = trim($str, '-'); + + // convert 'first-second' to 'firstSecond' + if (strpos($str, '-')) { + $str = preg_replace_callback('/-+([a-z])/', static function ($c) { + return strtoupper($c[1]); + }, trim($str, '- ')); + } + + return $ucFirst ? ucfirst($str) : $str; + } + + /** + * handle auto route match, when config `'autoRoute' => true` + * + * @param string $path The route path + * @param string $cnp controller namespace. eg: 'app\\controllers' + * @param string $sfx controller suffix. eg: 'Controller' + * @param bool $ucFirst + * + * @return bool|string + */ + public static function parseAutoRoute(string $path, string $cnp, string $sfx, bool $ucFirst = false): bool|string + { + $tmp = trim($path, '/- '); + + // one node. eg: 'home' + if (!strpos($tmp, '/')) { + $tmp = self::str2Camel($tmp); + $class = "$cnp\\" . ucfirst($tmp) . $sfx; + + return class_exists($class) ? $class : false; + } + + $nodes = array_filter(explode('/', $tmp)); + + if ($ucFirst) { + foreach ($nodes as $i => $node) { + $nodes[$i] = self::str2Camel($nodes[$i], true); + } + } else { + $nodes = array_map(self::class . '::str2Camel', $nodes); + } + + $count = count($nodes); + + // two nodes. eg: 'home/test' 'admin/user' + if ($count === 2) { + [$n1, $n2] = $nodes; + + // last node is an controller class name. eg: 'admin/user' + $class = "$cnp\\$n1\\" . ucfirst($n2) . $sfx; + + if (class_exists($class)) { + return $class; + } + + // first node is an controller class name, second node is a action name, + $class = "$cnp\\" . ucfirst($n1) . $sfx; + + return class_exists($class) ? $class . '@' . lcfirst($n2) : false; + } + + // max allow 5 nodes + if ($count > 5) { + return false; + } + + // last node is an controller class name + $n2 = array_pop($nodes); + $class = sprintf('%s\\%s\\%s', $cnp, implode('\\', $nodes), ucfirst($n2) . $sfx); + + if (class_exists($class)) { + return $class; + } + + // last second is an controller class name, last node is a action name, + $n1 = array_pop($nodes); + $class = sprintf('%s\\%s\\%s', $cnp, implode('\\', $nodes), ucfirst($n1) . $sfx); + + return class_exists($class) ? $class . '@' . lcfirst($n2) : false; + } + + /** + * @param callable|mixed $cb + * string - func name, class name + * array - [class, method] + * object - Closure, Object + * + * @param array $args + * + * @return mixed + * @throws InvalidArgumentException + */ + public static function call($cb, array $args = []) + { + if (!$cb) { + return true; + } + + if (is_array($cb)) { + [$obj, $mhd] = $cb; + + return is_object($obj) ? $obj->$mhd(...$args) : $obj::$mhd(...$args); + } + + if (is_string($cb)) { + if (function_exists($cb)) { + return $cb(...$args); + } + + // a class name + if (class_exists($cb)) { + $cb = new $cb; + } + } + + // a \Closure or Object implement '__invoke' + if (is_object($cb) && method_exists($cb, '__invoke')) { + return $cb(...$args); + } + + throw new InvalidArgumentException('the callback handler is not callable!'); + } +} diff --git a/src/Helper/functions.php b/src/Helper/functions.php new file mode 100644 index 0000000..d9d3970 --- /dev/null +++ b/src/Helper/functions.php @@ -0,0 +1,73 @@ +completed(); + + return $router; +} + +/** + * @param Closure $closure + * @param string $path + * @param string $method + * @param array $config + * + * @return PreMatchRouter + */ +function createPreMatchRouter( + Closure $closure, + string $path = '', + string $method = '', + array $config = [] +): PreMatchRouter { + $router = new PreMatchRouter($config, $path, $method); + + $closure($router); + + return $router; +} + +/** + * @param Closure $closure + * @param array $config + * + * @return ServerRouter + */ +function createServerRouter(Closure $closure, array $config = []): ServerRouter +{ + $closure($router = new ServerRouter($config)); + + return $router; +} diff --git a/src/ORouter.php b/src/ORouter.php deleted file mode 100644 index b120cfb..0000000 --- a/src/ORouter.php +++ /dev/null @@ -1,608 +0,0 @@ - [ 'localhost' ], // allowed domains - // 'schemas' => [ 'http' ], // allowed schemas - // 'time' => ['12'], - ]; - - /** @var string */ - private $currentGroupPrefix; - - /** @var array */ - private $currentGroupOption; - - /** @var bool */ - private $initialized = false; - - /** - * static Routes - no dynamic argument match - * 整个路由 path 都是静态字符串 e.g. '/user/login' - * @var array[] - * [ - * '/user/login' => [ - * // METHODS => [...] // 这里 key 和 value里的 'methods' 是一样的。仅是为了防止重复添加 - * 'GET,POST' => [ - * 'handler' => 'handler', - * 'methods' => 'GET,POST', - * 'option' => [...], - * ], - * 'PUT' => [ - * 'handler' => 'handler', - * 'methods' => 'PUT', - * 'option' => [...], - * ], - * ... - * ] - * ] - */ - private $staticRoutes = []; - - /** - * regular Routes - have dynamic arguments, but the first node is normal string. - * 第一节是个静态字符串,称之为有规律的动态路由。按第一节的信息进行分组存储 - * e.g '/hello[/{name}]' '/user/{id}' - * @var array[] - * [ - * // 使用完整的第一节作为key进行分组 - * 'a' => [ - * [ - * 'start' => '/a/', - * 'regex' => '/a/(\w+)', - * 'methods' => 'GET,POST', - * 'handler' => 'handler', - * 'option' => [...], - * ], - * ... ... - * ], - * 'add' => [ - * [ - * 'start' => '/add/', - * 'regex' => '/add/(\w+)', - * 'methods' => 'GET', - * 'handler' => 'handler', - * 'option' => [...], - * ], - * ... ... - * ], - * 'blog' => [ - * [ - * 'start' => '/blog/post-', - * 'regex' => '/blog/post-(\w+)', - * 'methods' => 'GET', - * 'handler' => 'handler', - * 'option' => [...], - * ], - * ... ... - * ], - * ] - */ - private $regularRoutes = []; - - /** - * vague Routes - have dynamic arguments,but the first node is exists regex. - * 第一节就包含了正则匹配,称之为无规律/模糊的动态路由 - * e.g '/{name}/profile' '/{some}/{some2}' - * @var array - * [ - * [ - * // 必定包含的字符串 - * 'include' => '/profile', - * 'regex' => '/(\w+)/profile', - * 'methods' => 'GET', - * 'handler' => 'handler', - * 'option' => [...], - * ], - * [ - * 'include' => null, - * 'regex' => '/(\w+)/(\w+)', - * 'methods' => 'GET,POST', - * 'handler' => 'handler', - * 'option' => [...], - * ], - * ... ... - * ] - */ - private $vagueRoutes = []; - - /** - * There are last route caches - * @see $staticRoutes - * @var array[] - */ - private $routeCaches = []; - - /** - * some setting for self - * @var array - */ - protected $config = [ - // the routes php file. - 'routesFile' => '', - - // ignore last '/' char. If is True, will clear last '/'. - 'ignoreLastSep' => false, - - // 'tmpCacheNumber' => 100, - 'tmpCacheNumber' => 0, - - // match all request. - // 1. If is a valid URI path, will matchAll all request uri to the path. - // 2. If is a closure, will matchAll all request then call it - // eg: '/site/maintenance' or `function () { echo 'System Maintaining ... ...'; }` - 'matchAll' => false, - - // auto route match @like yii framework - // If is True, will auto find the handler controller file. - 'autoRoute' => false, - // The default controllers namespace, is valid when `'enable' = true` - 'controllerNamespace' => '', // eg: 'app\\controllers' - // controller suffix, is valid when `'enable' = true` - 'controllerSuffix' => '', // eg: 'Controller' - ]; - - /** @var DispatcherInterface */ - private $dispatcher; - - /** - * object creator. - * @param array $config - * @return self - * @throws \LogicException - */ - public static function make(array $config = []) - { - return new static($config); - } - - /** - * object constructor. - * @param array $config - * @throws \LogicException - */ - public function __construct(array $config = []) - { - $this->setConfig($config); - - $this->currentGroupPrefix = ''; - $this->currentGroupOption = []; - - // load routes - if (($file = $this->config['routesFile']) && is_file($file)) { - require $file; - } - } - - /** - * @param array $config - * @throws \LogicException - */ - public function setConfig(array $config) - { - if ($this->initialized) { - throw new \LogicException('Routing has been added, and configuration is not allowed!'); - } - - foreach ($config as $name => $value) { - if (isset($this->config[$name])) { - $this->config[$name] = $value; - } - } - } - - /******************************************************************************* - * route collection - ******************************************************************************/ - - /** - * Defines a route callback and method - * @param string $method - * @param array $args - * @return ORouter - * @throws \LogicException - * @throws \InvalidArgumentException - */ - public function __call($method, array $args) - { - if (\count($args) < 2) { - throw new \InvalidArgumentException("The method [$method] parameters is missing."); - } - - return $this->map($method, $args[0], $args[1], isset($args[2]) ? $args[2] : []); - } - - /** - * Create a route group with a common prefix. - * All routes created in the passed callback will have the given group prefix prepended. - * @ref package 'nikic/fast-route' - * @param string $prefix - * @param \Closure $callback - * @param array $opts - */ - public function group($prefix, \Closure $callback, array $opts = []) - { - $previousGroupPrefix = $this->currentGroupPrefix; - $this->currentGroupPrefix = $previousGroupPrefix . '/' . trim($prefix, '/'); - - $previousGroupOption = $this->currentGroupOption; - $this->currentGroupOption = $opts; - - $callback($this); - - $this->currentGroupPrefix = $previousGroupPrefix; - $this->currentGroupOption = $previousGroupOption; - } - - /** - * @param string|array $methods The match request method(s). - * e.g - * string: 'get' - * array: ['get','post'] - * @param string $route The route path string. is allow empty string. eg: '/user/login' - * @param callable|string $handler - * @param array $opts some option data - * [ - * 'params' => [ 'id' => '[0-9]+', ], - * 'defaults' => [ 'id' => 10, ], - * 'domains' => [ 'a-domain.com', '*.b-domain.com'], - * 'schemas' => ['https'], - * ] - * @return static - * @throws \LogicException - * @throws \InvalidArgumentException - */ - public function map($methods, $route, $handler, array $opts = []) - { - if (!$this->initialized) { - $this->initialized = true; - } - - $hasPrefix = (bool)$this->currentGroupPrefix; - // validate and format arguments - $methods = static::validateArguments($methods, $handler); - - if ($route = trim($route)) { - // always add '/' prefix. - $route = $route{0} === '/' ? $route : '/' . $route; - } elseif (!$hasPrefix) { - $route = '/'; - } - - $route = $this->currentGroupPrefix . $route; - - // setting 'ignoreLastSep' - if ($route !== '/' && $this->config['ignoreLastSep']) { - $route = rtrim($route, '/'); - } - - $this->routeCounter++; - $opts = array_replace([ - 'params' => null, - // 'domains' => null, - ], $this->currentGroupOption, $opts); - $conf = [ - 'methods' => $methods, - 'handler' => $handler, - 'option' => $opts, - ]; - - // no dynamic param params - if (self::isNoDynamicParam($route)) { - $this->staticRoutes[$route][$methods] = $conf; - - return $this; - } - - // have dynamic param params - - // replace param name To pattern regex - $params = static::getAvailableParams(self::$globalParams, $opts['params']); - list($first, $conf) = static::parseParamRoute($route, $params, $conf); - - // route string have regular - if ($first) { - $this->regularRoutes[$first][] = $conf; - } else { - $this->vagueRoutes[] = $conf; - } - - return $this; - } - - /******************************************************************************* - * route match - ******************************************************************************/ - - /** - * find the matched route info for the given request uri path - * @param string $method - * @param string $path - * @return array - */ - public function match($path, $method = self::GET) - { - // if enable 'matchAll' - if ($matchAll = $this->config['matchAll']) { - if (\is_string($matchAll) && $matchAll{0} === '/') { - $path = $matchAll; - } elseif (\is_callable($matchAll)) { - return [self::FOUND, $path, [ - 'handler' => $matchAll, - 'option' => [], - ]]; - } - } - - // clear '//', '///' => '/' - $path = rawurldecode(preg_replace('#\/\/+#', '/', $path)); - $method = strtoupper($method); - - // setting 'ignoreLastSep' - if ($path !== '/' && $this->config['ignoreLastSep']) { - $path = rtrim($path, '/'); - } - - // find in route caches. - if ($this->routeCaches && isset($this->routeCaches[$path])) { - return self::findInStaticRoutes($this->routeCaches[$path], $path, $method); - } - - // is a static route path - if ($this->staticRoutes && isset($this->staticRoutes[$path])) { - return self::findInStaticRoutes($this->staticRoutes[$path], $path, $method); - } - - $first = self::getFirstFromPath($path); - - // is a regular dynamic route(the first node is 1th level index key). - if (isset($this->regularRoutes[$first])) { - foreach ($this->regularRoutes[$first] as $conf) { - if (0 === strpos($path, $conf['start']) && preg_match($conf['regex'], $path, $matches)) { - $conf['matches'] = $matches; - - return $this->checkMatched($path, $method, $conf); - } - } - } - - // is a irregular dynamic route - foreach ($this->vagueRoutes as $conf) { - if ($conf['include'] && false === strpos($path, $conf['include'])) { - continue; - } - - if (preg_match($conf['regex'], $path, $matches)) { - $conf['matches'] = $matches; - - return $this->checkMatched($path, $method, $conf); - } - } - - // handle Auto Route - if ( - $this->config['autoRoute'] && - ($handler = self::matchAutoRoute($path, $this->config['controllerNamespace'], $this->config['controllerSuffix'])) - ) { - return [self::FOUND, $path, [ - 'handler' => $handler, - 'option' => [], - ]]; - } - - // oo ... not found - return [self::NOT_FOUND, $path, null]; - } - - /******************************************************************************* - * route callback handler dispatch - ******************************************************************************/ - - /** - * Runs the callback for the given request - * @param DispatcherInterface|array $dispatcher - * @param null|string $path - * @param null|string $method - * @return mixed - * @throws \Throwable - */ - public function dispatch($dispatcher = null, $path = null, $method = null) - { - if ($dispatcher) { - if ($dispatcher instanceof DispatcherInterface) { - $this->dispatcher = $dispatcher; - } elseif (\is_array($dispatcher)) { - $this->dispatcher = new Dispatcher($dispatcher); - } - } - - if (!$this->dispatcher) { - $this->dispatcher = new Dispatcher; - } - - return $this->dispatcher->setMatcher(function ($p, $m) { - return $this->match($p, $m); - })->dispatch($path, $method); - } - - /******************************************************************************* - * helper methods - ******************************************************************************/ - - /** - * checkMatched - * @param string $path - * @param string $method - * @param array $conf - * @return array - */ - protected function checkMatched($path, $method, array $conf) - { - $methods = $conf['methods']; - $cacheNumber = (int)$this->config['tmpCacheNumber']; - - // method not allowed - if (false === strpos($methods . ',', $method . ',')) { - return [self::METHOD_NOT_ALLOWED, $path, explode(',', $methods)]; - } - - $conf['matches'] = self::filterMatches($conf['matches'], $conf); - - // cache last $cacheNumber routes. - if ($cacheNumber > 0) { - if ($this->cacheCounter === $cacheNumber) { - array_shift($this->routeCaches); - } - - if (!isset($this->routeCaches[$path][$methods])) { - $this->cacheCounter++; - $this->routeCaches[$path][$methods] = $conf; - } - } - - return [self::FOUND, $path, $conf]; - } - - /** - * @return int - */ - public function count() - { - return $this->routeCounter; - } - - /** - * @param array $staticRoutes - */ - public function setStaticRoutes(array $staticRoutes) - { - $this->staticRoutes = $staticRoutes; - } - - /** - * @return array - */ - public function getStaticRoutes() - { - return $this->staticRoutes; - } - - /** - * @param \array[] $regularRoutes - */ - public function setRegularRoutes(array $regularRoutes) - { - $this->regularRoutes = $regularRoutes; - } - - /** - * @return \array[] - */ - public function getRegularRoutes() - { - return $this->regularRoutes; - } - - /** - * @param array $vagueRoutes - */ - public function setVagueRoutes($vagueRoutes) - { - $this->vagueRoutes = $vagueRoutes; - } - - /** - * @return array - */ - public function getVagueRoutes() - { - return $this->vagueRoutes; - } - - /** - * @return array - */ - public function getRouteCaches() - { - return $this->routeCaches; - } - - /** - * @param null|string $name - * @param null|mixed $default - * @return array|string - */ - public function getConfig($name = null, $default = null) - { - if ($name) { - return isset($this->config[$name]) ? $this->config[$name] : $default; - } - - return $this->config; - } - - /** - * @return DispatcherInterface - */ - public function getDispatcher() - { - return $this->dispatcher; - } - - /** - * @param DispatcherInterface $dispatcher - * @return $this - */ - public function setDispatcher(DispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - - return $this; - } - - /** - * @return array - */ - public function getGlobalOptions(): array - { - return $this->globalOptions; - } - - /** - * @param array $globalOptions - * @return $this - */ - public function setGlobalOptions(array $globalOptions) - { - $this->globalOptions = $globalOptions; - - return $this; - } -} diff --git a/src/PreMatchRouter.php b/src/PreMatchRouter.php new file mode 100644 index 0000000..74fcfb0 --- /dev/null +++ b/src/PreMatchRouter.php @@ -0,0 +1,133 @@ +setRequest($path, $method); + } + + /** + * @param string $path + * @param string $method + */ + public function setRequest(string $path = '', string $method = ''): void + { + if (!$path) { + $path = $_SERVER['REQUEST_URI'] ?? ''; + } + + if (strpos($path, '?')) { + $path = (string)parse_url(http://github.com/$path,%20PHP_URL_PATH); + } + + $this->reqPath = RouteHelper::formatPath($path, $this->ignoreLastSlash); + $this->reqMethod = $method ? strtoupper($method) : $_SERVER['REQUEST_METHOD']; + } + + /** + * @param Route $route + * + * @return Route + */ + public function addRoute(Route $route): Route + { + // Has been matched. don't add again. + if ($this->preFounded) { + return $route; + } + + $path = $route->getPath(); + $method = $route->getMethod(); + + $this->routeCounter++; + + // Success match + if ($path === $this->reqPath && $method === $this->reqMethod) { + $this->preFounded = $route; + return $route; + } + + return parent::addRoute($route); + } + + /** + * {@inheritdoc} + */ + public function match(string $path, string $method = 'GET'): array + { + // If has been pre-matched. + if ($this->preFounded) { + return [self::FOUND, $path, $this->preFounded]; + } + + return parent::match($path, $method); + } + + /** + * @return Route|null + */ + public function getPreFounded(): ?Route + { + return $this->preFounded; + } + + /** + * @return string + */ + public function getReqPath(): string + { + return $this->reqPath; + } +} diff --git a/src/Route.php b/src/Route.php new file mode 100644 index 0000000..25636ce --- /dev/null +++ b/src/Route.php @@ -0,0 +1,653 @@ + regular expression path (or symbol name)] + * @var string[] + */ + private array $bindVars; + + /** + * dynamic route param values, only use for route cache + * [param name => value] + * @var string[] + */ + private array $params = []; + + // -- match condition. it is parsed from route path string. + + /** + * path var names. + * @var array '/users/{id}' => ['id'] + */ + private array $pathVars = []; + + /** + * @var string eg. '#^/users/(\d+)$#' + */ + private string $pathRegex = ''; + + /** + * '/users/{id}' -> '/users/' + * '/blog/post-{id}' -> '/blog/post-' + * @var string + */ + private string $pathStart = ''; + + // -- extra properties + + /** + * middleware handler chains + * @var callable[] + */ + private array $chains = []; + + /** + * some custom route options data. + * @var array + */ + private array $options; + + /** + * @param string $method + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $options + * + * @return Route + */ + public static function create( + string $method, + string $path, + mixed $handler, + array $pathParams = [], + array $options = [] + ): Route { + return new self($method, $path, $handler, $pathParams, $options); + } + + /** + * @param array $config + * + * @return Route + */ + public static function createFromArray(array $config = []): self + { + $route = new self('GET', '/', ''); + + foreach ($config as $property => $value) { + if (property_exists($route, $property)) { + $route->$property = $value; + } + } + + return $route; + } + + /** + * Route constructor. + * + * @param string $method + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $options + */ + public function __construct(string $method, string $path, mixed $handler, array $pathParams = [], array $options = []) + { + $this->initialize($method, $path, $handler, $pathParams, $options); + } + + public function initialize( + string $method, + string $path, + $handler, + array $pathParams = [], + array $options = [] + ): self { + $this->path = trim($path); + $this->method = strtoupper($method); + $this->bindVars = $pathParams; + $this->handler = $handler; + $this->options = $options; + + if (isset($options['name'])) { + $this->setName($options['name']); + } + + return $this; + } + + /** + * register route to the router + * + * @param Router $router + * + * @return Route + */ + public function attachTo(Router $router): self + { + $router->addRoute($this); + return $this; + } + + /** + * name the route and bind name to router. + * + * @param string $name + * @param Router $router + * @param bool $register + */ + public function namedTo(string $name, Router $router, bool $register = false): void + { + // not empty + if ($name = $this->setName($name)->name) { + if ($register) { + $router->addRoute($this); + } else { + $router->nameRoute($name, $this); + } + } + } + + /******************************************************************************* + * parse route path + ******************************************************************************/ + + /** + * parse route path string. fetch route params + * + * @param array $bindParams + * + * @return string returns the first node string. + */ + public function parseParam(array $bindParams = []): string + { + $argPos = strpos($this->path, '{'); + $optPos = strpos($this->path, '['); + + return $this->quickParseParams($argPos, $optPos, $bindParams); + } + + /** + * @param int|false $argPos + * @param int|false $optPos + * @param array $bindParams + * + * @return string + */ + public function quickParseParams($argPos, $optPos, array $bindParams = []): string + { + $first = $start = ''; + $path = $this->path; + + // regular: first node is a normal string e.g '/user/{id}' -> 'user', '/a/{post}' -> 'a' + if (preg_match('#^/([\w-]+)/(?:[\w\/-]*)#', $path, $m)) { + [$start, $first] = $m; + $this->pathStart = $start === '/' ? '' : $start; + } + + // quote '.','/' to '\.','\/' + if (false !== strpos($path, '.')) { + $path = str_replace('.', '\.', $path); + } + + // Parse the optional parameters + if (false !== $optPos) { + $noClosingOptionals = rtrim($path, ']'); + $optionalNum = strlen($path) - strlen($noClosingOptionals); + if ($optionalNum !== substr_count($noClosingOptionals, '[')) { + throw new LogicException('Optional segments can only occur at the end of a route'); + } + + // '/hello[/{name}]' -> '/hello(?:/{name})?' + $path = str_replace(['[', ']'], ['(?:', ')?'], $path); + // No params + if ($argPos === false) { + $this->pathRegex = '#^' . $path . '$#'; + return $first; + } + } + + if ($bindVars = $this->getBindVars()) { // merge current route vars + $bindParams = array_merge($bindParams, $bindVars); + } + + // Parse the parameters and replace them with the corresponding regular + $path = preg_replace_callback('#\{([a-zA-Z_][\w-]*)\}#', function ($m) use ($bindParams) { + $this->pathVars[] = $m[1]; + + $regex = $bindParams[$m[1]] ?? Router::DEFAULT_REGEX; + return '(' . $regex . ')'; + }, $path); + + $this->pathRegex = '#^' . $path . '$#'; + return $first; + } + + /******************************************************************************* + * route match + ******************************************************************************/ + + /** + * @param string $path + * + * @return array returns match result. has two elements. + * [ + * match ok?, + * route params values + * ] + */ + public function match(string $path): array + { + // Check start string + if ($this->pathStart !== '' && strpos($path, $this->pathStart) !== 0) { + return [false,]; + } + + return $this->matchRegex($path); + } + + /** + * @param string $path + * + * @return array + * [ + * match ok?, + * route params values + * ] + */ + public function matchRegex(string $path): array + { + // If don't match + if (!preg_match($this->pathRegex, $path, $matches)) { + return [false,]; + } + + // No params. eg: only use optional. '/about[.html]' + if (count($this->pathVars) === 0) { + return [true, []]; + } + + $params = []; + + // First is full match. + array_shift($matches); + foreach ($matches as $index => $value) { + $params[$this->pathVars[$index]] = $value; + } + + // If has default values + if (isset($this->options['defaults'])) { + $params = array_merge($this->options['defaults'], $params); + } + + return [true, $params]; + } + + /******************************************************************************* + * helper methods + ******************************************************************************/ + + /** + * @param array $params + * + * @return Route + */ + public function copyWithParams(array $params): self + { + $route = clone $this; + $route->params = $params; + + return $route; + } + + /** + * push middleware(s) to the route + * + * @param array ...$middleware + * + * @return Route + */ + public function middleware(...$middleware): self + { + foreach ($middleware as $handler) { + $this->chains[] = $handler; + } + + return $this; + } + + /** + * alias of the method: middleware() + * + * @param mixed ...$middleware + * + * @return Route + * @see middleware() + */ + public function push(...$middleware): self + { + return $this->middleware(...$middleware); + } + + /** + * replace set chains. + * + * @param callable[] $chains + */ + public function setChains(array $chains): void + { + $this->chains = $chains; + } + + /** + * build uri string. + * + * @param array $pathVars + * + * @return string + */ + public function toUri(array $pathVars = []): string + { + if ($pathVars) { + return strtr($this->path, $pathVars); + } + + return $this->path; + } + + /** + * get basic info data + * @return array + */ + public function info(): array + { + return [ + 'path' => $this->path, + 'method' => $this->method, + 'handlerName' => $this->getHandlerName(), + ]; + } + + /** + * get all info data + * @return array + */ + public function toArray(): array + { + return [ + 'name' => $this->name, + 'path' => $this->path, + 'method' => $this->method, + 'handler' => $this->handler, + 'binds' => $this->bindVars, + 'params' => $this->params, + 'options' => $this->options, + // + 'pathVars' => $this->pathVars, + 'pathStart' => $this->pathStart, + 'pathRegex' => $this->pathRegex, + // + 'chains' => $this->chains, + ]; + } + + /** + * @return string + */ + public function __toString(): string + { + return $this->toString(); + } + + /** + * @return string + */ + public function toString(): string + { + return sprintf( + '%-7s %-25s --> %s (%d middleware)', + $this->method, + $this->path, + $this->getHandlerName(), + count($this->chains) + ); + } + + /** + * @param string $name + * + * @return Route + */ + public function setName(string $name): self + { + if ($name = trim($name)) { + $this->name = $name; + } + + return $this; + } + + /** + * @param string $path + */ + public function setPath(string $path): void + { + $this->path = trim($path); + } + + /** + * @param string $name + * @param $value + * + * @return Route + */ + public function addOption(string $name, $value): self + { + $this->options[$name] = $value; + return $this; + } + + /** + * @param array $options + * + * @return Route + */ + public function setOptions(array $options): self + { + $this->options = $options; + return $this; + } + + /******************************************************************************* + * getter methods + ******************************************************************************/ + + /** + * Retrieve an external iterator + * @link https://php.net/manual/en/iteratoraggregate.getiterator.php + * @return Traversable An instance of an object implementing Iterator or Traversable + * @since 5.0.0 + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->toArray()); + } + + /** + * @return string + */ + public function getPath(): string + { + return $this->path; + } + + /** + * @return mixed + */ + public function getHandler() + { + return $this->handler; + } + + /** + * @return string[] + */ + public function getParams(): array + { + return $this->params; + } + + /** + * @param string $name + * @param null|mixed $default + * + * @return string|mixed + */ + public function getParam(string $name, $default = null) + { + return $this->params[$name] ?? $default; + } + + /** + * @return array + */ + public function getOptions(): array + { + return $this->options; + } + + /** + * @return string[] + */ + public function getBindVars(): array + { + return $this->bindVars; + } + + /** + * @return string + */ + public function getMethod(): string + { + return $this->method; + } + + /** + * @return array + */ + public function getPathVars(): array + { + return $this->pathVars; + } + + /** + * @return string + */ + public function getPathRegex(): string + { + return $this->pathRegex; + } + + /** + * @return string + */ + public function getPathStart(): string + { + return $this->pathStart; + } + + /** + * @return array + */ + public function getChains(): array + { + return $this->chains; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string + */ + public function getHandlerName(): string + { + $handlerName = 'unknown'; + + if (is_object($this->handler)) { + $handlerName = get_class($this->handler); + } elseif (is_array($this->handler)) { + $handlerName = '[array callback]'; + } elseif (is_string($this->handler)) { + $handlerName = $this->handler; + } + + return $handlerName; + } +} diff --git a/src/Router.php b/src/Router.php new file mode 100644 index 0000000..2371417 --- /dev/null +++ b/src/Router.php @@ -0,0 +1,824 @@ + Route] + */ + protected array $namedRoutes = []; + + /** + * static Routes - no dynamic argument match + * 整个路由 path 都是静态字符串 e.g. '/user/login' + * + * @var Route[] + * [ + * 'GET /user/login' => Route, + * 'POST /user/login' => Route, + * ] + */ + protected array $staticRoutes = []; + + /** + * regular Routes - have dynamic arguments, but the first node is normal string. + * 第一节是个静态字符串,称之为有规律的动态路由。按第一节的信息进行分组存储 + * + * @var Route[][] + * [ + * // 使用完整的第一节作为key进行分组 + * 'edit' => [ + * Route, // '/edit/{id}' + * ], + * 'blog' => [ + * Route, // '/blog/post-{id}' + * ], + * ] + */ + protected array $regularRoutes = []; + + /** + * vague Routes - have dynamic arguments,but the first node is exists regex. + * 第一节就包含了正则匹配,称之为无规律/模糊的动态路由 + * + * @var Route[][] + * [ + * // 使用 HTTP METHOD 作为 key进行分组 + * 'GET' => [ + * Route, // '/{name}/profile' + * ... + * ], + * 'POST' => [ + * Route, // '/{some}/{some2}' + * ... + * ], + * ] + */ + protected array $vagueRoutes = []; + + /** + * object creator. + * + * @param array $config + * + * @return self + * @throws LogicException + */ + public static function create(array $config = []): Router + { + return new static($config); + } + + /** + * object constructor. + * + * @param array $config = [ + * 'name' => 'my-router', + * 'chains' => [], + * // 'defaultRoute' => '', + * 'ignoreLastSlash' => false, + * 'tmpCacheNumber' => 100, + * 'handleMethodNotAllowed' => false, + * 'autoRoute' => false, + * 'controllerNamespace' => '', + * 'controllerSuffix' => 'Controller', + * ]; + * + * @throws LogicException + */ + public function __construct(array $config = []) + { + $this->config($config); + $this->basicRoute = new Route('GET', '/', null); + + $this->currentGroupPrefix = ''; + $this->currentGroupOption = []; + } + + /******************************************************************************* + * router middleware + ******************************************************************************/ + + /** + * alias of the method: middleware() + * + * @param array ...$middleware + * + * @return self + */ + public function use(...$middleware): Router + { + return $this->middleware(...$middleware); + } + + /** + * push middleware(s) for the route + * + * @param mixed ...$middleware + * + * @return Router + */ + public function middleware(...$middleware): Router + { + foreach ($middleware as $handler) { + $this->chains[] = $handler; + } + + return $this; + } + + /******************************************************************************* + * route register + ******************************************************************************/ + + /** + * register a route, allow GET request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function get(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('GET', $path, $handler, $pathParams, $opts); + // return $this->map(['GET', 'HEAD'], $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow POST request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function post(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('POST', $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow PUT request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function put(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('PUT', $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow PATCH request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function patch(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('PATCH', $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow DELETE request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function delete(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('DELETE', $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow HEAD request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function head(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('HEAD', $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow OPTIONS request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function options(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('OPTIONS', $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow CONNECT request method. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function connect(string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + return $this->add('CONNECT', $path, $handler, $pathParams, $opts); + } + + /** + * register a route, allow any request METHOD. + * + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + */ + public function any(string $path, mixed $handler, array $pathParams = [], array $opts = []): void + { + $this->map(self::METHODS_ARRAY, $path, $handler, $pathParams, $opts); + } + + /** + * @param array|string $methods + * @param string $path + * @param callable|string $handler + * @param array $pathParams + * @param array $opts + */ + public function map($methods, string $path, mixed $handler, array $pathParams = [], array $opts = []): void + { + foreach ((array)$methods as $method) { + $this->add($method, $path, $handler, $pathParams, $opts); + } + } + + /** + * @param string $method + * @param string $path + * @param mixed $handler + * @param array $pathParams + * @param array $opts + * + * @return Route + */ + public function add(string $method, string $path, mixed $handler, array $pathParams = [], array $opts = []): Route + { + if (!$method || !$handler) { + throw new InvalidArgumentException('The method and route handler is not allow empty.'); + } + + $route = $this->cloneRoute(); + $method = strtoupper($method); + if ($method === 'ANY') { + $this->any($path, $handler, $pathParams, $opts); + return $route; // Only use for return type + } + + if (!str_contains(self::METHODS_STRING, ',' . $method . ',')) { + throw new InvalidArgumentException( + "The method [$method] is not supported, Allow: " . trim(self::METHODS_STRING, ',') + ); + } + + // Initialize Route + $route->initialize($method, $path, $handler, $pathParams, $opts); + + return $this->addRoute($route); + } + + /** + * @param Route $route + * + * @return Route + */ + public function addRoute(Route $route): Route + { + $this->routeCounter++; + $this->appendGroupInfo($route); + + $path = $route->getPath(); + $method = $route->getMethod(); + if ($name = $route->getName()) { + $this->namedRoutes[$name] = $route; + } + + // It is static route + $argPos = strpos($path, '{'); + $optPos = strpos($path, '['); + if ($argPos === false && $optPos === false) { + $this->staticRoutes[$method . ' ' . $path] = $route; + return $route; + } + + // Parse param route + // - If the first node is static string. + $globalParams = self::$globalParams; + if ($first = $route->quickParseParams($argPos, $optPos, $globalParams)) { + $this->regularRoutes[$method . ' ' . $first][] = $route; + } else { + $this->vagueRoutes[$method][] = $route; + } + + return $route; + } + + /** + * Create a route group with a common prefix. + * All routes created in the passed callback will have the given group prefix prepended. + * + * @param string $prefix + * @param Closure $callback + * @param array $middleware + * @param array $opts + */ + public function group(string $prefix, Closure $callback, array $middleware = [], array $opts = []): void + { + // Backups + $previousGroupPrefix = $this->currentGroupPrefix; + $previousGroupOption = $this->currentGroupOption; + $previousGroupChains = $this->currentGroupChains; + + $this->currentGroupOption = $opts; + $this->currentGroupChains = $middleware; + $this->currentGroupPrefix = $previousGroupPrefix . '/' . trim($prefix, '/'); + + // Run callback. + $callback($this); + + // Reverts + $this->currentGroupPrefix = $previousGroupPrefix; + $this->currentGroupOption = $previousGroupOption; + $this->currentGroupChains = $previousGroupChains; + } + + /** + * prepare for add + * + * @param Route $route + * + * @return void + */ + protected function appendGroupInfo(Route $route): void + { + $path = $bak = $route->getPath(); + + // Always add '/' prefix. + $path = str_starts_with($path, '/') ? $path : '/' . $path; + $path = $this->currentGroupPrefix . $path; + + // Has setting 'ignoreLastSlash' + if ($path !== '/' && $this->ignoreLastSlash) { + $path = rtrim($path, '/'); + } + + // Not in group and path not change. + if ($bak === $path) { + return; + } + + $route->setPath($path); + + // Not in group + if (!$this->currentGroupPrefix) { + return; + } + + if ($this->currentGroupOption) { + $route->setOptions(array_merge($this->currentGroupOption, $route->getOptions())); + } + + // Prepend group middleware at before. + if ($this->currentGroupChains) { + $route->setChains(array_merge($this->currentGroupChains, $route->getChains())); + } + } + + /******************************************************************************* + * route match + ******************************************************************************/ + + /** + * find the matched route info for the given request uri path + * + * @param string $method + * @param string $path + * + * @return array returns array. + * [ + * match status, // found, not found, method not allowed + * formatted path, + * (Route object) OR (allowed methods list) + * ] + */ + public function match(string $path, string $method = 'GET'): array + { + // For HEAD requests, attempt fallback to GET + $method = strtoupper($method); + if ($method === 'HEAD') { + $method = 'GET'; + } + + $path = RouteHelper::formatPath($path, $this->ignoreLastSlash); + $sKey = $method . ' ' . $path; + + // It is a static route path + if (isset($this->staticRoutes[$sKey])) { + return [self::FOUND, $path, $this->staticRoutes[$sKey]]; + } + + // It is a dynamic route, match by regexp + $result = $this->matchDynamicRoute($path, $method); + if ($result[0] === self::FOUND) { + return $result; + } + + // Handle Auto Route. always return new Route object. + if ($this->autoRoute && ($handler = $this->matchAutoRoute($path))) { + return [self::FOUND, $path, Route::create($method, $path, $handler)]; + } + + // If nothing else matches, try fallback routes. $router->any('*', 'handler'); + $sKey = $method . ' /*'; + if (isset($this->staticRoutes[$sKey])) { + return [self::FOUND, $path, $this->staticRoutes[$sKey]]; + } + + if ($this->handleMethodNotAllowed) { + return $this->findAllowedMethods($path, $method); + } + + return [self::NOT_FOUND, $path, null]; + } + + /** + * is a dynamic route, match by regexp + * + * @param string $path + * @param string $method + * + * @return array + * [ + * status, + * path, + * Route(object) -> it's a raw Route clone. + * ] + */ + protected function matchDynamicRoute(string $path, string $method): array + { + $first = strstr(ltrim($path, '/'), '/', true); + $fKey = $first ? $method . ' ' . $first : ''; + + // It is a regular dynamic route(the first node is 1th level index key). + if ($fKey && isset($this->regularRoutes[$fKey])) { + foreach ($this->regularRoutes[$fKey] as $route) { + // Check path start string + $pathStart = $route->getPathStart(); + if (!str_starts_with($path, $pathStart)) { + continue; + } + + $result = $route->matchRegex($path); + if ($result[0]) { + return [self::FOUND, $path, $route->copyWithParams($result[1])]; + } + } + } + + // It is a irregular dynamic route + // if ($routeList = $this->vagueRoutes[$method] ?? false) { + if (isset($this->vagueRoutes[$method])) { + foreach ($this->vagueRoutes[$method] as $route) { + $result = $route->matchRegex($path); + if ($result[0]) { + return [self::FOUND, $path, $route->copyWithParams($result[1])]; + } + } + } + + return [self::NOT_FOUND, $path, null]; + } + + /** + * handle auto route match, when config `'autoRoute' => true` + * + * @param string $path The route path + * + * @return bool|string + */ + public function matchAutoRoute(string $path): string|bool + { + if (!$cnp = trim($this->controllerNamespace)) { + return false; + } + + $sfx = trim($this->controllerSuffix); + + return RouteHelper::parseAutoRoute($path, $cnp, $sfx, $this->namespaceUcFirst); + } + + /** + * @param string $path + * @param string $method + * + * @return array + */ + protected function findAllowedMethods(string $path, string $method): array + { + $methods = []; + foreach (self::METHODS_ARRAY as $m) { + if ($method === $m) { + continue; + } + + $sKey = $m . ' ' . $path; + if (isset($this->staticRoutes[$sKey])) { + $methods[$m] = 1; + continue; + } + + $result = $this->matchDynamicRoute($path, $m); + if ($result[0] === self::FOUND) { + $methods[$m] = 1; + } + } + + if ($methods) { + return [self::METHOD_NOT_ALLOWED, $path, array_keys($methods)]; + } + return [self::NOT_FOUND, $path, null]; + } + + /******************************************************************************* + * route dispatch + ******************************************************************************/ + + /** + * Runs the callback for the given request + * + * @param array|DispatcherInterface|null $dispatcher + * @param string $path + * @param string $method + * + * @return mixed + * @throws LogicException + * @throws Throwable + */ + public function dispatch(DispatcherInterface|array|null $dispatcher = null, string $path = '', string $method = ''): mixed + { + if (!$dispatcher) { + $dispatcher = new Dispatcher; + } elseif (is_array($dispatcher)) { + $dispatcher = new Dispatcher($dispatcher); + } + + if (!$dispatcher instanceof DispatcherInterface) { + throw new InvalidArgumentException( + 'The first argument is must an array OR an object instanceof the DispatcherInterface' + ); + } + + if (!$dispatcher->hasRouter()) { + $dispatcher->setRouter($this); + } + + return $dispatcher->dispatchUri($path, $method); + } + + /******************************************************************************* + * helper methods + ******************************************************************************/ + + /** + * @param string $name Route name + * @param array $pathVars + * + * @return string + */ + public function createUri(string $name, array $pathVars = []): string + { + if ($route = $this->getRoute($name)) { + return $route->toUri($pathVars); + } + + return ''; + } + + /** + * @param string $name + * @param Route $route + */ + public function nameRoute(string $name, Route $route): void + { + if ($name = trim($name)) { + $this->namedRoutes[$name] = $route; + } + } + + /** + * get a name route by given name. + * + * @param string $name + * + * @return Route|null + */ + public function getRoute(string $name): ?Route + { + return $this->namedRoutes[$name] ?? null; + } + + /** + * @return int + */ + public function count(): int + { + return $this->routeCounter; + } + + /** + * @param Closure $func + */ + public function each(Closure $func): void + { + foreach ($this->staticRoutes as $route) { + $func($route); + } + + foreach ($this->regularRoutes as $routes) { + foreach ($routes as $route) { + $func($route); + } + } + + foreach ($this->vagueRoutes as $routes) { + foreach ($routes as $route) { + $func($route); + } + } + } + + /** + * get all routes + * + * @return array + */ + public function getRoutes(): array + { + $routes = []; + $this->each(static function (Route $route) use (&$routes) { + $routes[] = $route; + }); + + return $routes; + } + + /** + * @return array + */ + public function getChains(): array + { + return $this->chains; + } + + protected function cloneRoute(): Route + { + return clone $this->basicRoute; + } + + /** + * Retrieve an external iterator + * + * @link https://php.net/manual/en/iteratoraggregate.getiterator.php + * @return Traversable An instance of an object implementing Iterator or + * Traversable + * @since 5.0.0 + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->getRoutes()); + } + + /** + * @return string + */ + public function __toString(): string + { + return $this->toString(); + } + + /** + * @return string + */ + public function toString(): string + { + $indent = ' '; + $strings = ['#Routes Number: ' . $this->count()]; + $strings[] = "\n#Static Routes:"; + foreach ($this->staticRoutes as $route) { + $strings[] = $indent . $route->toString(); + } + + $strings[] = "\n# Regular Routes:"; + foreach ($this->regularRoutes as $routes) { + foreach ($routes as $route) { + $strings[] = $indent . $route->toString(); + } + } + + $strings[] = "\n# Vague Routes:"; + foreach ($this->vagueRoutes as $routes) { + foreach ($routes as $route) { + $strings[] = $indent . $route->toString(); + } + } + + return implode("\n", $strings); + } +} diff --git a/src/RouterConfigTrait.php b/src/RouterConfigTrait.php new file mode 100644 index 0000000..b2b22d8 --- /dev/null +++ b/src/RouterConfigTrait.php @@ -0,0 +1,216 @@ +get('/user/{id}', 'handler'); + * + * @var array + */ + protected static array $globalParams = [ + 'all' => '.*', + 'any' => '[^/]+', // match any except '/' + 'num' => '[1-9][0-9]*', // match a number and gt 0 + 'int' => '\d+', // match a number + 'act' => '[a-zA-Z][\w-]+', // match a action name + ]; + + /******************************************************************************* + * router config + ******************************************************************************/ + + /* + * Can define an default route path + * + * @var string + */ + // public $defaultRoute = ''; + + /** + * Ignore last slash char('/'). If is True, will clear last '/'. + * + * @var bool + */ + public bool $ignoreLastSlash = false; + + /** + * Whether handle method not allowed. If True, will find allowed methods. + * + * @var bool + */ + public bool $handleMethodNotAllowed = false; + + /** + * Enable auto route match like yii framework + * If is True, will auto find the handler controller file. + * + * @var bool + */ + public bool $autoRoute = false; + + /** + * The default controllers namespace. eg: 'App\\Controllers' + * + * @var string + */ + public string $controllerNamespace = ''; + + /** + * The first char case of namespace. + * + * false - lower case. eg: 'controllers\admin' + * true - upper case. eg: 'Controllers\Admin' + * + * @var bool + */ + protected bool $namespaceUcFirst = false; + + /** + * Controller suffix, is valid when '$autoRoute' = true. eg: 'Controller' + * + * @var string + */ + public string $controllerSuffix = 'Controller'; + + /** + * @var array global Options + */ + private array $globalOptions = [ + // 'domains' => [ 'localhost' ], // allowed domains + // 'schemas' => [ 'http' ], // allowed schemas + // 'time' => ['12'], + ]; + + /** + * config the router + * + * @param array $config + * + * @throws LogicException + */ + public function config(array $config): void + { + if ($this->routeCounter > 0) { + throw new LogicException('Routing has been added, and configuration is not allowed!'); + } + + $props = [ + 'name' => 1, + 'chains' => 1, + // 'defaultRoute' => 1, + 'ignoreLastSlash' => 1, + 'handleMethodNotAllowed' => 1, + 'autoRoute' => 1, + 'controllerNamespace' => 1, + 'controllerSuffix' => 1, + ]; + + foreach ($config as $name => $value) { + $setter = 'set' . ucfirst($name); + if (method_exists($this, $setter)) { + $this->$setter($value); + } elseif (isset($props[$name])) { + $this->$name = $value; + } + } + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName(string $name): void + { + $this->name = $name; + } + + /** + * @param array $params + */ + public function addGlobalParams(array $params): void + { + foreach ($params as $name => $pattern) { + $this->addGlobalParam($name, $pattern); + } + } + + /** + * @param string $name + * @param string $pattern + */ + public function addGlobalParam(string $name, string $pattern): void + { + $name = trim($name, '{} '); + + self::$globalParams[$name] = $pattern; + } + + /** + * @return array + */ + public function getGlobalParams(): array + { + return self::$globalParams; + } + + /** + * @return array + */ + public function getGlobalOptions(): array + { + return $this->globalOptions; + } + + /** + * @param array $globalOptions + */ + public function setGlobalOptions(array $globalOptions): void + { + $this->globalOptions = $globalOptions; + } + + /** + * @return bool + */ + public function isNamespaceUcFirst(): bool + { + return $this->namespaceUcFirst; + } + + /** + * @param bool $namespaceUcFirst + */ + public function setNamespaceUcFirst($namespaceUcFirst): void + { + $this->namespaceUcFirst = (bool)$namespaceUcFirst; + } +} diff --git a/src/RouterInterface.php b/src/RouterInterface.php index be69196..78179df 100644 --- a/src/RouterInterface.php +++ b/src/RouterInterface.php @@ -1,4 +1,4 @@ - '[0-9]+', ] + * @param array $opts Extra options + * - name: string + * - ... more + * + * @return Route */ - const SUPPORTED_METHODS = [ - 'ANY', - 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD', 'SEARCH', 'CONNECT', 'TRACE', - ]; + public function add(string $method, string $path, $handler, array $pathParams = [], array $opts = []): Route; + + /** + * add a Route to the router + * + * @param Route $route + * + * @return Route + */ + public function addRoute(Route $route): Route; /** - * the matched result index key + * @param array|string $methods The match request method(s). e.g ['get','post'] + * @param string $path The route path string. is allow empty string. eg: '/user/login' + * @param callable|string $handler + * @param array $pathParams route path var bind. eg. [ 'id' => '[0-9]+', ] + * @param array $opts some option data + * [ + * 'defaults' => [ 'id' => 10, ], + * 'domains' => [ 'a-domain.com', '*.b-domain.com'], + * 'schemas' => ['https'], + * ] + */ + public function map($methods, string $path, $handler, array $pathParams = [], array $opts = []): void; + + /** + * find the matched route info for the given request uri path + * + * @param string $method + * @param string $path + * + * @return array + * + * [self::NOT_FOUND, $path, null] + * [self::METHOD_NOT_ALLOWED, $path, ['GET', 'OTHER_METHODS_ARRAY']] + * [self::FOUND, $path, array () // routeData ] + * */ - const INDEX_STATUS = 0; - const INDEX_PATH = 1; - const INDEX_INFO = 2; + public function match(string $path, string $method = 'GET'): array; /** * @return array */ - public static function getSupportedMethods(); + public function getChains(): array; } diff --git a/src/RouterManager.php b/src/RouterManager.php new file mode 100644 index 0000000..ee676fb --- /dev/null +++ b/src/RouterManager.php @@ -0,0 +1,313 @@ + Object(Router), + * ... ... + * ] + */ + private $routers = []; + + /** + * @var array Available router driver + */ + private $drivers = [ + 'default' => Router::class, + 'cached' => CachedRouter::class, + 'preMatch' => PreMatchRouter::class, + 'server' => ServerRouter::class, + ]; + + /** + * @var array[] + * [ + * 'default' => 'main-site', // this is default router. + * 'main-site' => [ + * 'driver' => 'default', + * 'conditions' => [ + * 'domains' => 'abc.com', + * 'schemes' => ['https'], + * ], + * 'options' => [ + * // some setting for router. + * 'name' => 'value' + * ], + * ], + * 'doc-site' => [ + * 'driver' => 'cached', + * 'conditions' => [ + * 'domains' => 'docs.abc.com', + * ], + * 'options' => [ + * 'cacheFile' => '/path/to/routes-cache.php', + * 'cacheEnable' => true, + * ], + * ], + * ] + */ + private $configs; + + /** + * @var array + * [ + * 'main-site' => [ + * 'domains' => 'abc.com', + * 'schemes' => ['https'], + * ], + * 'doc-site' => [ + * 'domains' => 'docs.abc.com', + * 'schemes' => ['https'], + * ], + * 'th3-site' => [ + * 'domains' => 'th3.abc.com', + * ], + * ] + */ + private $conditions = []; + + /** + * @var array + */ + private $supportedConditions = [ + 'domains' => 'domain', + 'schemes' => 'scheme', + ]; + + /** + * @var array + */ + // private $onCollected = [ + // 'cached' => 'completed', + // 'server' => 'flattenStatics' + // ]; + + /** + * @return RouterManager + */ + public static function instance(): RouterManager + { + return self::$_instance; + } + + /** + * RouterManager constructor. + * + * @param array $configs + */ + public function __construct(array $configs = []) + { + self::$_instance = $this; + + if ($configs) { + $this->configs($configs); + } + } + + // match by $_SERVER info. + + /** + * get router by condition + * + * @param array|string $condition + * array: + * [ + * 'domain' => 'abc.com', + * 'scheme' => 'https', + * ] + * string: + * get by name. same of call getByName() + * + * @return Router |RouterInterface + * @throws InvalidArgumentException + */ + public function get($condition = null): Router + { + if (!$condition) { + return $this->getDefault(); + } + + // alias of getByName() + if (is_string($condition)) { + return $this->getByName($condition); + } + + $useName = self::DEFAULT_ROUTER; + + foreach ($this->conditions as $name => $cond) { + if ($this->compareArray($cond, $condition)) { + $useName = $name; + break; + } + } + + return $this->getByName($useName); + } + + /** + * @param array $define + * @param array $input + * + * @return bool + */ + protected function compareArray(array $define, array $input): bool + { + $match = true; + + foreach ($this->supportedConditions as $def => $key) { + if (isset($define[$def], $input[$key])) { + $defValues = (array)$define[$def]; + + if (!in_array($input[$key], $defValues, true)) { + $match = false; + break; + } + } + } + + return $match; + } + + /** + * @param string $name + * + * @return Router + * @throws InvalidArgumentException + */ + public function getByName(string $name): Router + { + if (!isset($this->configs[$name])) { + throw new InvalidArgumentException("The named router '$name' does not exists!"); + } + + // if created + if (isset($this->routers[$name])) { + return $this->routers[$name]; + } + + // create + $config = $this->configs[$name]; + + if (is_string($config)) { + if (!isset($this->configs[$config])) { + throw new InvalidArgumentException("The reference config '$config' does not exists of the '$name'!"); + } + + $config = $this->configs[$config]; + } + + return ($this->routers[$name] = $this->createRouter($config, $name)); + } + + /** + * @return Router + * @throws InvalidArgumentException + */ + public function getDefault(): Router + { + return $this->getByName(self::DEFAULT_ROUTER); + } + + /** + * @param array $config + * @param string $name + * + * @return Router + * @throws InvalidArgumentException + */ + private function createRouter(array $config, string $name = ''): Router + { + $driver = $config['driver'] ?? self::DEFAULT_ROUTER; + $options = $config['options'] ?? []; + + if (!$class = $this->drivers[$driver] ?? null) { + throw new InvalidArgumentException("The router driver name '$driver' does not exists!"); + } + + if ($name && !isset($options['name'])) { + $options['name'] = $name; + } + + return new $class($options); + } + + /** + * @param string $name + * @param string $class + */ + public function setDriver(string $name, string $class): void + { + $this->drivers[$name] = $class; + } + + /** + * @return Router[] + */ + public function getRouters(): array + { + return $this->routers; + } + + /** + * @return array + */ + public function getDrivers(): array + { + return $this->drivers; + } + + /** + * @return array[] + */ + public function getConfigs(): array + { + return $this->configs; + } + + /** + * @param array[] $configs + */ + public function configs(array $configs): void + { + $this->configs = $configs; + + foreach ($configs as $name => $config) { + if (isset($config['conditions'])) { + $this->conditions[$name] = $config['conditions']; + } + } + } + + /** + * @return array + */ + public function getConditions(): array + { + return $this->conditions; + } +} diff --git a/src/SRouter.php b/src/SRouter.php index 3bc1a76..87a8eae 100644 --- a/src/SRouter.php +++ b/src/SRouter.php @@ -1,4 +1,4 @@ - '', - 'ignoreLastSep' => false, - 'tmpCacheNumber' => 0, - 'matchAll' => false, - - // auto route match @like yii framework - 'autoRoute' => false, - 'controllerNamespace' => '', // eg: 'app\\controllers' - 'controllerSuffix' => '', // eg: 'Controller' - ]; - - /** @var DispatcherInterface */ - private static $dispatcher; - - /** - * @param array $config - * @throws \LogicException - */ - public static function setConfig(array $config) + private function __construct() { - if (self::$initialized) { - throw new \LogicException('Routing has been added, and configuration is not allowed!'); - } - - foreach ($config as $name => $value) { - if (isset(self::$config[$name])) { - self::$config[$name] = $value; - } - } - - // load routes - if (($file = self::$config['routesFile']) && is_file($file)) { - require $file; - } } - /******************************************************************************* - * route collection - ******************************************************************************/ - /** * Defines a route callback and method - * @param string $method - * @param array $args - * @throws \InvalidArgumentException - * @throws \LogicException - */ - public static function __callStatic($method, array $args) - { - if (\count($args) < 2) { - throw new \InvalidArgumentException("The method [$method] parameters is required."); - } - - self::map($method, $args[0], $args[1], isset($args[2]) ? $args[2] : []); - } - - /** - * Create a route group with a common prefix. - * All routes created in the passed callback will have the given group prefix prepended. * - * @ref package 'nikic/fast-route' - * @param string $prefix - * @param \Closure $callback - * @param array $opts - */ - public static function group($prefix, \Closure $callback, array $opts = []) - { - $previousGroupPrefix = self::$currentGroupPrefix; - self::$currentGroupPrefix = $previousGroupPrefix . $prefix; - - $previousGroupOption = self::$currentGroupOption; - self::$currentGroupOption = $opts; - - $callback(); - - self::$currentGroupPrefix = $previousGroupPrefix; - self::$currentGroupOption = $previousGroupOption; - } - - /** - * @see ORouter::map() - * @param string|array $methods The match request method. - * @param string $route The route path string. eg: '/user/login' - * @param callable|string $handler - * @param array $opts some option data - * @return true - * @throws \LogicException - * @throws \InvalidArgumentException - */ - public static function map($methods, $route, $handler, array $opts = []) - { - if (!self::$initialized) { - self::$initialized = true; - } - - // validate arguments - $methods = static::validateArguments($methods, $handler); - - if ($route = trim($route)) { - // always add '/' prefix. - $route = $route{0} === '/' ? $route : '/' . $route; - } else { - $route = '/'; - } - - $route = self::$currentGroupPrefix . $route; - - // setting 'ignoreLastSep' - if ($route !== '/' && self::$config['ignoreLastSep']) { - $route = rtrim($route, '/'); - } - - self::$routeCounter++; - $opts = array_replace([ - 'params' => null, - // 'domains' => null, - ], self::$currentGroupOption, $opts); - $conf = [ - 'methods' => $methods, - 'handler' => $handler, - 'option' => $opts, - ]; - - // no dynamic param params - if (self::isNoDynamicParam($route)) { - self::$staticRoutes[$route][] = $conf; - - return true; - } - - // have dynamic param params - - // replace param name To pattern regex - $params = self::getAvailableParams(self::$globalParams, $opts['params']); - list($first, $conf) = static::parseParamRoute($route, $params, $conf); - - // route string have regular - if ($first) { - self::$regularRoutes[$first][] = $conf; - } else { - self::$vagueRoutes[] = $conf; - } - - return true; - } - - /******************************************************************************* - * route match - ******************************************************************************/ - - /** - * find the matched route info for the given request uri path * @param string $method - * @param string $path - * @return array + * @param array $args + * + * @return Router|mixed + * @throws InvalidArgumentException + * @throws LogicException */ - public static function match($path, $method = self::GET) + public static function __callStatic($method, array $args) { - // if enable 'matchAll' - if ($matchAll = static::$config['matchAll']) { - if (\is_string($matchAll) && $matchAll{0} === '/') { - $path = $matchAll; - } elseif (\is_callable($matchAll)) { - return [self::FOUND, $path, [ - 'handler' => $matchAll, - 'option' => [], - ]]; - } + if (method_exists(self::getRouter(), $method)) { + return self::getRouter()->$method(...$args); } - // clear '//', '///' => '/' - $path = rawurldecode(preg_replace('#\/\/+#', '/', $path)); - $method = strtoupper($method); - - // find in class cache. - if (self::$routeCaches && isset(self::$routeCaches[$path])) { - return self::findInStaticRoutes(self::$staticRoutes[$path], $path, $method); - } - - // is a static path route - if (self::$staticRoutes && isset(self::$staticRoutes[$path])) { - return self::findInStaticRoutes(self::$staticRoutes[$path], $path, $method); - } - - $first = self::getFirstFromPath($path); - - // is a regular dynamic route(the first char is 1th level index key). - if (isset(self::$regularRoutes[$first])) { - foreach (self::$regularRoutes[$first] as $conf) { - if (0 === strpos($path, $conf['start']) && preg_match($conf['regex'], $path, $matches)) { - $conf['matches'] = $matches; - - return self::checkMatched($path, $method, $conf); - } - } - } - - // is a irregular dynamic route - foreach (self::$vagueRoutes as $conf) { - if ($conf['include'] && false === strpos($path, $conf['include'])) { - continue; - } - - if (preg_match($conf['regex'], $path, $matches)) { - $conf['matches'] = $matches; - - return self::checkMatched($path, $method, $conf); - } - } - - // handle Auto Route - if ( - self::$config['autoRoute'] && - ($handler = self::matchAutoRoute($path, self::$config['controllerNamespace'], self::$config['controllerSuffix'])) - ) { - return [self::FOUND, $path, [ - 'handler' => $handler, - 'option' => [], - ]]; - } - - // oo ... not found - return [self::NOT_FOUND, $path, null]; + throw new InvalidArgumentException("call invalid method: $method"); } - /******************************************************************************* - * route callback handler dispatch - ******************************************************************************/ - /** - * Runs the callback for the given request - * @param DispatcherInterface|array $dispatcher - * @param null|string $path - * @param null|string $method - * @return mixed - * @throws \Throwable + * @return Router|RouterInterface */ - public static function dispatch($dispatcher = null, $path = null, $method = null) + public static function getRouter(): RouterInterface { - if ($dispatcher) { - if ($dispatcher instanceof DispatcherInterface) { - self::$dispatcher = $dispatcher; - } elseif (\is_array($dispatcher)) { - self::$dispatcher = new Dispatcher($dispatcher); - } - } - - if (!self::$dispatcher) { - self::$dispatcher = new Dispatcher; + if (!self::$router) { + self::$router = new Router(); } - return self::$dispatcher->setMatcher(function ($p, $m) { - return self::match($p, $m); - })->dispatch($path, $method); + return self::$router; } - /******************************************************************************* - * helper methods - ******************************************************************************/ - /** - * checkMatched - * @param string $path - * @param string $method - * @param array $conf - * @return array + * @param RouterInterface $router */ - protected static function checkMatched($path, $method, array $conf) + public static function setRouter(RouterInterface $router): void { - $methods = $conf['methods']; - $cacheNumber = (int)self::$config['tmpCacheNumber']; - - // method not allowed - if (false === strpos($methods . ',', $method . ',')) { - return [self::METHOD_NOT_ALLOWED, $path, explode(',', $methods)]; - } - - $conf['matches'] = self::filterMatches($conf['matches'], $conf); - - // cache last $cacheNumber routes. - if ($cacheNumber > 0) { - if (self::$cacheCounter === $cacheNumber) { - array_shift(self::$routeCaches); - } - - if (!isset(self::$routeCaches[$path][$methods])) { - self::$cacheCounter++; - self::$routeCaches[$path][$methods] = $conf; - } - } - - return [self::FOUND, $path, $conf]; + self::$router = $router; } - - /** - * @return int - */ - public static function count() - { - return self::$routeCounter; - } - - /** - * @return array - */ - public static function getStaticRoutes() - { - return self::$staticRoutes; - } - - /** - * @return \array[] - */ - public static function getRegularRoutes() - { - return self::$regularRoutes; - } - - /** - * @return array - */ - public static function getVagueRoutes() - { - return self::$vagueRoutes; - } - - /** - * @return array - */ - public static function getConfig() - { - return static::$config; - } - - /** - * @return DispatcherInterface - */ - public static function getDispatcher() - { - return self::$dispatcher; - } - - /** - * @param DispatcherInterface $dispatcher - */ - public static function setDispatcher(DispatcherInterface $dispatcher) - { - self::$dispatcher = $dispatcher; - } - } diff --git a/src/ServerRouter.php b/src/ServerRouter.php new file mode 100644 index 0000000..92f4dc4 --- /dev/null +++ b/src/ServerRouter.php @@ -0,0 +1,152 @@ + Route, + * 'PUT /user/login' => Route, + * ] + */ + private array $cacheRoutes = []; + + /** + * object constructor. + * + * @param array $config + * + * @throws LogicException + */ + public function __construct(array $config = []) + { + parent::__construct($config); + + if (isset($config['tmpCacheNumber'])) { + $this->tmpCacheNumber = (int)$config['tmpCacheNumber']; + } + } + + /******************************************************************************* + * route match + ******************************************************************************/ + + /** + * {@inheritdoc} + */ + public function match(string $path, string $method = 'GET'): array + { + // For HEAD requests, attempt fallback to GET + $method = strtoupper($method); + if ($method === 'HEAD') { + $method = 'GET'; + } + + $path = RouteHelper::formatPath($path, $this->ignoreLastSlash); + $sKey = $method . ' ' . $path; + + // It is a static route path + if (isset($this->staticRoutes[$sKey])) { + return [self::FOUND, $path, $this->staticRoutes[$sKey]]; + } + + // Find in route caches. + if ($this->cacheRoutes && isset($this->cacheRoutes[$sKey])) { + return [self::FOUND, $path, $this->cacheRoutes[$sKey]]; + } + + // It is a dynamic route, match by regexp + $result = $this->matchDynamicRoute($path, $method); + if ($result[0] === self::FOUND) { // will cache param route. + $this->cacheMatchedParamRoute($path, $method, $result[2]); + return $result; + } + + // Handle Auto Route + if ($this->autoRoute && ($handler = $this->matchAutoRoute($path))) { + return [self::FOUND, $path, Route::create($method, $path, $handler)]; + } + + // If nothing else matches, try fallback routes. $router->any('*', 'handler'); + $sKey = $method . ' /*'; + if ($this->staticRoutes && isset($this->staticRoutes[$sKey])) { + return [self::FOUND, $path, $this->staticRoutes[$sKey]]; + } + + if ($this->handleMethodNotAllowed) { + return $this->findAllowedMethods($path, $method); + } + + return [self::NOT_FOUND, $path, null]; + } + + /******************************************************************************* + * helper methods + ******************************************************************************/ + + /** + * @param string $path + * @param string $method + * @param Route $route + */ + protected function cacheMatchedParamRoute(string $path, string $method, Route $route): void + { + $cacheKey = $method . ' ' . $path; + $cacheNumber = $this->tmpCacheNumber; + + // cache last $cacheNumber routes. + if ($cacheNumber > 0 && !isset($this->cacheRoutes[$cacheKey])) { + if ($this->getCacheCount() >= $cacheNumber) { + array_shift($this->cacheRoutes); + } + + $this->cacheRoutes[$cacheKey] = $route; + } + } + + /** + * @return array[] + */ + public function getCacheRoutes(): array + { + return $this->cacheRoutes; + } + + /** + * @return int + */ + public function getCacheCount(): int + { + return count($this->cacheRoutes); + } +} diff --git a/test/CachedRouterTest.php b/test/CachedRouterTest.php new file mode 100644 index 0000000..b26d992 --- /dev/null +++ b/test/CachedRouterTest.php @@ -0,0 +1,67 @@ + $cacheFile, + 'cacheEnable' => 1, + ]; + $callback = function (CachedRouter $router) { + $router->get('/path0', 'handler0'); + }; + + $router = createCachedRouter($callback, $config); + + $this->assertFalse($router->isCacheLoaded()); + $this->assertTrue($router->isCacheExists()); + + /** @var Route $route */ + [$sts, , $route] = $router->match('/path0'); + + $this->assertSame(CachedRouter::FOUND, $sts); + $this->assertSame('/path0', $route->getPath()); + + // create again, will load caches. + $router = createCachedRouter($callback, $config); + + $this->assertTrue($router->isCacheExists()); + $this->assertTrue($router->isCacheLoaded()); + + /** @var Route $route */ + [$sts, , $route] = $router->match('/path0'); + + $this->assertSame(CachedRouter::FOUND, $sts); + $this->assertSame('/path0', $route->getPath()); + + // if (file_exists($cacheFile)) { + // unlink($cacheFile); + // } + } +} diff --git a/examples/Controllers/Admin/UserController.php b/test/Controllers/Admin/UserController.php similarity index 57% rename from examples/Controllers/Admin/UserController.php rename to test/Controllers/Admin/UserController.php index b3f77fe..0a14df2 100644 --- a/examples/Controllers/Admin/UserController.php +++ b/test/Controllers/Admin/UserController.php @@ -1,4 +1,4 @@ -'; } - public function infoAction() + public function infoAction(): void { echo 'hello, this is ' . __METHOD__ . '
'; } diff --git a/examples/Controllers/DemoController.php b/test/Controllers/DemoController.php similarity index 63% rename from examples/Controllers/DemoController.php rename to test/Controllers/DemoController.php index 02f3e46..1d6a55d 100644 --- a/examples/Controllers/DemoController.php +++ b/test/Controllers/DemoController.php @@ -1,4 +1,4 @@ -'; } - public function testAction() + public function testAction(): void { echo 'hello, this is ' . __METHOD__ . '
'; } // you can access by '/demo/oneTwo' or '/demo/one-two' - public function oneTwoAction() + public function oneTwoAction(): void { echo 'hello, this is ' . __METHOD__ . '
'; } diff --git a/examples/Controllers/HomeController.php b/test/Controllers/HomeController.php similarity index 58% rename from examples/Controllers/HomeController.php rename to test/Controllers/HomeController.php index 414debc..62060fb 100644 --- a/examples/Controllers/HomeController.php +++ b/test/Controllers/HomeController.php @@ -1,4 +1,4 @@ -'; } - public function testAction() + public function testAction(): void { echo 'hello, this is ' . __METHOD__ . '
'; } - public function aboutAction() + public function aboutAction(): void { echo 'hello, this is about page'; } diff --git a/test/Controllers/RestController.php b/test/Controllers/RestController.php new file mode 100644 index 0000000..f7cc5a4 --- /dev/null +++ b/test/Controllers/RestController.php @@ -0,0 +1,46 @@ +handleMethodNotAllowed = true; + $router->get('/', $handler); + $router->get('/user/info[/{int}]', $handler); + $router->get('/my[/{name}[/{age}]]', $handler, [ + 'age' => '\d+' + ])->setOptions([ + 'defaults' => [ + 'name' => 'God', + 'age' => 25, + ] + ]); + + $d = new Dispatcher(); + + // add events + $d->on(Dispatcher::ON_NOT_FOUND, static function () { + return 'TEST: page not found'; + }); + $d->on(Dispatcher::ON_METHOD_NOT_ALLOWED, static function ($path, $m, $ms) { + return sprintf('TEST: %s %s is not allowed, allowed methods: %s', $m, $path, implode(',', $ms)); + }); + $d->setRouter($router); + + // not found + $ret = $d->dispatchUri('/not-exist', 'get'); + $this->assertSame('TEST: page not found', $ret); + + // not allowed + $ret = $d->dispatchUri('/', 'post'); + $this->assertSame('TEST: POST / is not allowed, allowed methods: GET', $ret); + + $ret = $d->dispatchUri('/', 'get'); + $this->assertStringStartsWith('hello', $ret); + $this->assertStringEndsWith('[]', $ret); + + $ret = $d->dispatchUri('/user/info', 'get'); + $this->assertStringStartsWith('hello', $ret); + $this->assertStringEndsWith('[]', $ret); + + $ret = $d->dispatchUri('/user/info/45', 'get'); + $this->assertStringStartsWith('hello', $ret); + $this->assertStringEndsWith('"45"}', $ret); + + $ret = $d->dispatchUri('/my', 'get'); + $this->assertStringStartsWith('hello', $ret); + $this->assertStringEndsWith('25}', $ret); + $this->assertStringEndsWith('{"name":"God","age":25}', $ret); + + $ret = $d->dispatchUri('/my/tom', 'get'); + $this->assertStringStartsWith('hello', $ret); + $this->assertStringEndsWith('25}', $ret); + $this->assertStringEndsWith('{"name":"tom","age":25}', $ret); + + $ret = $d->dispatchUri('/my/tom/45', 'get'); + $this->assertStringStartsWith('hello', $ret); + $this->assertStringEndsWith('"45"}', $ret); + $this->assertStringEndsWith('{"name":"tom","age":"45"}', $ret); + } +} diff --git a/test/Dispatcher/SimpleDispatcherTest.php b/test/Dispatcher/SimpleDispatcherTest.php new file mode 100644 index 0000000..1d8c96b --- /dev/null +++ b/test/Dispatcher/SimpleDispatcherTest.php @@ -0,0 +1,71 @@ +get('/', static function () { + self::$buffer = 'hello'; + }); + + $d = new SimpleDispatcher([], $router); + + $bakServer = $_SERVER; + + $_SERVER['REQUEST_URI'] = '/'; + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $d->dispatchUri(); + + $this->assertSame('hello', self::$buffer); + + $_SERVER = $bakServer; + } + + /** + * @throws Throwable + */ + public function testDispatchUri2(): void + { + $router = new Router(); + $router->get('/', static function () { + self::$buffer = 'hello'; + }); + + $d = SimpleDispatcher::create([], $router); + + $bakServer = $_SERVER; + + $_SERVER['REQUEST_URI'] = '/'; + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $d->dispatchUri(); + + $this->assertSame('hello', self::$buffer); + + $_SERVER = $bakServer; + } +} diff --git a/test/PreMatchRouterTest.php b/test/PreMatchRouterTest.php new file mode 100644 index 0000000..a2daadb --- /dev/null +++ b/test/PreMatchRouterTest.php @@ -0,0 +1,60 @@ +get('/', 'handler0'); + $r->get('/test', 'handler1'); + $r->get('/test1[/optional]', 'handler'); + $r->get('/{name}', 'handler2'); + $r->get('/hi/{name}', 'handler3', [ + 'params' => [ + 'name' => '\w+', + ] + ]); + $r->post('/hi/{name}', 'handler4'); + $r->put('/hi/{name}', 'handler5'); + + return $r; + } + + public function testRouteCacheExists(): void + { + $p = '/test'; + $m = 'GET'; + $router = $this->createRouter($p, $m); + + $this->assertInstanceOf(Route::class, $router->getPreFounded()); + + $ret = $router->match($p); + $this->assertCount(3, $ret); + + /** @var Route $route */ + [$status, $path, $route] = $ret; + + $this->assertSame(RouterInterface::FOUND, $status); + $this->assertSame($p, $path); + $this->assertSame('handler1', $route->getHandler()); + } +} diff --git a/test/RouteHelperTest.php b/test/RouteHelperTest.php new file mode 100644 index 0000000..fb02c43 --- /dev/null +++ b/test/RouteHelperTest.php @@ -0,0 +1,31 @@ +assertTrue($ret); + + $ret = RouteHelper::isStaticRoute('/hi/{name}'); + $this->assertFalse($ret); + + $ret = RouteHelper::isStaticRoute('/hi/[tom]'); + $this->assertFalse($ret); + } +} diff --git a/test/RouteTest.php b/test/RouteTest.php new file mode 100644 index 0000000..40dfcd9 --- /dev/null +++ b/test/RouteTest.php @@ -0,0 +1,129 @@ + '/kfhxlkeugug/{name}', + 'method' => 'GET', + 'handler' => 'handler_func', + 'bindVars' => [], + 'params' => [], + 'pathVars' => ['name',], + 'pathRegex' => '#^/kfhxlkeugug/([^/]+)$#', + 'pathStart' => '/kfhxlkeugug/', + 'chains' => [], + 'options' => [], + ]); + $route->addOption('n1', 'v1'); + + $this->assertEquals('GET', $route->getMethod()); + $this->assertEquals(['name'], $route->getPathVars()); + $this->assertEquals('/kfhxlkeugug/', $route->getPathStart()); + $this->assertEquals('#^/kfhxlkeugug/([^/]+)$#', $route->getPathRegex()); + $this->assertArrayHasKey('name', $route->toArray()); + $this->assertArrayHasKey('n1', $route->getOptions()); + } + + public function testParseParam(): void + { + // 抽象方法才需要配置 + // $stub->expects($this->any()) + // ->method('parseParamRoute') + // ->will($this->returnValue('foo')); + + $path = '/im/{name}/{age}'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(['age' => '\d+']); + $this->assertCount(2, $route->getPathVars()); + $this->assertEquals('im', $first);// first node + $this->assertEquals(['name', 'age'], $route->getPathVars()); + $this->assertEquals('/im/', $route->getPathStart()); + $this->assertEquals('#^/im/([^/]+)/(\d+)$#', $route->getPathRegex()); + + $path = '/path/to/{name}'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(); + $this->assertEquals('path', $first); + $this->assertEquals('/path/to/', $route->getPathStart()); + + $path = '/path/to/some/{name}'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(); + $this->assertEquals('path', $first); + $this->assertEquals('/path/to/some/', $route->getPathStart()); + + $path = '/hi/{name}'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(); + $this->assertEquals('hi', $first); + $this->assertEquals(['name'], $route->getPathVars()); + $this->assertEquals('/hi/', $route->getPathStart()); + $this->assertEquals('#^/hi/([^/]+)$#', $route->getPathRegex()); + + $path = '/hi[/{name}]'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(); + $this->assertEquals('', $first); + $this->assertEquals(['name'], $route->getPathVars()); + $this->assertEquals('', $route->getPathStart()); + $this->assertEquals('#^/hi(?:/([^/]+))?$#', $route->getPathRegex()); + + $path = '/hi[/tom]'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(); + $this->assertEquals('', $first); + $this->assertEquals([], $route->getPathVars()); + $this->assertEquals('', $route->getPathStart()); + $this->assertEquals('#^/hi(?:/tom)?$#', $route->getPathRegex()); + + $path = '/hi/[tom]'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(); + $this->assertEquals('hi', $first); + $this->assertEquals('/hi/', $route->getPathStart()); + $this->assertEquals('#^/hi/(?:tom)?$#', $route->getPathRegex()); + + $path = '/{category}'; + $route = Route::create('GET', $path, 'my_handler'); + $first = $route->parseParam(); + $this->assertEquals('', $first); + $this->assertEquals('', $route->getPathStart()); + $this->assertEquals('#^/([^/]+)$#', $route->getPathRegex()); + + $path = '/blog-{category}'; + $route = Route::create('GET', $path, 'my_handler', ['category' => '\w+']); + $first = $route->parseParam(); + $this->assertEquals('', $first); + $this->assertEquals('', $route->getPathStart()); + $this->assertEquals('#^/blog-(\w+)$#', $route->getPathRegex()); + + $path = '/blog/user-{id}'; + $route = Route::create('GET', $path, 'my_handler', ['id' => '\w+']); + $first = $route->parseParam(); + $this->assertEquals('blog', $first); + $this->assertEquals('/blog/user-', $route->getPathStart()); + $this->assertEquals('#^/blog/user-(\w+)$#', $route->getPathRegex()); + + $route = Route::create('GET', '/some/[to/]path', 'my_handler'); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Optional segments can only occur at the end of a route'); + $route->parseParam(); + } + + public function testMiddleware(): void + { + $route = Route::createFromArray(['path' => '/middle', 'handler' => 'handler0']); + $route->middleware('func1', 'func2'); + $route->push('func3'); + + $this->assertEquals(['func1', 'func2', 'func3'], $route->getChains()); + } +} diff --git a/test/RouterManagerTest.php b/test/RouterManagerTest.php new file mode 100644 index 0000000..bfc00e8 --- /dev/null +++ b/test/RouterManagerTest.php @@ -0,0 +1,84 @@ + 'main-site', + 'main-site' => [ + 'driver' => 'default', + 'conditions' => [ + 'domains' => ['abc.com', 'www.abc.com'] + ], + ], + 'doc-site' => [ + 'driver' => 'cached', + 'options' => [ + + ], + 'conditions' => [ + 'domains' => 'doc.abc.com' + ], + ], + 'blog-site' => [ + 'driver' => 'preMatch', + 'options' => [ + 'path' => '/test', + 'method' => 'GET', + ], + 'conditions' => [ + 'schemes' => 'http', + 'domains' => 'blog.abc.com' + ], + ], + ]; + + $this->manager = new RouterManager($configs); + } + + public function testGet(): void + { + $router = $this->manager->get([ + 'scheme' => 'http', + 'domain' => 'blog.abc.com', + ]); + + $this->assertSame('blog-site', $router->getName()); + $this->assertInstanceOf(PreMatchRouter::class, $router); + } + + public function testGetByName(): void + { + $router = $this->manager->getByName('blog-site'); + + $this->assertSame('blog-site', $router->getName()); + } + + public function testGetDefault(): void + { + $router = $this->manager->getDefault(); + + $this->assertSame('default', $router->getName()); + } +} diff --git a/test/RouterTest.php b/test/RouterTest.php new file mode 100644 index 0000000..493e15e --- /dev/null +++ b/test/RouterTest.php @@ -0,0 +1,413 @@ +setName('my-router'); + + $this->assertSame('my-router', $router->getName()); + + $router->addGlobalParams([ + 'myArg' => '\w{5}' + ]); + $this->assertArrayHasKey('myArg', $router->getGlobalParams()); + + $router->setGlobalOptions(['opt1' => 'val1']); + $this->assertArrayHasKey('opt1', $router->getGlobalOptions()); + } + + public function testAddRoutes(): void + { + $r = new Router([]); + + $r->get('/', 'handler0'); + $r->get('/hi/{name}', 'handler3', [ + 'name' => '\w+', + ]); + + $r1 = $r->get('/my[/{name}[/{age}]]', 'handler2', [ + 'age' => '\d+' + ]); + + $this->assertTrue($r->count() > 1); + $this->assertNotEmpty($r->getRoutes()); + + $isGt8 = (int)Version::series() > 7; + if ($isGt8) { + $this->assertTrue(in_array('name', $r1->getPathVars(), true)); + $this->assertTrue(in_array('age', $r1->getPathVars(), true)); + $this->assertStringContainsString('GET /my[/{name}[/{age}]]', (string)$r1); + } else { + $this->assertContains('name', $r1->getPathVars()); + $this->assertContains('age', $r1->getPathVars()); + $this->assertContains('GET /my[/{name}[/{age}]]', (string)$r1); + } + + $this->assertArrayHasKey('age', $r1->getBindVars()); + + foreach (Router::METHODS_ARRAY as $method) { + $r->$method("/$method", "handle_$method"); + } + $string = (string)$r; + foreach (Router::METHODS_ARRAY as $method) { + $s = sprintf('%-7s %-25s --> %s', $method, "/$method", "handle_$method"); + if ($isGt8) { + $this->assertStringContainsString($s, $string); + } else { + $this->assertContains($s, $string); + } + } + + $r->add('ANY', '/any', 'handler_any'); + $string = $r->toString(); + foreach (Router::METHODS_ARRAY as $method) { + $s = sprintf('%-7s %-25s --> %s', $method, '/any', 'handler_any'); + if ($isGt8) { + $this->assertStringContainsString($s, $string); + } else { + $this->assertContains($s, $string); + } + } + + $this->expectExceptionMessage('The method and route handler is not allow empty.'); + $r->add('GET', '', ''); + + $this->expectException(InvalidArgumentException::class); + $r->add('invalid', '/path', '/handler'); + + try { + $r->add('invalid', '/path', '/handler'); + } catch (Throwable $e) { + if ($isGt8) { + $this->assertStringContainsString('The method [INVALID] is not supported', $e->getMessage()); + } else { + $this->assertContains('The method [INVALID] is not supported', $e->getMessage()); + } + } + } + + public function testAddRoute(): void + { + $router = createRouter(function () { + // + }); + + $r1 = Route::create('GET', '/path1', 'handler0'); + $r1->setName('r1'); + $router->addRoute($r1); + + $r2 = Route::create('GET', '/path2', 'handler2'); + $r2->namedTo('r2', $router, true); + + $r3 = $router->add('get', '/path3', 'handler3'); + $r3->namedTo('r3', $router); + + $r4 = $router->add('get', '/path4', 'handler4', [], ['name' => 'r4']); + $r5 = Route::create('get', '/path5', 'handler5', [], ['name' => 'r5']) + ->attachTo($router); + + $this->assertEmpty($router->getRoute('not-exist')); + $this->assertEquals($r1, $router->getRoute('r1')); + $this->assertEquals($r2, $router->getRoute('r2')); + $this->assertEquals($r4, $router->getRoute('r4')); + $this->assertEquals($r5, $router->getRoute('r5')); + + $ret = $router->getRoute('r3'); + $this->assertEquals($r3, $ret); + $this->assertEquals([ + 'path' => '/path3', + 'method' => 'GET', + 'handlerName' => 'handler3', + ], $ret->info()); + } + + public function testStaticRoute(): void + { + /** @var Router $router */ + $router = Router::create(); + $router->get('/', 'handler0'); + $router->get('/about', 'handler1'); + $router->post('/some/to/path', 'handler2'); + + /** @var Route $route */ + [$status, $path, $route] = $router->match('/'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/', $path); + $this->assertSame('handler0', $route->getHandler()); + + // match use HEAD + [$status, ,] = $router->match('/', 'HEAD'); + $this->assertSame(Router::FOUND, $status); + + [$status, $path, $route] = $router->match('about'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/about', $path); + $this->assertSame('handler1', $route->getHandler()); + + [$status, $path, $route] = $router->match('/some//to/path', 'post'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/some/to/path', $path); + $this->assertSame('handler2', $route->getHandler()); + + [$status, $path,] = $router->match('not-exist'); + $this->assertSame(Router::NOT_FOUND, $status); + $this->assertSame('/not-exist', $path); + + // add fallback route. + $router->any('/*', 'fb_handler'); + [$status, $path,] = $router->match('not-exist'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/not-exist', $path); + } + + public function testOptionalParamRoute(): void + { + /** @var Router $router */ + $router = Router::create(); + $router->get('/about[.html]', 'handler0'); + $router->get('/test1[/optional]', 'handler1'); + + /** @var Route $route */ + + // route: '/about' + [$status, , $route] = $router->match('/about'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('handler0', $route->getHandler()); + + // route: '/about.html' + [$status, , $route] = $router->match('/about.html'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('handler0', $route->getHandler()); + + // route: '/test1' + [$status, , $route] = $router->match('/test1'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('handler1', $route->getHandler()); + + // route: '/test1/optional' + [$status, , $route] = $router->match('/test1/optional'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('handler1', $route->getHandler()); + + // route: '/test1/other' + [$status, ,] = $router->match('/test1/other'); + $this->assertSame(Router::NOT_FOUND, $status); + } + + public function testParamRoute(): void + { + $router = Router::create(); + /** @var Route $route */ + $route = $router->get('/hi/{name}', 'handler3', [ + 'name' => '\w+', + ]); + + $this->assertEquals('#^/hi/(\w+)$#', $route->getPathRegex()); + + // int param + [$status, $path, $route] = $router->match('/hi/3456'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/hi/3456', $path); + $this->assertSame('/hi/{name}', $route->getPath()); + $this->assertSame('handler3', $route->getHandler()); + $this->assertSame('3456', $route->getParam('name')); + + // string param + [$status, $path, $route] = $router->match('/hi/tom'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/hi/tom', $path); + $this->assertSame('/hi/{name}', $route->getPath()); + $this->assertSame('handler3', $route->getHandler()); + $this->assertArrayHasKey('name', $route->getParams()); + $this->assertSame('tom', $route->getParam('name')); + + // invalid + [$status, ,] = $router->match('/hi/dont-match'); + $this->assertSame(Router::NOT_FOUND, $status); + } + + public function testComplexRoute(): void + { + $router = Router::create(); + // handleMethodNotAllowed + $router->handleMethodNotAllowed = true; + + /** @var Route $route */ + $route = $router->get('/my[/{name}[/{age}]]', 'handler2', [ + 'age' => '\d+' + ])->setOptions([ + 'defaults' => [ + 'name' => 'God', + 'age' => 25, + ] + ]); + + $this->assertSame('handler2', $route->getHandler()); + $this->assertContains('age', $route->getPathVars()); + $this->assertContains('name', $route->getPathVars()); + + // access '/my' + [$status, $path, $route] = $router->match('/my'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/my', $path); + $this->assertSame('handler2', $route->getHandler()); + $this->assertArrayHasKey('defaults', $route->getOptions()); + $this->assertArrayHasKey('age', $route->getParams()); + $this->assertArrayHasKey('name', $route->getParams()); + $this->assertSame('God', $route->getParam('name')); + $this->assertSame(25, $route->getParam('age')); + + // access '/my/tom' + [$status, $path, $route] = $router->match('/my/tom'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/my/tom', $path); + $this->assertSame('handler2', $route->getHandler()); + $this->assertSame('tom', $route->getParam('name')); + $this->assertSame(25, $route->getParam('age')); + + // access '/my/tom/45' + [$status, $path, $route] = $router->match('/my/tom/45'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/my/tom/45', $path); + $this->assertSame('handler2', $route->getHandler()); + $this->assertSame('tom', $route->getParam('name')); + $this->assertSame(45, (int)$route->getParam('age')); + + // use HEAD + $ret = $router->match('/my/tom/45', 'HEAD'); + $this->assertSame(Router::FOUND, $ret[0]); + + // not allowed + $ret = $router->match('/my/tom/45', 'POST'); + $this->assertSame(Router::METHOD_NOT_ALLOWED, $ret[0]); + $this->assertEquals(['GET'], $ret[2]); + + // not found + $ret = $router->match('/my/tom/not-match'); + $this->assertSame(Router::NOT_FOUND, $ret[0]); + } + + public function testMatchAutoRoute(): void + { + $router = Router::create([ + // enable autoRoute + // you can access '/demo' '/admin/user/info', Don't need to configure any route + 'autoRoute' => true, + 'namespaceUcFirst' => true, + 'controllerNamespace' => 'Inhere\RouteTest\Controllers', + 'controllerSuffix' => 'Controller', + ]); + + /** @var Route $route */ + + [$status, $path, $route] = $router->match('///demo'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/demo', $path); + $this->assertSame(DemoController::class, $route->getHandler()); + + [$status, $path, $route] = $router->match('/admin/user/info'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/admin/user/info', $path); + $this->assertSame('Inhere\RouteTest\Controllers\Admin\UserController@info', $route->getHandler()); + + [$status, $path,] = $router->match('/not-exist'); + $this->assertSame(Router::NOT_FOUND, $status); + $this->assertSame('/not-exist', $path); + } + + public function testNotFound(): void + { + $router = Router::create(); + $router->get('/hi/{name}', 'handler3', [ + 'name' => '\w+', + ]); + + [$status, $path,] = $router->match('/not-exist'); + $this->assertSame(Router::NOT_FOUND, $status); + $this->assertSame('/not-exist', $path); + + [$status, $path,] = $router->match('/hi'); + $this->assertSame(Router::NOT_FOUND, $status); + $this->assertSame('/hi', $path); + } + + public function testRequestMethods(): void + { + $router = Router::create([ + 'handleMethodNotAllowed' => true, + ]); + $router->get('/hi/{name}', 'handler3', [ + 'name' => '\w+', + ]); + $router->map(['POST', 'PUT'], '/hi/{name}', 'handler4'); + + /** @var Route $route */ + + // GET + [$status, , $route] = $router->match('/hi/tom', 'get'); + $this->assertSame(Router::FOUND, $status); + $this->assertArrayHasKey('name', $route->getParams()); + $this->assertSame('handler3', $route->getHandler()); + + // POST + [$status, , $route] = $router->match('/hi/tom', 'post'); + $this->assertSame(Router::FOUND, $status); + $this->assertArrayHasKey('name', $route->getParams()); + $this->assertSame('handler4', $route->getHandler()); + $this->assertEquals('tom', $route->getParam('name')); + + // PUT + [$status, , $route] = $router->match('/hi/john', 'put'); + $this->assertSame(Router::FOUND, $status); + $this->assertSame('handler4', $route->getHandler()); + $this->assertArrayHasKey('name', $route->getParams()); + $this->assertEquals('john', $route->getParam('name')); + + // DELETE + [$status, , $methods] = $router->match('/hi/tom', 'delete'); + $this->assertSame(Router::METHOD_NOT_ALLOWED, $status); + $this->assertCount(3, $methods); + $this->assertEquals(['GET', 'POST', 'PUT'], $methods); + } + + public function testMiddleware(): void + { + $router = Router::create(); + $router->use('func0', 'func1'); + + // global middleware + $this->assertSame(['func0', 'func1'], $router->getChains()); + + $router->group('/grp', function (Router $r) use (&$r1) { + $r1 = $r->get('/path', 'h0')->push('func2'); + }, ['func3', 'func4'], ['n1' => 'v1']); + + /** @var Route $route */ + [$status, , $route] = $router->match('/grp/path', 'get'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame($r1, $route); + $this->assertSame(['func3', 'func4', 'func2'], $route->getChains()); + $this->assertArrayHasKey('n1', $route->getOptions()); + } +} diff --git a/test/SRouterTest.php b/test/SRouterTest.php new file mode 100644 index 0000000..a0afd69 --- /dev/null +++ b/test/SRouterTest.php @@ -0,0 +1,71 @@ + '\w+', + ]); + } + + public function testBasic(): void + { + $router = Router::create(['name' => 'myRouter']); + SRouter::setRouter($router); + + $r = SRouter::getRouter(); + $this->assertSame($router->getName(), $r->getName()); + + $this->expectExceptionMessage('call invalid method: notExist'); + SRouter::notExist(); + } + + public function testStaticRoute(): void + { + $this->registerRoutes(); + + /** @var Route $route */ + [$status, $path, $route] = SRouter::match('/'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/', $path); + $this->assertSame('handler0', $route->getHandler()); + } + + public function testParamRoute(): void + { + $this->registerRoutes(); + + /** @var Route $route */ + + // route: /{name} + [$status, $path, $route] = SRouter::match('/tom'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/tom', $path); + $this->assertSame('handler2', $route->getHandler()); + + // route: /hi/{name} + [$status, $path, $route] = SRouter::match('/hi/tom'); + + $this->assertSame(Router::FOUND, $status); + $this->assertSame('/hi/tom', $path); + $this->assertSame('/hi/{name}', $route->getPath()); + $this->assertSame('handler3', $route->getHandler()); + } +} diff --git a/test/ServerRouterTest.php b/test/ServerRouterTest.php new file mode 100644 index 0000000..7b22c06 --- /dev/null +++ b/test/ServerRouterTest.php @@ -0,0 +1,74 @@ + 10, + ]); + $router->get('/path', 'handler0'); + $router->get('/test1[/optional]', 'handler'); + $router->get('/{name}', 'handler2'); + $router->get('/hi/{name}', 'handler3', [ + 'name' => '\w+', + ]); + $router->post('/hi/{name}', 'handler4'); + $router->put('/hi/{name}', 'handler5'); + + $this->assertTrue(4 < $router->count()); + + /** @var Route $route */ + [$status, $path, $route] = $router->match('/hi/tom'); + $this->assertSame(ServerRouter::FOUND, $status); + $this->assertSame('/hi/tom', $path); + $this->assertSame('handler3', $route->getHandler()); + + $this->assertEquals(1, $router->getCacheCount()); + + $cachedRoutes = $router->getCacheRoutes(); + $this->assertCount(1, $cachedRoutes); + + $cached = array_shift($cachedRoutes); + $this->assertEquals($route, $cached); + + // repeat request + /** @var Route $route */ + [$status, $path, $route] = $router->match('/hi/tom'); + $this->assertSame(ServerRouter::FOUND, $status); + $this->assertSame('/hi/tom', $path); + $this->assertSame('handler3', $route->getHandler()); + + // match use HEAD + [$status, ,] = $router->match('/path', 'HEAD'); + $this->assertSame(ServerRouter::FOUND, $status); + + // match not exist + [$status, $path,] = $router->match('/not/exist'); + $this->assertSame(ServerRouter::NOT_FOUND, $status); + $this->assertSame('/not/exist', $path); + + // add fallback route. + $router->any('/*', 'fb_handler'); + [$status, $path,] = $router->match('/not/exist'); + $this->assertSame(ServerRouter::FOUND, $status); + $this->assertSame('/not/exist', $path); + } +} diff --git a/test/boot.php b/test/boot.php new file mode 100644 index 0000000..e199d26 --- /dev/null +++ b/test/boot.php @@ -0,0 +1,115 @@ + $libDir . '/test/', + 'Inhere\Route\\' => $libDir . '/src/', + ]; + + spl_autoload_register(function ($class) use ($npMap) { + foreach ($npMap as $np => $dir) { + $file = $dir . str_replace('\\', '/', substr($class, strlen($np))) . '.php'; + + if (file_exists($file)) { + include $file; + } + } + }); +} + +// generates a random request url +function random_request_url(http://github.com/$chance%20=%205) +{ + $characters = 'abcdefghijklmnopqrstuvwxyz'; + $charactersLength = strlen($characters); + $randomString = '/'; + $prefixes = ['api', 'v2', 'user', 'goods']; + $rand = random_int(5, 20); + + $hasPrefix = false; + if (in_array($rand, [6, 12, 15, 18], true)) { + $hasPrefix = true; + $randomString .= $prefixes[array_rand($prefixes, 1)] . '/'; + } + + // create random path of 5-20 characters + for ($i = 0; $i < $rand; $i++) { + $randomString .= $characters[random_int(0, $charactersLength - 1)]; + + if (!$hasPrefix && random_int(1, 8) === 1) { + $randomString .= '/'; + } + } + + $v = random_int(1, 10); + + // add dynamic route with 50% chance + if ($v <= $chance) { + $randomString = rtrim($randomString, '/') . '/{name}'; + } + + return $randomString; +} + +// generate a random request method +function random_request_method() +{ + static $methods = ['GET', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE']; + $random_key = array_rand($methods); + return $methods[$random_key]; +} + +function pretty_echo($msg, $style = 'green', $nl = false) +{ + static $styles = [ + 'yellow' => '1;33', + 'magenta' => '1;35', + 'white' => '1;37', + 'black' => '0;30', + 'red' => '0;31', + 'green' => '0;32', + 'brown' => '0;33', + 'blue' => '0;34', + 'cyan' => '0;36', + + 'light_red' => '1;31', + 'light_blue' => '1;34', + 'light_gray' => '37', + 'light_green' => '1;32', + 'light_cyan' => '1;36', + ]; + + if (isset($styles[$style]) && false === strpos(PHP_OS, 'WIN')) { + return sprintf("\033[%sm%s\033[0m" . ($nl ? PHP_EOL : ''), $styles[$style], $msg); + } + + return $msg . ($nl ? PHP_EOL : ''); +} + +function pretty_match_result($ret) +{ + $str = json_encode($ret, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + + return str_replace('\\', '', $str); +} diff --git a/tests/AbstractRouterTest.php b/tests/AbstractRouterTest.php deleted file mode 100644 index c7d8112..0000000 --- a/tests/AbstractRouterTest.php +++ /dev/null @@ -1,21 +0,0 @@ -assertEquals($ret, 'GET'); - - $this->expectException(\InvalidArgumentException::class); - - AbstractRouter::validateArguments(null, null); - } -} diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php deleted file mode 100644 index 0c783b6..0000000 --- a/tests/DispatcherTest.php +++ /dev/null @@ -1,16 +0,0 @@ -assertTrue(1 == 1); - } -} diff --git a/tests/ORouterTest.php b/tests/ORouterTest.php deleted file mode 100644 index d99f72d..0000000 --- a/tests/ORouterTest.php +++ /dev/null @@ -1,82 +0,0 @@ -get('/', 'handler0'); - $r->get('/test', 'handler1'); - $r->get('/{name}', 'handler2'); - $r->get('/hi/{name}', 'handler3', [ - 'params' => [ - 'name' => '\w+', - ] - ]); - - return $r; - } - - public function testAddRoutes() - { - $router = $this->createRouter(); - - $this->assertSame(4, $router->count()); - $this->assertCount(2, $router->getStaticRoutes()); - $this->assertCount(1, $router->getRegularRoutes()); - $this->assertCount(1, $router->getVagueRoutes()); - } - - public function testStaticRoute() - { - $router = $this->createRouter(); - - // 1 - $ret = $router->match('/', 'GET'); - - $this->assertCount(3, $ret); - - list($status, $path, $route) = $ret; - - $this->assertSame(ORouter::FOUND, $status); - $this->assertSame('/', $path); - $this->assertSame('handler0', $route['handler']); - - } - - public function testParamRoute() - { - $router = $this->createRouter(); - - // route: /{name} - $ret = $router->match('/tom', 'GET'); - - $this->assertCount(3, $ret); - - list($status, $path, $route) = $ret; - - $this->assertSame(ORouter::FOUND, $status); - $this->assertSame('/tom', $path); - $this->assertSame('/{name}', $route['original']); - $this->assertSame('handler2', $route['handler']); - - // route: /hi/{name} - $ret = $router->match('/hi/tom', 'GET'); - - $this->assertCount(3, $ret); - - list($status, $path, $route) = $ret; - - $this->assertSame(ORouter::FOUND, $status); - $this->assertSame('/hi/tom', $path); - $this->assertSame('/hi/{name}', $route['original']); - $this->assertSame('handler3', $route['handler']); - } -} diff --git a/tests/SRouterTest.php b/tests/SRouterTest.php deleted file mode 100644 index 5694eff..0000000 --- a/tests/SRouterTest.php +++ /dev/null @@ -1,78 +0,0 @@ - [ - 'name' => '\w+', - ] - ]); - } - - public function testAddRoutes() - { - $this->registerRoutes(); - - $this->assertSame(4, SRouter::count()); - $this->assertCount(2, SRouter::getStaticRoutes()); - $this->assertCount(1, SRouter::getRegularRoutes()); - $this->assertCount(1, SRouter::getVagueRoutes()); - } - - public function testStaticRoute() - { - $this->registerRoutes(); - - // 1 - $ret = SRouter::match('/', 'GET'); - - $this->assertCount(3, $ret); - - list($status, $path, $route) = $ret; - - $this->assertSame(SRouter::FOUND, $status); - $this->assertSame('/', $path); - $this->assertSame('handler0', $route['handler']); - } - - public function testParamRoute() - { - $this->registerRoutes(); - - // route: /{name} - $ret = SRouter::match('/tom', 'GET'); - - $this->assertCount(3, $ret); - - list($status, $path, $route) = $ret; - - $this->assertSame(SRouter::FOUND, $status); - $this->assertSame('/tom', $path); - $this->assertSame('handler2', $route['handler']); - - // route: /hi/{name} - $ret = SRouter::match('/hi/tom', 'GET'); - - $this->assertCount(3, $ret); - - list($status, $path, $route) = $ret; - - $this->assertSame(SRouter::FOUND, $status); - $this->assertSame('/hi/tom', $path); - $this->assertSame('/hi/{name}', $route['original']); - $this->assertSame('handler3', $route['handler']); - } -} diff --git a/tests/boot.php b/tests/boot.php deleted file mode 100644 index 55b67e7..0000000 --- a/tests/boot.php +++ /dev/null @@ -1,8 +0,0 @@ -