@@ -225,9 +225,26 @@ public function set(String $key, String $value, int $ttl = 0): bool
225
225
return file_put_contents ($ filename , $ string , LOCK_EX ) !== false ;
226
226
}
227
227
228
+ private function fileGetContents ($ path )
229
+ {
230
+ $ f = fopen ($ path , 'r ' );
231
+ if ($ f === false ) {
232
+ return false ;
233
+ }
234
+ $ locked = flock ($ f , LOCK_SH );
235
+ if (!$ locked ) {
236
+ fclose ($ f );
237
+ return false ;
238
+ }
239
+ $ data = file_get_contents ($ path );
240
+ flock ($ f , LOCK_UN );
241
+ fclose ($ f );
242
+ return $ data ;
243
+ }
244
+
228
245
private function getString ($ filename ): String
229
246
{
230
- $ data = file_get_contents ($ filename );
247
+ $ data = $ this -> fileGetContents ($ filename );
231
248
if ($ data === false ) {
232
249
return '' ;
233
250
}
@@ -251,7 +268,7 @@ public function get(String $key): String
251
268
return $ string ;
252
269
}
253
270
254
- private function clean (String $ path , array $ segments , int $ len , bool $ all )/*: void*/
271
+ private function clean (String $ path , array $ segments , int $ len , bool $ all ) /*: void*/
255
272
{
256
273
$ entries = scandir ($ path );
257
274
foreach ($ entries as $ entry ) {
@@ -2653,21 +2670,44 @@ public function route(Request $request): Response;
2653
2670
class SimpleRouter implements Router
2654
2671
{
2655
2672
private $ responder ;
2673
+ private $ cache ;
2674
+ private $ ttl ;
2675
+ private $ registration ;
2656
2676
private $ routes ;
2657
2677
private $ midlewares ;
2658
2678
2659
- public function __construct (Responder $ responder )
2679
+ public function __construct (Responder $ responder, Cache $ cache , int $ ttl )
2660
2680
{
2661
2681
$ this ->responder = $ responder ;
2662
- $ this ->routes = new PathTree ();
2682
+ $ this ->cache = $ cache ;
2683
+ $ this ->ttl = $ ttl ;
2684
+ $ this ->registration = true ;
2685
+ $ this ->routes = $ this ->loadPathTree ();
2686
+ $ this ->routeHandlers = [];
2663
2687
$ this ->middlewares = array ();
2664
2688
}
2665
2689
2690
+ private function loadPathTree (): PathTree
2691
+ {
2692
+ $ data = $ this ->cache ->get ('PathTree ' );
2693
+ if ($ data != '' ) {
2694
+ $ tree = PathTree::fromJson (json_decode (gzuncompress ($ data )));
2695
+ $ this ->registration = false ;
2696
+ } else {
2697
+ $ tree = new PathTree ();
2698
+ }
2699
+ return $ tree ;
2700
+ }
2701
+
2666
2702
public function register (String $ method , String $ path , array $ handler )
2667
2703
{
2668
- $ parts = explode ('/ ' , trim ($ path , '/ ' ));
2669
- array_unshift ($ parts , $ method );
2670
- $ this ->routes ->put ($ parts , $ handler );
2704
+ $ routeNumber = count ($ this ->routeHandlers );
2705
+ $ this ->routeHandlers [$ routeNumber ] = $ handler ;
2706
+ if ($ this ->registration ) {
2707
+ $ parts = explode ('/ ' , trim ($ path , '/ ' ));
2708
+ array_unshift ($ parts , $ method );
2709
+ $ this ->routes ->put ($ parts , $ routeNumber );
2710
+ }
2671
2711
}
2672
2712
2673
2713
public function load (Middleware $ middleware ) /*: void*/
@@ -2683,50 +2723,34 @@ public function load(Middleware $middleware) /*: void*/
2683
2723
2684
2724
public function route (Request $ request ): Response
2685
2725
{
2726
+ if ($ this ->registration ) {
2727
+ $ data = gzcompress (json_encode ($ this ->routes , JSON_UNESCAPED_UNICODE ));
2728
+ $ this ->cache ->set ('PathTree ' , $ data , $ this ->ttl );
2729
+ }
2686
2730
$ obj = $ this ;
2687
2731
if (count ($ this ->middlewares ) > 0 ) {
2688
2732
$ obj = $ this ->middlewares [0 ];
2689
2733
}
2690
2734
return $ obj ->handle ($ request );
2691
2735
}
2692
2736
2693
- private function getHandlers (Request $ request ): array
2737
+ private function getRouteNumbers (Request $ request ): array
2694
2738
{
2695
2739
$ method = strtoupper ($ request ->getMethod ());
2696
2740
$ path = explode ('/ ' , trim ($ request ->getPath (0 ), '/ ' ));
2697
2741
array_unshift ($ path , $ method );
2698
-
2699
- return $ this ->matchPath ($ path , $ this ->routes );
2742
+ return $ this ->routes ->match ($ path );
2700
2743
}
2701
2744
2702
2745
public function handle (Request $ request ): Response
2703
2746
{
2704
- $ handlers = $ this ->getHandlers ($ request );
2705
- if (count ($ handlers ) == 0 ) {
2747
+ $ routeNumbers = $ this ->getRouteNumbers ($ request );
2748
+ if (count ($ routeNumbers ) == 0 ) {
2706
2749
return $ this ->responder ->error (ErrorCode::ROUTE_NOT_FOUND , $ request ->getPath ());
2707
2750
}
2708
- return call_user_func ($ handlers [ 0 ], $ request );
2751
+ return call_user_func ($ this -> routeHandlers [ $ routeNumbers [ 0 ] ], $ request );
2709
2752
}
2710
2753
2711
- private function matchPath (array $ path , PathTree $ tree ): array
2712
- {
2713
- $ values = array ();
2714
- while (count ($ path ) > 0 ) {
2715
- $ key = array_shift ($ path );
2716
- if ($ tree ->has ($ key )) {
2717
- $ tree = $ tree ->get ($ key );
2718
- } else if ($ tree ->has ('* ' )) {
2719
- $ tree = $ tree ->get ('* ' );
2720
- } else {
2721
- $ tree = null ;
2722
- break ;
2723
- }
2724
- }
2725
- if ($ tree !== null ) {
2726
- $ values = $ tree ->getValues ();
2727
- }
2728
- return $ values ;
2729
- }
2730
2754
}
2731
2755
2732
2756
// file: src/Tqdev/PhpCrudApi/Middleware/AuthorizationMiddleware.php
@@ -3734,45 +3758,80 @@ public function getResultSize(array $params): int
3734
3758
3735
3759
// file: src/Tqdev/PhpCrudApi/Record/PathTree.php
3736
3760
3737
- class PathTree
3761
+ class PathTree implements \JsonSerializable
3738
3762
{
3763
+ const WILDCARD = '* ' ;
3764
+
3765
+ private $ tree ;
3739
3766
3740
- private $ values = array ();
3767
+ public function __construct (object &$ tree = null )
3768
+ {
3769
+ if (!$ tree ) {
3770
+ $ tree = $ this ->newTree ();
3771
+ }
3772
+ $ this ->tree = &$ tree ;
3773
+ }
3774
+
3775
+ public function newTree ()
3776
+ {
3777
+ return (object ) ['values ' => [], 'branches ' => (object ) []];
3778
+ }
3741
3779
3742
- private $ branches = array ();
3780
+ public function getKeys (): array
3781
+ {
3782
+ $ branches = (array ) $ this ->tree ->branches ;
3783
+ return array_keys ($ branches );
3784
+ }
3743
3785
3744
3786
public function getValues (): array
3745
3787
{
3746
- return $ this ->values ;
3788
+ return $ this ->tree -> values ;
3747
3789
}
3748
3790
3749
- public function put ( array $ path , $ value )
3791
+ public function get ( String $ key ): PathTree
3750
3792
{
3751
- if (count ($ path ) == 0 ) {
3752
- $ this ->values [] = $ value ;
3753
- return ;
3793
+ if (!isset ($ this ->tree ->branches ->$ key )) {
3794
+ return null ;
3754
3795
}
3755
- $ key = array_shift ($ path );
3756
- if (!isset ($ this ->branches [$ key ])) {
3757
- $ this ->branches [$ key ] = new PathTree ();
3796
+ return new PathTree ($ this ->tree ->branches ->$ key );
3797
+ }
3798
+
3799
+ public function put (array $ path , $ value )
3800
+ {
3801
+ $ tree = &$ this ->tree ;
3802
+ foreach ($ path as $ key ) {
3803
+ if (!isset ($ tree ->branches ->$ key )) {
3804
+ $ tree ->branches ->$ key = $ this ->newTree ();
3805
+ }
3806
+ $ tree = &$ tree ->branches ->$ key ;
3758
3807
}
3759
- $ tree = $ this ->branches [$ key ];
3760
- $ tree ->put ($ path , $ value );
3808
+ $ tree ->values [] = $ value ;
3761
3809
}
3762
3810
3763
- public function getKeys ( ): array
3811
+ public function match ( array $ path ): array
3764
3812
{
3765
- return array_keys ($ this ->branches );
3813
+ $ star = self ::WILDCARD ;
3814
+ $ tree = &$ this ->tree ;
3815
+ foreach ($ path as $ key ) {
3816
+ if (isset ($ tree ->branches ->$ key )) {
3817
+ $ tree = &$ tree ->branches ->$ key ;
3818
+ } else if (isset ($ tree ->branches ->$ star )) {
3819
+ $ tree = &$ tree ->branches ->$ star ;
3820
+ } else {
3821
+ return [];
3822
+ }
3823
+ }
3824
+ return $ tree ->values ;
3766
3825
}
3767
3826
3768
- public function has ( $ key ): bool
3827
+ public static function fromJson ( /* object */ $ tree ): PathTree
3769
3828
{
3770
- return isset ( $ this -> branches [ $ key ] );
3829
+ return new PathTree ( $ tree );
3771
3830
}
3772
3831
3773
- public function get ( $ key ): PathTree
3832
+ public function jsonSerialize ()
3774
3833
{
3775
- return $ this ->branches [ $ key ] ;
3834
+ return $ this ->tree ;
3776
3835
}
3777
3836
}
3778
3837
@@ -4184,7 +4243,7 @@ public function __construct(Config $config)
4184
4243
$ reflection = new ReflectionService ($ db , $ cache , $ config ->getCacheTime ());
4185
4244
$ definition = new DefinitionService ($ db , $ reflection );
4186
4245
$ responder = new Responder ();
4187
- $ router = new SimpleRouter ($ responder );
4246
+ $ router = new SimpleRouter ($ responder, $ cache , $ config -> getCacheTime () );
4188
4247
foreach ($ config ->getMiddlewares () as $ middleware => $ properties ) {
4189
4248
switch ($ middleware ) {
4190
4249
case 'cors ' :
@@ -4470,14 +4529,16 @@ private function parseParams(String $query = null)
4470
4529
parse_str ($ query , $ this ->params );
4471
4530
}
4472
4531
4473
- private function parseHeaders (array $ headers = null )
4532
+ private function parseHeaders (array $ headers = null , bool $ parse = false )
4474
4533
{
4475
4534
if (!$ headers ) {
4476
4535
$ headers = array ();
4477
- foreach ($ _SERVER as $ name => $ value ) {
4478
- if (substr ($ name , 0 , 5 ) == 'HTTP_ ' ) {
4479
- $ key = str_replace (' ' , '- ' , ucwords (strtolower (str_replace ('_ ' , ' ' , substr ($ name , 5 )))));
4480
- $ headers [$ key ] = $ value ;
4536
+ if ($ parse ) {
4537
+ foreach ($ _SERVER as $ name => $ value ) {
4538
+ if (substr ($ name , 0 , 5 ) == 'HTTP_ ' ) {
4539
+ $ key = str_replace (' ' , '- ' , ucwords (strtolower (str_replace ('_ ' , ' ' , substr ($ name , 5 )))));
4540
+ $ headers [$ key ] = $ value ;
4541
+ }
4481
4542
}
4482
4543
}
4483
4544
}
@@ -4547,6 +4608,11 @@ public function getHeader(String $key): String
4547
4608
{
4548
4609
if (isset ($ this ->headers [$ key ])) {
4549
4610
return $ this ->headers [$ key ];
4611
+ } else {
4612
+ $ serverKey = 'HTTP_ ' . strtoupper (str_replace ('_ ' , '- ' , $ key ));
4613
+ if (isset ($ _SERVER [$ serverKey ])) {
4614
+ return $ _SERVER [$ serverKey ];
4615
+ }
4550
4616
}
4551
4617
return '' ;
4552
4618
}
0 commit comments