Skip to content

Commit

Permalink
added comments
Browse files Browse the repository at this point in the history
  • Loading branch information
jeroennoten committed Aug 5, 2014
1 parent 8a3002d commit 621063b
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 11 deletions.
13 changes: 2 additions & 11 deletions src/Nutsweb/LaravelPrerender/LaravelPrerenderServiceProvider.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php namespace Nutsweb\LaravelPrerender;

use App;
use Config;
use GuzzleHttp\Client;
use Illuminate\Support\ServiceProvider;

Expand Down Expand Up @@ -34,6 +33,8 @@ public function boot()
*/
public function register()
{
// We must register a package for cascading configuration ourselves, because it is normally done
// after booting the application, but we need the configuration beforehand.
$namespace = $this->getPackageNamespace($this->package, null);
$config = $this->guessPackagePath() . '/config';
$this->app['config']->package($this->package, $config, $namespace);
Expand All @@ -54,14 +55,4 @@ public function register()
}
}

/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array();
}

}
84 changes: 84 additions & 0 deletions src/Nutsweb/LaravelPrerender/PrerenderMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,59 @@

class PrerenderMiddleware implements HttpKernelInterface
{
/**
* The application instance (implements the HttpKernelInterface)
*
* @var HttpKernelInterface
*/
private $app;

/**
* The Guzzle Client that sends GET requests to the prerender server
* This client must take care of the base URL by itself
*
* @var GuzzleClient
*/
private $client;

/**
* This token will be provided via the X-Prerender-Token header.
*
* @var string
*/
private $prerenderToken;

/**
* List of crawler user agents that will be
*
* @var array
*/
private $crawlerUserAgents;

/**
* URI whitelist for prerendering pages only on this list
*
* @var array
*/
private $whitelist;

/**
* URI blacklist for prerendering pages that are not on the list
*
* @var array
*/
private $blacklist;

/**
* Creates a new PrerenderMiddleware instance
*
* @param HttpKernelInterface $app
* @param GuzzleClient $client
* @param $prerenderToken
* @param array $crawlerUserAgents
* @param array $whitelist
* @param array $blacklist
*/
public function __construct(HttpKernelInterface $app,
GuzzleClient $client,
$prerenderToken,
Expand All @@ -40,6 +81,14 @@ public function __construct(HttpKernelInterface $app,
$this->blacklist = $blacklist;
}

/**
* Handles a request and prerender if it should, otherwise call the next middleware.
*
* @param SymfonyRequest $request
* @param int $type
* @param bool $catch
* @return SymfonyResponse
*/
public function handle(SymfonyRequest $request, $type = self::MASTER_REQUEST, $catch = true)
{
if ($this->shouldShowPrerenderedPage($request)) {
Expand All @@ -52,6 +101,12 @@ public function handle(SymfonyRequest $request, $type = self::MASTER_REQUEST, $c
return $this->app->handle($request, $type, $catch);
}

/**
* Returns whether the request must be prerendered.
*
* @param SymfonyRequest $request
* @return bool
*/
private function shouldShowPrerenderedPage(SymfonyRequest $request)
{
$userAgent = strtolower($request->server->get('HTTP_USER_AGENT'));
Expand All @@ -64,8 +119,10 @@ private function shouldShowPrerenderedPage(SymfonyRequest $request)
if (!$userAgent) return false;
if (!$request->isMethod('GET')) return false;

// prerender if _escaped_fragment_ is in the query string
if ($request->query->has('_escaped_fragment_')) $isRequestingPrerenderedPage = true;

// prerender if a crawler is detected
foreach ($this->crawlerUserAgents as $crawlerUserAgent) {
if (str_contains($userAgent, strtolower($crawlerUserAgent))) {
$isRequestingPrerenderedPage = true;
Expand All @@ -76,23 +133,33 @@ private function shouldShowPrerenderedPage(SymfonyRequest $request)

if (!$isRequestingPrerenderedPage) return false;

// 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) {
$uris[] = $requestUri;
// we also check for a blacklisted referer
if ($referer) $uris[] = $referer;
if ($this->isListed($uris, $this->blacklist)) {
return false;
}
}

// Okay! Prerender please.
return true;
}

/**
* Prerender the page and return the Guzzle Response
*
* @param SymfonyRequest $request
* @return null|void
*/
private function getPrerenderedPageResponse(SymfonyRequest $request)
{
$headers = [
Expand All @@ -103,15 +170,25 @@ private function getPrerenderedPageResponse(SymfonyRequest $request)
}

try {
// Return the Guzzle Response
return $this->client->get('/' . urlencode($request->getUri()), compact('headers'));
} catch (RequestException $exception) {
// In case of an exception, we only throw the exception if we are in debug mode. Otherwise,
// we return null and the handle() method will just pass the request to the next middleware
// and we do not show a prerendered page.
if ($this->app['config']->get('app.debug')) {
throw $exception;
}
return null;
}
}

/**
* Convert a Guzzle Response to a Symfony Response
*
* @param GuzzleResponse $prerenderedResponse
* @return SymfonyResponse
*/
private function buildSymfonyResponseFromGuzzleResponse(GuzzleResponse $prerenderedResponse)
{
$body = $prerenderedResponse->getBody();
Expand All @@ -120,6 +197,13 @@ private function buildSymfonyResponseFromGuzzleResponse(GuzzleResponse $prerende
return new SymfonyResponse($body, $statusCode, $headers);
}

/**
* Check whether one or more needles are in the given list
*
* @param $needles
* @param $list
* @return bool
*/
private function isListed($needles, $list)
{
$needles = is_array($needles) ? $needles : [$needles];
Expand Down

0 comments on commit 621063b

Please sign in to comment.