Passed
Push — master ( a42101...e1535a )
by Caen
03:50 queued 13s
created

Router::generateSearchIndex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 2
b 0
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Hyde\RealtimeCompiler\Routing;
4
5
use Desilva\Microserve\JsonResponse;
6
use Desilva\Microserve\Request;
7
use Desilva\Microserve\Response;
8
use Hyde\RealtimeCompiler\Actions\AssetFileLocator;
9
use Hyde\RealtimeCompiler\Concerns\SendsErrorResponses;
10
use Hyde\RealtimeCompiler\Models\FileObject;
11
use Hyde\RealtimeCompiler\Concerns\InteractsWithLaravel;
12
use Hyde\Framework\Actions\GeneratesDocumentationSearchIndex;
13
14
class Router
15
{
16
    use SendsErrorResponses;
17
    use InteractsWithLaravel;
18
19
    protected Request $request;
20
21
    protected array $virtualRoutes = [
22
        '/ping',
23
    ];
24
25
    public function __construct(Request $request)
26
    {
27
        $this->request = $request;
28
    }
29
30
    public function handle(): Response
31
    {
32
        if ($this->shouldProxy($this->request)) {
33
            return $this->proxyStatic();
34
        }
35
36
        if (in_array($this->request->path, $this->virtualRoutes)) {
37
            if ($this->request->path === '/ping') {
38
                return new JsonResponse(200, 'OK', [
39
                    'server' => 'Hyde/RealtimeCompiler',
40
                ]);
41
            }
42
        }
43
44
        return PageRouter::handle($this->request);
45
    }
46
47
    /**
48
     * If the request is not for a web page, we assume it's
49
     * a static asset, which we instead want to proxy.
50
     */
51
    protected function shouldProxy(Request $request): bool
52
    {
53
        // Always proxy media files. This condition is just to improve performance
54
        // without having to check the file extension.
55
        if (str_starts_with($request->path, '/media/')) {
56
            return true;
57
        }
58
59
        // Get the requested file extension
60
        $extension = pathinfo($request->path)['extension'] ?? null;
61
62
        // If the extension is not set (pretty url), or is .html,
63
        // we assume it's a web page which we need to compile.
64
        if ($extension === null || $extension === 'html') {
65
            return false;
66
        }
67
68
        // The page is not a web page, so we assume it should be proxied.
69
        return true;
70
    }
71
72
    /**
73
     * Proxy a static file or return a 404.
74
     */
75
    protected function proxyStatic(): Response
76
    {
77
        if ($this->request->path === '/docs/search.json') {
78
            $this->generateSearchIndex();
79
        }
80
81
        $path = AssetFileLocator::find($this->request->path);
82
83
        if ($path === null) {
84
            return $this->notFound();
85
        }
86
87
        $file = new FileObject($path);
88
89
        return (new Response(200, 'OK', [
90
            'body' => $file->getStream(),
91
        ]))->withHeaders([
92
            'Content-Type'   => $file->getMimeType(),
93
            'Content-Length' => $file->getContentLength(),
94
        ]);
95
    }
96
97
    /**
98
     * Generate the documentation search index.
99
     */
100
    protected function generateSearchIndex(): void
101
    {
102
        $this->bootApplication();
103
104
        GeneratesDocumentationSearchIndex::handle();
105
    }
106
}
107