(Update) Http2ServerPush Middleware 🚀

This commit is contained in:
HDVinnie
2019-09-16 15:19:42 -04:00
parent fd718fdde1
commit 89eeaef5a5
2 changed files with 73 additions and 20 deletions
+47 -20
View File
@@ -14,7 +14,6 @@
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Symfony\Component\DomCrawler\Crawler;
@@ -31,45 +30,66 @@ class Http2ServerPush
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @param null $limit
* @return mixed
*/
public function handle(Request $request, Closure $next, $limit = null)
public function handle(Request $request, Closure $next, $limit = null, $sizeLimit = null, $excludeKeywords=null)
{
$response = $next($request);
if ($response->isRedirection() || ! $response instanceof Response || $request->isJson()) {
if ($response->isRedirection() || !$response instanceof Response || $request->isJson()) {
return $response;
}
$this->generateAndAttachLinkHeaders($response, $limit);
$this->generateAndAttachLinkHeaders($response, $limit, $sizeLimit, $excludeKeywords);
return $response;
}
public function getConfig($key, $default=false) {
if(!function_exists('config')) { // for tests..
return $default;
}
return config('http2serverpush.'.$key, $default);
}
/**
* @param \Illuminate\Http\Response $response
* @param \Illuminate\Http\Response $response
*
* @param null $limit
* @return $this
*/
protected function generateAndAttachLinkHeaders(Response $response, $limit = null)
protected function generateAndAttachLinkHeaders(Response $response, $limit = null, $sizeLimit = null, $excludeKeywords=null)
{
$excludeKeywords ?? $this->getConfig('exclude_keywords', []);
$headers = $this->fetchLinkableNodes($response)
->flatten(1)
->map(function ($url) {
return $this->buildLinkHeaderString($url);
})
->filter()
->unique()
->take($limit)
->implode(',');
->filter(function($value, $key) use ($excludeKeywords){
if(!$value) return false;
$exclude_keywords = collect($excludeKeywords)->map(function ($keyword) {
return preg_quote($keyword);
});
if($exclude_keywords->count() <= 0) {
return true;
}
return !preg_match('%('.$exclude_keywords->implode('|').')%i', $value);
})
->take($limit);
if (! empty(trim($headers))) {
$this->addLinkHeader($response, $headers);
$sizeLimit = $sizeLimit ?? max(1, intval($this->getConfig('size_limit', 32*1024)));
$headersText = trim($headers->implode(','));
while(strlen($headersText) > $sizeLimit) {
$headers->pop();
$headersText = trim($headers->implode(','));
}
if (!empty($headersText)) {
$this->addLinkHeader($response, $headersText);
}
return $this;
@@ -102,7 +122,7 @@ class Http2ServerPush
{
$crawler = $this->getCrawler($response);
return collect($crawler->filter('link, script[src]')->extract(['src', 'href']));
return collect($crawler->filter('link:not([rel*="icon"]), script[src], img[src], object[data]')->extract(['src', 'href', 'data']));
}
/**
@@ -120,24 +140,31 @@ class Http2ServerPush
];
$type = collect($linkTypeMap)->first(function ($type, $extension) use ($url) {
return Str::contains(strtoupper($url), $extension);
return str_contains(strtoupper($url), $extension);
});
if(!preg_match('%^https?://%i', $url)) {
$basePath = $this->getConfig('base_path', '/');
$url = $basePath . ltrim($url, $basePath);
}
return is_null($type) ? null : "<{$url}>; rel=preload; as={$type}";
}
/**
* Add Link Header.
* Add Link Header
*
* @param \Illuminate\Http\Response $response
*
* @param $link
*/
private function addLinkHeader(Response $response, $link)
{
if ($response->headers->get('Link')) {
$link = $response->headers->get('Link').','.$link;
$link = $response->headers->get('Link') . ',' . $link;
}
$response->header('Link', $link);
}
}
}