Skip to content

Commit

Permalink
Config file for : Size limit, exceptions, base path (#28)
Browse files Browse the repository at this point in the history
* #25 deduplicate header links

* - Add config file
- Add size limit
- Add base path configuration
- Add exceptions filters
- Update test
- Updates doc

solves #23, #27

* update travis :
- remove PHP5.6,
- add PHP7.2 and 7.3
  • Loading branch information
Nuranto authored and JacobBennett committed Sep 19, 2019
1 parent 2c861a2 commit a03e7ac
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 10 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
language: php

php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3

env:
matrix:
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ protected $middlewareGroups = [
];
```

## Publish config

```php
php artisan vendor:publish --provider="JacobBennett\Http2ServerPush\ServiceProvider"
```


## Usage

When you route a request through the `AddHttp2ServerPush` middleware, the response is scanned for any `link`, `script` or `img` tags that could benefit from being loaded using Server Push.
Expand Down
45 changes: 37 additions & 8 deletions src/Middleware/AddHttp2ServerPush.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,61 @@ class AddHttp2ServerPush
*
* @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()) {
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
*
* @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);

$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(trim($headers))) {
$this->addLinkHeader($response, $headers);
if (!empty($headersText)) {
$this->addLinkHeader($response, $headersText);
}

return $this;
Expand Down Expand Up @@ -115,6 +138,12 @@ private function buildLinkHeaderString($url)
$type = collect($linkTypeMap)->first(function ($type, $extension) use ($url) {
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}";
}
Expand Down
22 changes: 22 additions & 0 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace JacobBennett\Http2ServerPush;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;

class ServiceProvider extends LaravelServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
// Register paths to be published by 'vendor:publish' Artisan command
$this->publishes([
__DIR__ . '/config.php' => config_path('http2serverpush.php'),
]);
}

}
8 changes: 8 additions & 0 deletions src/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php


return [
'size_limit' => '6000', // in bytes
'base_path' => '/',
'exclude_keywords' => []
];
28 changes: 27 additions & 1 deletion tests/AddHttp2ServerPushTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,32 @@ public function setUp()
$this->middleware = new AddHttp2ServerPush();
}


/** @test */
public function it_will_not_exceed_size_limit()
{
$request = new Request();

$limit = 50;
$response = $this->middleware->handle($request, $this->getNext('pageWithCssAndJs'), null, $limit, []);

$this->assertTrue($this->isServerPushResponse($response));
$this->assertTrue(strlen($response->headers->get('link')) <= $limit );
$this->assertCount(1, explode(",", $response->headers->get('link')));
}

/** @test */
public function it_will_not_add_excluded_asset()
{
$request = new Request();

$response = $this->middleware->handle($request, $this->getNext('pageWithCssAndJs'), null, null, ['thing']);

$this->assertTrue($this->isServerPushResponse($response));
$this->assertTrue(!str_contains($response->headers, 'thing'));
$this->assertCount(1, explode(",", $response->headers->get('link')));
}

/** @test */
public function it_will_not_modify_a_response_with_no_server_push_assets()
{
Expand Down Expand Up @@ -77,7 +103,7 @@ public function it_returns_well_formatted_link_headers()

$response = $this->middleware->handle($request, $this->getNext('pageWithCss'));

$this->assertEquals("<css/test.css>; rel=preload; as=style", $response->headers->get('link'));
$this->assertEquals("</css/test.css>; rel=preload; as=style", $response->headers->get('link'));
}

/** @test */
Expand Down

0 comments on commit a03e7ac

Please sign in to comment.