Passed
Push — 8.0 ( 521226...4eda4d )
by liu
04:47
created

Route::checkDomain()   F

Complexity

Conditions 15
Paths 388

Size

Total Lines 48
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 32.0416

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
eloc 25
c 1
b 0
f 0
nc 388
nop 0
dl 0
loc 48
ccs 15
cts 26
cp 0.5769
crap 32.0416
rs 2.7333

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2023 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use Closure;
16
use think\exception\RouteNotFoundException;
17
use think\route\Dispatch;
18
use think\route\dispatch\Callback;
19
use think\route\Domain;
20
use think\route\Resource;
21
use think\route\ResourceRegister;
22
use think\route\Rule;
23
use think\route\RuleGroup;
24
use think\route\RuleItem;
25
use think\route\RuleName;
26
use think\route\Url as UrlBuild;
27
28
/**
29
 * 路由管理类
30
 * @package think
31
 */
32
class Route
33
{
34
    /**
35
     * REST定义
36
     * @var array
37
     */
38
    protected $rest = [
39
        'index'  => ['get', '', 'index'],
40
        'create' => ['get', '/create', 'create'],
41
        'edit'   => ['get', '/<id>/edit', 'edit'],
42
        'read'   => ['get', '/<id>', 'read'],
43
        'save'   => ['post', '', 'save'],
44
        'update' => ['put', '/<id>', 'update'],
45
        'delete' => ['delete', '/<id>', 'delete'],
46
    ];
47
48
    /**
49
     * 配置参数
50
     * @var array
51
     */
52
    protected $config = [
53
        // pathinfo分隔符
54
        'pathinfo_depr'         => '/',
55
        // 是否开启路由延迟解析
56
        'url_lazy_route'        => false,
57
        // 是否强制使用路由
58
        'url_route_must'        => false,
59
        // 是否区分大小写
60
        'url_case_sensitive'    => false,
61
        // 合并路由规则
62
        'route_rule_merge'      => false,
63
        // 路由是否完全匹配
64
        'route_complete_match'  => false,
65
        // 去除斜杠
66
        'remove_slash'          => false,
67
        // 使用注解路由
68
        'route_annotation'      => false,
69
        // 默认的路由变量规则
70
        'default_route_pattern' => '[\w\.]+',
71
        // URL伪静态后缀
72
        'url_html_suffix'       => 'html',
73
        // 访问控制器层名称
74
        'controller_layer'      => 'controller',
75
        // 空控制器名
76
        'empty_controller'      => 'Error',
77
        // 是否使用控制器后缀
78
        'controller_suffix'     => false,
79
        // 默认路由 [路由规则, 路由地址]
80
        'default_route'         => [],
81
        // 默认模块名
82
        'default_module'        => 'index',
83
        // 默认控制器名
84
        'default_controller'    => 'Index',
85
        // 默认操作名
86
        'default_action'        => 'index',
87
        // 操作方法后缀
88
        'action_suffix'         => '',
89
        // 非路由变量是否使用普通参数方式(用于URL生成)
90
        'url_common_param'      => true,
91
    ];
92
93
    /**
94
     * 请求对象
95
     * @var Request
96
     */
97
    protected $request;
98
99
    /**
100
     * @var RuleName
101
     */
102
    protected $ruleName;
103
104
    /**
105
     * 当前HOST
106
     * @var string
107
     */
108
    protected $host;
109
110
    /**
111
     * 当前分组对象
112
     * @var RuleGroup
113
     */
114
    protected $group;
115
116
    /**
117
     * 域名对象
118
     * @var Domain[]
119
     */
120
    protected $domains = [];
121
122
    /**
123
     * 跨域路由规则
124
     * @var RuleGroup
125
     */
126
    protected $cross;
127
128
    /**
129
     * 路由是否延迟解析
130
     * @var bool
131
     */
132
    protected $lazy = false;
133
134
    /**
135
     * (分组)路由规则是否合并解析
136
     * @var bool
137
     */
138
    protected $mergeRuleRegex = false;
139
140
    /**
141
     * 是否去除URL最后的斜线
142
     * @var bool
143
     */
144
    protected $removeSlash = false;
145
146 27
    public function __construct(protected App $app)
147
    {
148 27
        $this->ruleName = new RuleName();
149 27
        $this->setDefaultDomain();
150
151 27
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
152
            // 读取路由映射文件
153
            $this->import(include $this->app->getRuntimePath() . 'route.php');
154
        }
155
156 27
        $this->config = array_merge($this->config, $this->app->config->get('route'));
0 ignored issues
show
Bug introduced by
It seems like $this->app->config->get('route') can also be of type null; however, parameter $arrays of array_merge() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

156
        $this->config = array_merge($this->config, /** @scrutinizer ignore-type */ $this->app->config->get('route'));
Loading history...
157
158 27
        $this->init();
159
    }
160
161 27
    protected function init()
162
    {
163 27
        if (!empty($this->config['middleware'])) {
164
            $this->app->middleware->import($this->config['middleware'], 'route');
165
        }
166
167 27
        $this->lazy($this->config['url_lazy_route']);
168 27
        $this->mergeRuleRegex = $this->config['route_rule_merge'];
169 27
        $this->removeSlash    = $this->config['remove_slash'];
170
171 27
        $this->group->removeSlash($this->removeSlash);
172
173
        // 注册全局MISS路由
174 27
        $this->miss(function () {
175 3
            return Response::create('', 'html', 204)->header(['Allow' => 'GET, POST, PUT, DELETE']);
176 27
        }, 'options');
177
    }
178
179 27
    public function config(?string $name = null)
180
    {
181 27
        if (is_null($name)) {
182
            return $this->config;
183
        }
184
185 27
        return $this->config[$name] ?? null;
186
    }
187
188
    /**
189
     * 设置路由域名及分组(包括资源路由)是否延迟解析
190
     * @access public
191
     * @param bool $lazy 路由是否延迟解析
192
     * @return $this
193
     */
194 27
    public function lazy(bool $lazy = true)
195
    {
196 27
        $this->lazy = $lazy;
197 27
        return $this;
198
    }
199
200
    /**
201
     * 设置路由域名及分组(包括资源路由)是否合并解析
202
     * @access public
203
     * @param bool $merge 路由是否合并解析
204
     * @return $this
205
     */
206
    public function mergeRuleRegex(bool $merge = true)
207
    {
208
        $this->mergeRuleRegex = $merge;
209
        $this->group->mergeRuleRegex($merge);
210
211
        return $this;
212
    }
213
214
    /**
215
     * 初始化默认域名
216
     * @access protected
217
     * @return void
218
     */
219 27
    protected function setDefaultDomain(): void
220
    {
221
        // 注册默认域名
222 27
        $domain = new Domain($this);
223
224 27
        $this->domains['-'] = $domain;
225
226
        // 默认分组
227 27
        $this->group = $domain;
228
    }
229
230
    /**
231
     * 设置当前分组
232
     * @access public
233
     * @param RuleGroup $group 域名
234
     * @return void
235
     */
236 27
    public function setGroup(RuleGroup $group): void
237
    {
238 27
        $this->group = $group;
239
    }
240
241
    /**
242
     * 获取指定标识的路由分组 不指定则获取当前分组
243
     * @access public
244
     * @param string $name 分组标识
245
     * @return RuleGroup
246
     */
247 27
    public function getGroup(?string $name = null)
248
    {
249 27
        return $name ? $this->ruleName->getGroup($name) : $this->group;
250
    }
251
252
    /**
253
     * 注册变量规则
254
     * @access public
255
     * @param array $pattern 变量规则
256
     * @return $this
257
     */
258
    public function pattern(array $pattern)
259
    {
260
        $this->group->pattern($pattern);
261
262
        return $this;
263
    }
264
265
    /**
266
     * 注册路由参数
267
     * @access public
268
     * @param array $option 参数
269
     * @return $this
270
     */
271
    public function option(array $option)
272
    {
273
        $this->group->option($option);
274
275
        return $this;
276
    }
277
278
    /**
279
     * 注册域名路由
280
     * @access public
281
     * @param string|array $name 子域名
282
     * @param mixed        $rule 路由规则
283
     * @return Domain
284
     */
285 3
    public function domain(string | array $name, $rule = null): Domain
286
    {
287
        // 支持多个域名使用相同路由规则
288 3
        $domainName = is_array($name) ? array_shift($name) : $name;
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
289
290 3
        if (!isset($this->domains[$domainName])) {
291 3
            $domain = (new Domain($this, $domainName, $rule, $this->lazy))
292 3
                ->removeSlash($this->removeSlash)
293 3
                ->mergeRuleRegex($this->mergeRuleRegex);
294
295 3
            $this->domains[$domainName] = $domain;
296
        } else {
297
            $domain = $this->domains[$domainName];
298
            $domain->parseGroupRule($rule);
299
        }
300
301 3
        if (is_array($name) && !empty($name)) {
302
            foreach ($name as $item) {
303
                $this->domains[$item] = $domainName;
304
            }
305
        }
306
307
        // 返回域名对象
308 3
        return $domain;
309
    }
310
311
    /**
312
     * 获取域名
313
     * @access public
314
     * @return array
315
     */
316
    public function getDomains(): array
317
    {
318
        return $this->domains;
319
    }
320
321
    /**
322
     * 获取域名路由的绑定信息
323
     * @access public
324
     * @param string $domain 子域名
325
     * @return string|null
326
     */
327
    public function getDomainBind(?string $domain = null)
328
    {
329
        if ($domain && isset($this->domains[$domain])) {
330
            $item = $this->domains[$domain];
331
            if (is_string($item)) {
0 ignored issues
show
introduced by
The condition is_string($item) is always false.
Loading history...
332
                $item = $this->domains[$item];
333
            }
334
            return $item->getBind();
335
        }
336
    }
337
338
    /**
339
     * 获取RuleName对象
340
     * @access public
341
     * @return RuleName
342
     */
343
    public function getRuleName(): RuleName
344
    {
345
        return $this->ruleName;
346
    }
347
348
    /**
349
     * 读取路由标识
350
     * @access public
351
     * @param string $name   路由标识
352
     * @param string $domain 域名
353
     * @param string $method 请求类型
354
     * @return array
355
     */
356
    public function getName(?string $name = null, ?string $domain = null, string $method = '*'): array
357
    {
358
        return $this->ruleName->getName($name, $domain, $method);
359
    }
360
361
    /**
362
     * 批量导入路由标识
363
     * @access public
364
     * @param array $name 路由标识
365
     * @return void
366
     */
367
    public function import(array $name): void
368
    {
369
        $this->ruleName->import($name);
370
    }
371
372
    /**
373
     * 注册路由标识
374
     * @access public
375
     * @param string   $name     路由标识
376
     * @param RuleItem $ruleItem 路由规则
377
     * @param bool     $first    是否优先
378
     * @return void
379
     */
380 9
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
381
    {
382 9
        $this->ruleName->setName($name, $ruleItem, $first);
383
    }
384
385
    /**
386
     * 保存路由规则
387
     * @access public
388
     * @param string   $rule     路由规则
389
     * @param RuleItem $ruleItem RuleItem对象
390
     * @return void
391
     */
392 27
    public function setRule(string $rule, ?RuleItem $ruleItem = null): void
393
    {
394 27
        $this->ruleName->setRule($rule, $ruleItem);
0 ignored issues
show
Bug introduced by
It seems like $ruleItem can also be of type null; however, parameter $ruleItem of think\route\RuleName::setRule() does only seem to accept think\route\RuleItem, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

394
        $this->ruleName->setRule($rule, /** @scrutinizer ignore-type */ $ruleItem);
Loading history...
395
    }
396
397
    /**
398
     * 读取路由
399
     * @access public
400
     * @param string $rule 路由规则
401
     * @return RuleItem[]
402
     */
403
    public function getRule(string $rule): array
404
    {
405
        return $this->ruleName->getRule($rule);
406
    }
407
408
    /**
409
     * 读取路由列表
410
     * @access public
411
     * @return array
412
     */
413
    public function getRuleList(): array
414
    {
415
        return $this->ruleName->getRuleList();
416
    }
417
418
    /**
419
     * 清空路由规则
420
     * @access public
421
     * @return void
422
     */
423
    public function clear(): void
424
    {
425
        $this->ruleName->clear();
426
427
        if ($this->group) {
428
            $this->group->clear();
429
        }
430
    }
431
432
    /**
433
     * 注册路由规则
434
     * @access public
435
     * @param string $rule   路由规则
436
     * @param mixed  $route  路由地址
437
     * @param string $method 请求类型
438
     * @return RuleItem
439
     */
440 24
    public function rule(string $rule, $route = null, string $method = '*'): RuleItem
441
    {
442 24
        return $this->group->addRule($rule, $route, $method);
443
    }
444
445
    /**
446
     * 设置路由规则全局有效
447
     * @access public
448
     * @param Rule   $rule   路由规则
449
     * @return $this
450
     */
451
    public function setCrossDomainRule(Rule $rule)
452
    {
453
        if (!isset($this->cross)) {
454
            $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
455
        }
456
457
        $this->cross->addRuleItem($rule);
458
459
        return $this;
460
    }
461
462
    /**
463
     * 注册路由分组
464
     * @access public
465
     * @param string|Closure $name  分组名称或者参数
466
     * @param mixed           $route 分组路由
467
     * @return RuleGroup
468
     */
469 3
    public function group(string | Closure $name, $route = null): RuleGroup
470
    {
471 3
        if ($name instanceof Closure) {
472 3
            $route = $name;
473 3
            $name  = '';
474
        }
475
476 3
        return (new RuleGroup($this, $this->group, $name, $route, $this->lazy))
477 3
            ->removeSlash($this->removeSlash)
478 3
            ->mergeRuleRegex($this->mergeRuleRegex);
479
    }
480
481
    /**
482
     * 注册路由
483
     * @access public
484
     * @param string $rule  路由规则
485
     * @param mixed  $route 路由地址
486
     * @return RuleItem
487
     */
488
    public function any(string $rule, $route): RuleItem
489
    {
490
        return $this->rule($rule, $route, '*');
491
    }
492
493
    /**
494
     * 注册GET路由
495
     * @access public
496
     * @param string $rule  路由规则
497
     * @param mixed  $route 路由地址
498
     * @return RuleItem
499
     */
500 18
    public function get(string $rule, $route): RuleItem
501
    {
502 18
        return $this->rule($rule, $route, 'GET');
503
    }
504
505
    /**
506
     * 注册POST路由
507
     * @access public
508
     * @param string $rule  路由规则
509
     * @param mixed  $route 路由地址
510
     * @return RuleItem
511
     */
512 3
    public function post(string $rule, $route): RuleItem
513
    {
514 3
        return $this->rule($rule, $route, 'POST');
515
    }
516
517
    /**
518
     * 注册PUT路由
519
     * @access public
520
     * @param string $rule  路由规则
521
     * @param mixed  $route 路由地址
522
     * @return RuleItem
523
     */
524 3
    public function put(string $rule, $route): RuleItem
525
    {
526 3
        return $this->rule($rule, $route, 'PUT');
527
    }
528
529
    /**
530
     * 注册DELETE路由
531
     * @access public
532
     * @param string $rule  路由规则
533
     * @param mixed  $route 路由地址
534
     * @return RuleItem
535
     */
536
    public function delete(string $rule, $route): RuleItem
537
    {
538
        return $this->rule($rule, $route, 'DELETE');
539
    }
540
541
    /**
542
     * 注册PATCH路由
543
     * @access public
544
     * @param string $rule  路由规则
545
     * @param mixed  $route 路由地址
546
     * @return RuleItem
547
     */
548
    public function patch(string $rule, $route): RuleItem
549
    {
550
        return $this->rule($rule, $route, 'PATCH');
551
    }
552
553
    /**
554
     * 注册HEAD路由
555
     * @access public
556
     * @param string $rule  路由规则
557
     * @param mixed  $route 路由地址
558
     * @return RuleItem
559
     */
560
    public function head(string $rule, $route): RuleItem
561
    {
562
        return $this->rule($rule, $route, 'HEAD');
563
    }
564
565
    /**
566
     * 注册OPTIONS路由
567
     * @access public
568
     * @param string $rule  路由规则
569
     * @param mixed  $route 路由地址
570
     * @return RuleItem
571
     */
572
    public function options(string $rule, $route): RuleItem
573
    {
574
        return $this->rule($rule, $route, 'OPTIONS');
575
    }
576
577
    /**
578
     * 注册资源路由
579
     * @access public
580
     * @param string $rule  路由规则
581
     * @param string $route 路由地址
582
     * @return Resource|ResourceRegister
583
     */
584
    public function resource(string $rule, string $route)
585
    {
586
        $resource = new Resource($this, $this->group, $rule, $route, $this->rest);
587
588
        if (!$this->lazy) {
589
            return new ResourceRegister($resource);
590
        }
591
592
        return $resource;
593
    }
594
595
    /**
596
     * 注册视图路由
597
     * @access public
598
     * @param string $rule     路由规则
599
     * @param string $template 路由模板地址
600
     * @param array  $vars     模板变量
601
     * @return RuleItem
602
     */
603 3
    public function view(string $rule, string $template = '', array $vars = []): RuleItem
604
    {
605 3
        return $this->rule($rule, function () use ($vars, $template) {
606 3
            return Response::create($template, 'view')->assign($vars);
0 ignored issues
show
Bug introduced by
The method assign() does not exist on think\Response. It seems like you code against a sub-type of think\Response such as think\response\View. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

606
            return Response::create($template, 'view')->/** @scrutinizer ignore-call */ assign($vars);
Loading history...
607 3
        }, 'GET');
608
    }
609
610
    /**
611
     * 注册重定向路由
612
     * @access public
613
     * @param string $rule   路由规则
614
     * @param string $route  路由地址
615
     * @param int    $status 状态码
616
     * @return RuleItem
617
     */
618 3
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
619
    {
620 3
        return $this->rule($rule, function (Request $request) use ($status, $route) {
621 3
            $search  = $replace  = [];
622 3
            $matches = $request->rule()->getVars();
623
624 3
            foreach ($matches as $key => $value) {
625
                $search[]  = '<' . $key . '>';
626
                $replace[] = $value;
627
                $search[]  = '{' . $key . '}';
628
                $replace[] = $value;
629
                $search[]  = ':' . $key;
630
                $replace[] = $value;
631
            }
632
633 3
            $route = str_replace($search, $replace, $route);
634 3
            return Response::create($route, 'redirect')->code($status);
635 3
        }, '*');
636
    }
637
638
    /**
639
     * rest方法定义和修改
640
     * @access public
641
     * @param string|array $name     方法名称
642
     * @param array|bool   $resource 资源
643
     * @return $this
644
     */
645
    public function rest(string | array $name, array | bool $resource = [])
646
    {
647
        if (is_array($name)) {
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
648
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
649
        } else {
650
            $this->rest[$name] = $resource;
651
        }
652
653
        return $this;
654
    }
655
656
    /**
657
     * 获取rest方法定义的参数
658
     * @access public
659
     * @param string $name 方法名称
660
     * @return array|null
661
     */
662
    public function getRest(?string $name = null)
663
    {
664
        if (is_null($name)) {
665
            return $this->rest;
666
        }
667
668
        return $this->rest[$name] ?? null;
669
    }
670
671
    /**
672
     * 注册未匹配路由规则后的处理
673
     * @access public
674
     * @param string|Closure $route  路由地址
675
     * @param string         $method 请求类型
676
     * @return RuleItem
677
     */
678 27
    public function miss(string | Closure $route, string $method = '*'): RuleItem
679
    {
680 27
        return $this->group->miss($route, $method);
681
    }
682
683
    /**
684
     * 路由调度
685
     * @param Request $request
686
     * @param Closure|bool $withRoute
687
     * @return Response
688
     */
689 27
    public function dispatch(Request $request, Closure | bool $withRoute = true)
690
    {
691 27
        $this->request = $request;
692 27
        $this->host    = $this->request->host(true);
693 27
        $completeMatch = (bool) $this->config['route_complete_match'];
694 27
        $url           = str_replace($this->config['pathinfo_depr'], '|', $this->path());
695
696 27
        if ($withRoute) {
697 27
            if ($withRoute instanceof Closure) {
698
                $withRoute();
699
            }
700
            // 路由检测
701 27
            $dispatch = $this->check($url, $completeMatch);
702
        }
703
704 27
        if (empty($dispatch)) {
705
            // 默认URL调度
706 3
            $dispatch = $this->checkUrlDispatch($url);
707
        }
708
709 27
        $dispatch->init($this->app);
710
711 27
        return $this->app->middleware->pipeline('route')
712 27
            ->send($request)
713 27
            ->then(function () use ($dispatch) {
714 27
                return $dispatch->run();
715 27
            });
716
    }
717
718
    /**
719
     * 检测URL路由
720
     * @access public
721
     * @param  bool $completeMatch
722
     * @return Dispatch|false
723
     * @throws RouteNotFoundException
724
     */
725 27
    public function check(string $url, bool $completeMatch = false)
726
    {
727
        // 检测域名路由
728 27
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
729
730 27
        if (false === $result && !empty($this->cross)) {
731
            // 检测跨域路由
732
            $result = $this->cross->check($this->request, $url, $completeMatch);
733
        }
734
735 27
        if (false === $result && $this->config['url_route_must']) {
736
            // 开启强制路由
737
            throw new RouteNotFoundException();
738
        }
739
740 27
        return $result;
741
    }
742
743
    /**
744
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
745
     * @access protected
746
     * @return string
747
     */
748 27
    protected function path(): string
749
    {
750 27
        $suffix   = $this->config['url_html_suffix'];
751 27
        $pathinfo = $this->request->pathinfo();
752
753 27
        if (false === $suffix) {
754
            // 禁止伪静态访问
755
            $path = $pathinfo;
756 27
        } elseif ($suffix) {
757
            // 去除正常的URL后缀
758 27
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
759
        } else {
760
            // 允许任何后缀访问
761
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
762
        }
763
764 27
        return $path;
765
    }
766
767
    /**
768
     * 自动多模块URL路由 如使用多模块在路由定义文件最后定义
769
     * @access public
770
     * @param  string $rule    路由规则
771
     * @param  mixed  $route   路由地址
772
     * @return RuleItem
773
     */
774
    public function auto(string $rule = '[:module]/[:controller]/[:action]', $route = ':module/:controller/:action'): RuleItem
775
    {
776
        return $this->rule($rule, $route)
777
            ->pattern([
778
                'module'     => '[A-Za-z0-9\.\_]+',
779
                'controller' => '[A-Za-z0-9\.\_]+',
780
                'action'     => '[A-Za-z0-9\_]+',
781
            ])->default([
782
                'module'     => $this->config['default_module'],
783
                'controller' => $this->config['default_controller'],
784
                'action'     => $this->config['default_action'],
785
            ]);
786
    }
787
788
    /**
789
     * 检测默认URL解析路由
790
     * @access public
791
     * @param  string   $url URL
792
     * @return Dispatch
793
     */
794 3
    protected function checkUrlDispatch(string $url): Dispatch
795
    {
796 3
        if ($this->request->method() == 'OPTIONS') {
797
            // 自动响应options请求
798
            return new Callback($this->request, $this->group, function () {
799
                return Response::create('', 'html', 204)->header(['Allow' => 'GET, POST, PUT, DELETE']);
800
            });
801
        }
802
803 3
        return $this->group->auto()->checkBind($this->request, $url);
804
    }
805
806
    /**
807
     * 检测域名的路由规则
808
     * @access protected
809
     * @return Domain
810
     */
811 27
    protected function checkDomain(): Domain
812
    {
813 27
        $item = false;
814
815 27
        if (count($this->domains) > 1) {
816
            // 获取当前子域名
817 3
            $subDomain = $this->request->subDomain();
818 3
            $domain    = $subDomain ? explode('.', $subDomain) : [];
819 3
            $domain2   = $domain ? array_pop($domain) : '';
820
821 3
            if ($domain) {
822
                // 存在三级域名
823
                $domain3 = array_pop($domain);
824
            }
825
826 3
            if (isset($this->domains[$this->host])) {
827
                // 子域名配置
828
                $item = $this->domains[$this->host];
829 3
            } elseif (isset($this->domains[$subDomain])) {
830 3
                $item = $this->domains[$subDomain];
831
            } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
832
                // 泛三级域名
833
                $item      = $this->domains['*.' . $domain2];
834
                $panDomain = $domain3;
835
            } elseif (isset($this->domains['*']) && !empty($domain2)) {
836
                // 泛二级域名
837
                if ('www' != $domain2) {
838
                    $item      = $this->domains['*'];
839
                    $panDomain = $domain2;
840
                }
841
            }
842
843 3
            if (isset($panDomain)) {
844
                // 保存当前泛域名
845
                $this->request->setPanDomain($panDomain);
846
            }
847
        }
848
849 27
        if (false === $item) {
850
            // 检测全局域名规则
851 24
            $item = $this->domains['-'];
852
        }
853
854 27
        if (is_string($item)) {
855
            $item = $this->domains[$item];
856
        }
857
858 27
        return $item;
859
    }
860
861
    /**
862
     * URL生成 支持路由反射
863
     * @access public
864
     * @param string $url  路由地址
865
     * @param array  $vars 参数 ['a'=>'val1', 'b'=>'val2']
866
     * @return UrlBuild
867
     */
868
    public function buildUrl(string $url = '', array $vars = []): UrlBuild
869
    {
870
        return $this->app->make(UrlBuild::class, [$this, $this->app, $url, $vars], true);
871
    }
872
873
    /**
874
     * 设置全局的路由分组参数
875
     * @access public
876
     * @param string $method 方法名
877
     * @param array  $args   调用参数
878
     * @return RuleGroup
879
     */
880
    public function __call($method, $args)
881
    {
882
        return call_user_func_array([$this->group, $method], $args);
883
    }
884
}
885