Skip to content

Commit 394c8dd

Browse files
author
thomaskeyte
committed
Only add header in middleware for correct response type
Previously, the middleware was applied for all GET responses, which could cause errors
1 parent 3d20af3 commit 394c8dd

File tree

2 files changed

+155
-19
lines changed

2 files changed

+155
-19
lines changed

src/Middleware/AddLinkHeader.php

+49-6
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,21 @@
33
namespace TomKeyte\LaravelHttp2Push\Middleware;
44

55
use Closure;
6+
use Illuminate\Support\Facades\Log;
7+
use Throwable;
68

79
class AddLinkHeader
810
{
11+
/**
12+
* The request object
13+
*/
14+
protected $request;
15+
16+
/**
17+
* The response object
18+
*/
19+
protected $response;
20+
921
/**
1022
* Handle an incoming request.
1123
*
@@ -16,15 +28,46 @@ class AddLinkHeader
1628
*/
1729
public function handle($request, Closure $next)
1830
{
19-
$response = $next($request);
31+
$this->request = $request;
32+
$this->response = $next($request);
33+
34+
try {
35+
if ($this->isCorrectRequestType() && $this->isCorrectResponseType()) {
36+
$this->pushReources();
37+
}
38+
} catch (Throwable $t) {
39+
Log::error($t);
40+
}
41+
42+
return $this->response;
43+
}
44+
45+
/**
46+
* Check that the request is of the correct type for a HTTP push
47+
*/
48+
private function isCorrectRequestType(): bool
49+
{
50+
return $this->request->method() === 'GET' && !$this->request->isJson();
51+
}
52+
53+
/**
54+
* Check that the response is of the correct type for a HTTP push
55+
*/
56+
private function isCorrectResponseType(): bool
57+
{
58+
return ($this->response instanceof \Illuminate\Http\Response && !$this->response->isRedirection());
59+
}
2060

61+
/**
62+
* Add the Link header to the response
63+
*/
64+
private function pushReources(): void
65+
{
2166
$http2push = resolve('http2push');
2267

23-
if ($request->method() === 'GET' && $http2push->isNotEmpty()) {
24-
$response->header('Link', $http2push->buildLinkHeader(), false);
25-
$http2push->setPushCookies($response);
68+
if ($http2push->isNotEmpty()) {
69+
$this->response->header('Link', $http2push->buildLinkHeader(), false);
70+
$http2push->setPushCookies($this->response);
2671
}
27-
28-
return $response;
2972
}
3073
}

tests/MiddlewareTest.php

+106-13
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
namespace TomKeyte\LaravelHttp2Push\Tests;
44

5+
use Illuminate\Foundation\Testing\TestResponse;
56
use Illuminate\Http\Request;
7+
use Illuminate\Http\Response;
8+
use Illuminate\Support\Facades\Log;
69
use TomKeyte\LaravelHttp2Push\Http2PushServiceProvider;
710
use TomKeyte\LaravelHttp2Push\Middleware\AddLinkHeader;
811
use TomKeyte\LaravelHttp2Push\PushCookie;
912
use Orchestra\Testbench\TestCase;
13+
use stdClass;
1014

1115
class MiddlewareTest extends TestCase
1216
{
@@ -26,40 +30,129 @@ protected function setUp(): void
2630
// have to empty cookie array between runs
2731
$_COOKIE = [];
2832

29-
$this->response = $this->get('/');
30-
$this->request = Request::create('/', 'GET');
33+
$this->response = new Response();
34+
$this->request = new Request();
3135
$this->push = $this->app->get('http2push');
3236
$this->push->add('/js/app.js');
3337
}
3438

39+
/**
40+
* Converts a base response class into a test response
41+
*/
42+
private function toTestResponse($response)
43+
{
44+
return TestResponse::fromBaseResponse($response);
45+
}
46+
47+
/**
48+
* @test
49+
*/
50+
public function a_response_has_the_link_header()
51+
{
52+
$this->toTestResponse(
53+
(new AddLinkHeader)
54+
->handle(
55+
$this->request,
56+
function () {
57+
return $this->response;
58+
}
59+
)
60+
)
61+
->assertHeader('Link', $this->push->buildLinkHeader());
62+
}
3563

3664
/**
3765
* @test
3866
*/
3967
public function a_response_has_the_push_cookie()
4068
{
41-
(new AddLinkHeader)
42-
->handle(
43-
$this->request,
44-
function () {
45-
return $this->response;
46-
}
47-
)
69+
$this->toTestResponse(
70+
(new AddLinkHeader)
71+
->handle(
72+
$this->request,
73+
function () {
74+
return $this->response;
75+
}
76+
)
77+
)
4878
->assertCookie((new PushCookie('/js/app.js'))->getName());
4979
}
5080

5181
/**
5282
* @test
5383
*/
54-
public function a_response_has_the_link_header()
84+
public function it_does_not_set_link_header_for_json_request()
5585
{
86+
$jsonRequest = (new Request());
87+
$jsonRequest->headers->set('Content-Type', 'application/json', true);
88+
89+
$this->toTestResponse(
90+
(new AddLinkHeader)
91+
->handle(
92+
$jsonRequest,
93+
function () {
94+
return $this->response;
95+
}
96+
)
97+
)
98+
->assertHeaderMissing('Link');
99+
}
100+
101+
/**
102+
* @test
103+
*/
104+
public function it_does_not_set_link_header_for_redirect_response()
105+
{
106+
$redirectResponse = new Response('', 302);
107+
108+
$this->toTestResponse(
109+
(new AddLinkHeader)
110+
->handle(
111+
$this->request,
112+
function () use ($redirectResponse) {
113+
return $redirectResponse;
114+
}
115+
)
116+
)
117+
->assertHeaderMissing('Link');
118+
}
119+
120+
/**
121+
* @test
122+
*/
123+
public function it_does_not_set_link_header_for_a_binary_response()
124+
{
125+
$binaryResponse = response()->streamDownload(
126+
function () {
127+
return ['data'];
128+
}
129+
);
130+
131+
$this->toTestResponse(
132+
(new AddLinkHeader)
133+
->handle(
134+
$this->request,
135+
function () use ($binaryResponse) {
136+
return $binaryResponse;
137+
}
138+
)
139+
)
140+
->assertHeaderMissing('Link');
141+
}
142+
143+
/**
144+
* @test
145+
*/
146+
public function it_logs_an_error_if_middleware_throws_exception()
147+
{
148+
Log::shouldReceive('error');
149+
56150
(new AddLinkHeader)
57151
->handle(
58-
$this->request,
152+
(new stdClass),
59153
function () {
60154
return $this->response;
61155
}
62-
)
63-
->assertHeader('Link', $this->push->buildLinkHeader());
156+
);
64157
}
65158
}

0 commit comments

Comments
 (0)