Prerender.php
4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?php
namespace FootyRoom\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use FootyRoom\PrerenderService;
class Prerender
{
/**
* List of crawler user agents that will be.
*
* @var array
*/
protected $crawlerUserAgents = [
'Googlebot',
'bingbot',
'Yahoo',
'YandexBot',
'Baiduspider',
'Twitterbot',
'facebookexternalhit',
];
/**
* URI whitelist for prerendering pages only on this list.
*
* Whitelist paths or patterns. You can use asterix syntax, or regular
* expressions (without start and end markers). If a whitelist is supplied,
* only url's containing a whitelist path will be prerendered. An empty
* array means that all URIs will pass this filter. Note that this is the
* full request URI, so including starting slash and query parameter string.
* See github.com/JeroenNoten/Laravel-Prerender for an example.
*
* @var array
*/
protected $whitelist = [
'/matches/*',
'/lemix/*'
];
/**
* URI blacklist for prerendering pages that are not on the list.
*
* Blacklist paths to exclude. You can use asterix syntax, or regular
* expressions (without start and end markers). If a blacklist is supplied,
* all url's will be prerendered except ones containing a blacklist path. By
* default, a set of asset extentions are included (this is actually only
* necessary when you dynamically provide assets via routes). Note that this
* is the full request URI, so including starting slash and query parameter
* string. See github.com/JeroenNoten/Laravel-Prerender for an example.
*
* @var array
*/
protected $blacklist = [];
/**
* @var \FootyRoom\PrerenderService
*/
protected $prerenderService;
public function __construct(PrerenderService $prerenderService)
{
$this->prerenderService = $prerenderService;
}
/**
* Handles a request and prerender if it should, otherwise call the next middleware.
*
* @return Response
*/
public function handle(Request $request, Closure $next)
{
if ($this->shouldShowPrerenderedPage($request)) {
$response = $this->prerenderService->prerender($request->fullUrl(), false);
if ($response) {
return $response;
}
}
// If prerender could not prerender it properly then let it handle as usual instead.
return $next($request);
}
/**
* Returns whether the request must be prerendered.
*/
protected function shouldShowPrerenderedPage(Request $request): bool
{
if (!$request->isMethod('GET')) {
return false;
}
$userAgent = $request->userAgent();
// Prerender if a crawler is detected.
if (!$userAgent || !$this->isUserAgentListed($userAgent)) {
return false;
}
$requestUri = $request->getRequestUri();
// Only check whitelist if it is not empty.
if ($this->whitelist) {
if (!$this->isListed([$requestUri], $this->whitelist)) {
return false;
}
}
// Only check blacklist if it is not empty.
if ($this->blacklist) {
if ($this->isListed([$requestUri], $this->blacklist)) {
return false;
}
}
// Okay! Prerender please.
return true;
}
/**
* Determine if given user agent needs prerendered response.
*/
protected function isUserAgentListed($userAgent): bool
{
foreach ($this->crawlerUserAgents as $crawlerUserAgent) {
if (str_contains($userAgent, $crawlerUserAgent)) {
return true;
}
}
return false;
}
/**
* Check whether one or more needles are in the given list.
*/
protected function isListed(array $needles, array $list): bool
{
foreach ($list as $pattern) {
foreach ($needles as $needle) {
if (str_is($pattern, $needle)) {
return true;
}
}
}
return false;
}
}