Passed
Push — 8.0 ( 88b01c...7e38fd )
by liu
02:26
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_module'        => 'index',
81
        // 默认控制器名
82
        'default_controller'    => 'Index',
83
        // 默认操作名
84
        'default_action'        => 'index',
85
        // 操作方法后缀
86
        'action_suffix'         => '',
87
        // 非路由变量是否使用普通参数方式(用于URL生成)
88
        'url_common_param'      => true,
89
    ];
90
91
    /**
92
     * 请求对象
93
     * @var Request
94
     */
95
    protected $request;
96
97
    /**
98
     * @var RuleName
99
     */
100
    protected $ruleName;
101
102
    /**
103
     * 当前HOST
104
     * @var string
105
     */
106
    protected $host;
107
108
    /**
109
     * 当前分组对象
110
     * @var RuleGroup
111
     */
112
    protected $group;
113
114
    /**
115
     * 域名对象
116
     * @var Domain[]
117
     */
118
    protected $domains = [];
119
120
    /**
121
     * 跨域路由规则
122
     * @var RuleGroup
123
     */
124
    protected $cross;
125
126
    /**
127
     * 路由是否延迟解析
128
     * @var bool
129
     */
130
    protected $lazy = false;
131
132
    /**
133
     * (分组)路由规则是否合并解析
134
     * @var bool
135
     */
136
    protected $mergeRuleRegex = false;
137
138
    /**
139
     * 是否去除URL最后的斜线
140
     * @var bool
141
     */
142
    protected $removeSlash = false;
143
144 27
    public function __construct(protected App $app)
145
    {
146 27
        $this->ruleName = new RuleName();
147 27
        $this->setDefaultDomain();
148
149 27
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
150
            // 读取路由映射文件
151
            $this->import(include $this->app->getRuntimePath() . 'route.php');
152
        }
153
154 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

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

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

604
            return Response::create($template, 'view')->/** @scrutinizer ignore-call */ assign($vars);
Loading history...
605 3
        }, 'GET');
606
    }
607
608
    /**
609
     * 注册重定向路由
610
     * @access public
611
     * @param string $rule   路由规则
612
     * @param string $route  路由地址
613
     * @param int    $status 状态码
614
     * @return RuleItem
615
     */
616 3
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
617
    {
618 3
        return $this->rule($rule, function (Request $request) use ($status, $route) {
619 3
            $search  = $replace  = [];
620 3
            $matches = $request->rule()->getVars();
621
622 3
            foreach ($matches as $key => $value) {
623
                $search[]  = '<' . $key . '>';
624
                $replace[] = $value;
625
                $search[]  = '{' . $key . '}';
626
                $replace[] = $value;
627
                $search[]  = ':' . $key;
628
                $replace[] = $value;
629
            }
630
631 3
            $route = str_replace($search, $replace, $route);
632 3
            return Response::create($route, 'redirect')->code($status);
633 3
        }, '*');
634
    }
635
636
    /**
637
     * rest方法定义和修改
638
     * @access public
639
     * @param string|array $name     方法名称
640
     * @param array|bool   $resource 资源
641
     * @return $this
642
     */
643
    public function rest(string | array $name, array | bool $resource = [])
644
    {
645
        if (is_array($name)) {
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
646
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
647
        } else {
648
            $this->rest[$name] = $resource;
649
        }
650
651
        return $this;
652
    }
653
654
    /**
655
     * 获取rest方法定义的参数
656
     * @access public
657
     * @param string $name 方法名称
658
     * @return array|null
659
     */
660
    public function getRest(?string $name = null)
661
    {
662
        if (is_null($name)) {
663
            return $this->rest;
664
        }
665
666
        return $this->rest[$name] ?? null;
667
    }
668
669
    /**
670
     * 注册未匹配路由规则后的处理
671
     * @access public
672
     * @param string|Closure $route  路由地址
673
     * @param string         $method 请求类型
674
     * @return RuleItem
675
     */
676 27
    public function miss(string | Closure $route, string $method = '*'): RuleItem
677
    {
678 27
        return $this->group->miss($route, $method);
679
    }
680
681
    /**
682
     * 路由调度
683
     * @param Request $request
684
     * @param Closure|bool $withRoute
685
     * @return Response
686
     */
687 27
    public function dispatch(Request $request, Closure | bool $withRoute = true)
688
    {
689 27
        $this->request = $request;
690 27
        $this->host    = $this->request->host(true);
691 27
        $completeMatch = (bool) $this->config['route_complete_match'];
692 27
        $url           = str_replace($this->config['pathinfo_depr'], '|', $this->path());
693
694 27
        if ($withRoute) {
695 27
            if ($withRoute instanceof Closure) {
696
                $withRoute();
697
            }
698
            // 路由检测
699 27
            $dispatch = $this->check($url, $completeMatch);
700
        }
701
702 27
        if (empty($dispatch)) {
703
            // 默认URL调度
704 3
            $dispatch = $this->checkUrlDispatch($url);
705
        }
706
707 27
        $dispatch->init($this->app);
708
709 27
        return $this->app->middleware->pipeline('route')
710 27
            ->send($request)
711 27
            ->then(function () use ($dispatch) {
712 27
                return $dispatch->run();
713 27
            });
714
    }
715
716
    /**
717
     * 检测URL路由
718
     * @access public
719
     * @param  bool $completeMatch
720
     * @return Dispatch|false
721
     * @throws RouteNotFoundException
722
     */
723 27
    public function check(string $url, bool $completeMatch = false)
724
    {
725
        // 检测域名路由
726 27
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
727
728 27
        if (false === $result && !empty($this->cross)) {
729
            // 检测跨域路由
730
            $result = $this->cross->check($this->request, $url, $completeMatch);
731
        }
732
733 27
        if (false === $result && $this->config['url_route_must']) {
734
            // 开启强制路由
735
            throw new RouteNotFoundException();
736
        }
737
738 27
        return $result;
739
    }
740
741
    /**
742
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
743
     * @access protected
744
     * @return string
745
     */
746 27
    protected function path(): string
747
    {
748 27
        $suffix   = $this->config['url_html_suffix'];
749 27
        $pathinfo = $this->request->pathinfo();
750
751 27
        if (false === $suffix) {
752
            // 禁止伪静态访问
753
            $path = $pathinfo;
754 27
        } elseif ($suffix) {
755
            // 去除正常的URL后缀
756 27
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
757
        } else {
758
            // 允许任何后缀访问
759
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
760
        }
761
762 27
        return $path;
763
    }
764
765
    /**
766
     * 自动多模块URL路由 如使用多模块在路由定义文件最后定义
767
     * @access public
768
     * @param  string $rule    路由规则
769
     * @param  mixed  $route   路由地址
770
     * @param  bool   $middleware  自动注册中间件
771
     * @return RuleItem
772
     */
773
    public function auto(string $rule = '[:module]/[:controller]/[:action]', $route = ':module/:controller/:action', bool $middleware = false): RuleItem
774
    {
775
        return $this->rule($rule, $route)
776
            ->name('__think_auto_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
            ])->autoMiddleware($middleware);
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