Skip to content

Commit 2ef203c

Browse files
kellerjmrtnKeller Martin
and
Keller Martin
authored
Send Entire Request, Including Query Params, To Prerender (#40)
* Send Entire Request, Including Query Params, To Prerender * Update To Include New Config Value & Maintain Backwards Compatibility * Fix Typo --------- Co-authored-by: Keller Martin <kellerm@schwebdesign.com>
1 parent 44809f1 commit 2ef203c

File tree

5 files changed

+115
-10
lines changed

5 files changed

+115
-10
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,22 @@ return [
289289
| See: https://docs.guzzlephp.org/en/stable/request-options.html#timeout
290290
|
291291
*/
292+
292293
'timeout' => env('PRERENDER_TIMEOUT', 0),
293294

295+
/*
296+
|--------------------------------------------------------------------------
297+
| Query Parameters
298+
|--------------------------------------------------------------------------
299+
|
300+
| By default, request query parameters are not sent to prerender when
301+
| requesting the prerendered page. Setting this to true will cause the full
302+
| URL, including query parameters, to be sent to prerender.
303+
|
304+
*/
305+
306+
'full_url' => env('PRERENDER_FULL_URL', false),
307+
294308
];
295309
```
296310

config/prerender.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,20 @@
194194
| See: https://docs.guzzlephp.org/en/stable/request-options.html#timeout
195195
|
196196
*/
197+
197198
'timeout' => env('PRERENDER_TIMEOUT', 0),
198199

200+
/*
201+
|--------------------------------------------------------------------------
202+
| Query Parameters
203+
|--------------------------------------------------------------------------
204+
|
205+
| By default, request query parameters are not sent to prerender when
206+
| requesting the prerendered page. Setting this to true will cause the full
207+
| URL, including query parameters, to be sent to prerender.
208+
|
209+
*/
210+
211+
'full_url' => env('PRERENDER_FULL_URL', false),
212+
199213
];

src/PrerenderMiddleware.php

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ class PrerenderMiddleware
6565
*/
6666
private $returnSoftHttpCodes;
6767

68+
/**
69+
* Send the full request URL to prerender.
70+
*
71+
* @var bool
72+
*/
73+
private $useFullURL;
74+
6875
/**
6976
* Creates a new PrerenderMiddleware instance.
7077
*/
@@ -88,6 +95,7 @@ public function __construct(Guzzle $client)
8895
$this->prerenderToken = $config['prerender_token'];
8996
$this->whitelist = $config['whitelist'];
9097
$this->blacklist = $config['blacklist'];
98+
$this->useFullURL = $config['full_url'];
9199
}
92100

93101
/**
@@ -195,18 +203,10 @@ private function getPrerenderedPageResponse(Request $request): ?ResponseInterfac
195203
$headers['X-Prerender-Token'] = $this->prerenderToken;
196204
}
197205

198-
$protocol = $request->isSecure() ? 'https' : 'http';
199-
200206
try {
201-
// Return the Guzzle Response
202-
$host = $request->getHost();
203-
$path = $request->Path();
204-
// Fix "//" 404 error
205-
if ($path === '/') {
206-
$path = '';
207-
}
207+
$url = $this->generatePrerenderUrl($request);
208208

209-
return $this->client->get($this->prerenderUri.'/'.urlencode($protocol.'://'.$host.'/'.$path), compact('headers'));
209+
return $this->client->get($this->prerenderUri.'/'.urlencode($url), compact('headers'));
210210
} catch (RequestException $exception) {
211211
if (!$this->returnSoftHttpCodes && !empty($exception->getResponse()) && $exception->getResponse()->getStatusCode() === 404) {
212212
abort(404);
@@ -250,4 +250,26 @@ private function isListed($needles, array $list): bool
250250

251251
return false;
252252
}
253+
254+
/**
255+
* Generate the request URL to send to prerender. When useFullURL is false, the legacy URL
256+
* generation logic is used
257+
*/
258+
private function generatePrerenderUrl(Request $request): string
259+
{
260+
if ($this->useFullURL) {
261+
return $request->fullUrl();
262+
}
263+
264+
$protocol = $request->isSecure() ? 'https' : 'http';
265+
$host = $request->getHost();
266+
$path = $request->Path();
267+
268+
// Fix "//" 404 error
269+
if ($path === '/') {
270+
$path = '';
271+
}
272+
273+
return $protocol.'://'.$host.'/'.$path;
274+
}
253275
}

tests/PrerenderMiddlewareTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,45 @@ public function it_should_not_prerender_page_if_request_times_out()
9494
->assertSee('GET - Success');
9595
}
9696

97+
/** @test */
98+
public function it_does_not_send_query_strings_to_prerender_by_default()
99+
{
100+
$this->app->bind(Client::class, function () {
101+
return $this->createMockUrlTrackingClient();
102+
});
103+
104+
$this->allowSymfonyUserAgent();
105+
106+
$this->get('/test-middleware?withQueryParam=true')
107+
->assertHeader('prerender.io-mock', true)
108+
->assertSuccessful()
109+
->assertSee(urlencode('/test-middleware'))
110+
->assertDontSee('withQueryParam');
111+
}
112+
113+
/** @test */
114+
public function it_sends_full_query_string_to_prerender()
115+
{
116+
$this->app->bind(Client::class, function () {
117+
return $this->createMockUrlTrackingClient();
118+
});
119+
120+
$this->allowSymfonyUserAgent();
121+
$this->allowQueryParams();
122+
123+
$this->get('/test-middleware?withQueryParam=true')
124+
->assertHeader('prerender.io-mock', true)
125+
->assertSuccessful()
126+
->assertSee(urlencode('/test-middleware?withQueryParam=true'));
127+
}
128+
97129
private function allowSymfonyUserAgent()
98130
{
99131
config()->set('prerender.crawler_user_agents', ['symfony']);
100132
}
133+
134+
private function allowQueryParams()
135+
{
136+
config()->set('prerender.full_url', true);
137+
}
101138
}

tests/TestCase.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Illuminate\Foundation\Application;
1414
use Illuminate\Foundation\Http\Kernel;
1515
use Illuminate\Support\Facades\Route;
16+
use Psr\Http\Message\RequestInterface;
1617

1718
class TestCase extends \Orchestra\Testbench\TestCase
1819
{
@@ -62,6 +63,23 @@ protected function createMockTimeoutClient(): Client
6263
return new Client(['handler' => $stack]);
6364
}
6465

66+
protected function createMockUrlTrackingClient(): Client
67+
{
68+
$mock = new MockHandler([
69+
function (RequestInterface $request) {
70+
return new Response(
71+
200,
72+
['prerender.io-mock' => true],
73+
(string) $request->getUri()
74+
);
75+
},
76+
]);
77+
78+
$stack = HandlerStack::create($mock);
79+
80+
return new Client(['handler' => $stack]);
81+
}
82+
6583
protected function setupRoutes(): void
6684
{
6785
Route::get('test-middleware', function () {

0 commit comments

Comments
 (0)