Skip to content

Commit

Permalink
Moving over to a more robust approach to routing
Browse files Browse the repository at this point in the history
  • Loading branch information
develpr committed Jun 3, 2015
1 parent 5e5f0db commit e8ff4a7
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 37 deletions.
9 changes: 9 additions & 0 deletions src/Facades/AlexaRouter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php namespace Develpr\AlexaApp\Facades;

use Illuminate\Support\Facades\Facade;

class AlexaRouter extends Facade {
protected static function getFacadeAccessor() {
return 'alexa.router';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Develpr\AlexaApp\Exceptions\InvalidCertificateException;
use Develpr\AlexaApp\Exceptions\InvalidAppIdException;

class VerifyAlexaRequestSecurity implements Middleware{
class Certificate implements Middleware{

const CERTIFICATE_URL_HEADER = "Signaturecertchainurl";
const SIGNATURE_HEADER = "Signature";
Expand Down
89 changes: 89 additions & 0 deletions src/Http/Middleware/Request.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,94 @@
<?php namespace Develpr\AlexaApp\Http\Middleware;

use Develpr\AlexaApp\Http\Routing\AlexaRouter;
use Closure;
use Develpr\AlexaApp\Request\AlexaRequest;
use Illuminate\Pipeline\Pipeline;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Request as IlluminateRequest;


class Request {
/**
* Application instance.
*
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;

/**
* Router instance.
*
* @var AlexaRouter
*/
protected $router;

/**
* HTTP validator instance.
*
* @var \Dingo\Api\Http\Validator
*/
// protected $validator;

/**
* Array of middleware.
*
* @var array
*/
protected $middleware;
/**
* @var \Develpr\AlexaApp\Request\AlexaRequest
*/
private $alexaRequest;

/**
* @param Application $app
* @param AlexaRouter $router
* @param AlexaRequest $alexaRequest
* @param array $middleware
*/
public function __construct(Application $app, AlexaRouter $router, AlexaRequest $alexaRequest, array $middleware)
{
$this->app = $app;
$this->router = $router;
$this->middleware = $middleware;
$this->alexaRequest = $alexaRequest;
}

/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$test = "HI";

// if ($this->validator->validateRequest($request)) {
if ($this->alexaRequest->isAlexaRequest()) {
return $this->sendRequestThroughRouter($request);
}

return $next($request);
}

/**
* Send the request through the Dingo router.
*
* @param \Illuminate\Http\Request $request
*
* @return \Dingo\Api\Http\Response
*/
protected function sendRequestThroughRouter( $request)
{
$this->app->instance('request', $request);

return (new Pipeline($this->app))->send($request)->through($this->middleware)->then(function ($request) {
return $this->router->dispatch($request);
});

}
}
4 changes: 2 additions & 2 deletions src/Http/Routing/AlexaRouter.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php namespace Develpr\AlexaApp\Http\Routing;

use Illuminate\Routing\Router;
use Illuminate\Routing\Router as IlluminateRouter;

class AlexaRouter extends Router{
class AlexaRouter extends IlluminateRouter{

private $intentRoutes = [];

Expand Down
66 changes: 34 additions & 32 deletions src/Provider/AlexaServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Develpr\AlexaApp\Certificate\RedisCertificateProvider;
use Develpr\AlexaApp\Device\DatabaseDeviceProvider;
use Develpr\AlexaApp\Device\EloquentDeviceProvider;
use Develpr\AlexaApp\Http\Routing\AlexaRouter;
use Develpr\AlexaApp\Request\NonAlexaRequest;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Http\Request;
Expand All @@ -17,12 +18,6 @@
class AlexaServiceProvider extends ServiceProvider
{

public function boot()
{

}


/**
* Register any application services.
*
Expand All @@ -34,12 +29,28 @@ public function register()

$request = $this->app->make('request');

$this->setupClassAliases();
$this->registerRouter();
$this->bindAlexaRequest($request);
$this->bindCertificateProvider();
$this->bindAlexa();
$this->registerMiddleware();

}

protected function setupClassAliases()
{
$this->app->alias('alexa.router', 'Develpr\AlexaApp\Http\Routing\AlexaRouter');
$this->app->alias('alexa.request', 'Develpr\AlexaApp\Request\AlexaRequest');
}

protected function registerRouter()
{
$this->app->singleton('alexa.router', function ($app) {
return $app->make('\Develpr\AlexaApp\Http\Routing\AlexaRouter');
});
}

protected function setupConfig()
{
$this->mergeConfigFrom(realpath(__DIR__.'/../../config/alexa.php'), 'alexa');
Expand All @@ -50,86 +61,77 @@ protected function setupConfig()
*/
private function bindAlexaRequest(Request $request)
{
$this->app->singleton('Develpr\AlexaApp\Request\AlexaRequest', function() use ($request) {
$this->app->singleton('alexa.request', function() use ($request) {

//todo: do something more complex to verify that a request really should be handled by AlexaApp
$requestType = array_get(json_decode($request->getContent(), true), 'request.type');

//todo: throw an exception?
if(! $requestType)
return new NonAlexaRequest;

if(! $requestType){
return new NonAlexaRequest;
}
$className = 'Develpr\AlexaApp\Request\\' . $requestType;

if( ! class_exists($className))
{
throw new Exception("This type of request is not supported");
}

return new $className($request);

});
}

private function bindAlexa()
{
$this->app->singleton('alexa', function($app){

$providerType = $app['config']['alexa.device.provider'];

$provider = null;

if($providerType == "eloquent"){

$provider = new EloquentDeviceProvider($app['config']['alexa.device.model']);

}else if($providerType == "database"){

$connection = $app['db']->connection();

$provider = new DatabaseDeviceProvider($connection, $app['config']['alexa.device.table']);

}else{
throw new Exception("Unsupported Alexa Device Provider specified - currently only 'database' and 'eloquent' are supported");
}

$alexaRequest = $this->app->make('Develpr\AlexaApp\Request\AlexaRequest');

return new Alexa($alexaRequest, $provider, $app['config']['alexa']);

});
}

/**
* Register the middleware.
*
* @return void
*/
protected function registerMiddleware()
{
$this->app->singleton('Develpr\AlexaApp\Http\Middleware\Request', function ($app) {
return new \Develpr\AlexaApp\Http\Middleware\Request($app, $app['alexa.router'], $app['alexa.request'], $app['app.middleware']);
});
}

private function bindCertificateProvider()
{
$this->app->bind('Develpr\AlexaApp\Contracts\CertificateProvider', function($app){

$providerType = $this->app['config']['alexa.certificate.provider'];

if($providerType == "file"){

$provider = new FileCertificateProvider(new Filesystem, $this->app['config']['alexa.certificate.filePath']);

}else if($providerType == "redis"){

$redis = $app->make('redis');
$provider = new RedisCertificateProvider($redis);

}else if($providerType == "eloquent"){

$provider = new EloquentCertificateProvider($app['config']['alexa.certificate.model']);

}else if($providerType == "database"){

$connection = $app['db']->connection();

$provider = new DatabaseCertificateProvider($connection, $app['config']['alexa.device.table']);

}else{
throw new Exception("Unsupported Alexa Certificate Provider specified - currently only 'file', 'database', and 'eloquent' are supported");
}

return $provider;

});
}
}
51 changes: 49 additions & 2 deletions src/Provider/LaravelServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,59 @@

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Support\ServiceProvider;
use ReflectionClass;

class LaravelServiceProvider extends ServiceProvider {

public function boot()
{
$this->publishes([
realpath(__DIR__.'/../../config/alexa.php') => config_path('alexa.php'),
]);

$this->app['router']->middleware('alexa.certificate', 'Develpr\AlexaApp\Http\Middleware\Certificate');
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$kernel = $this->app->make('Illuminate\Contracts\Http\Kernel');

$this->app->instance('app.middleware', $this->gatherAppMiddleware($kernel));

$this->addRequestMiddlewareToBeginning($kernel);

//Register our universal service provider
$this->app->register('Develpr\AlexaApp\Provider\AlexaServiceProvider');
}

class LaravelServiceProvider {

protected function addRequestMiddlewareToBeginning(Kernel $kernel)
{
$kernel->prependMiddleware('Dingo\Api\Http\Middleware\Request');
$kernel->prependMiddleware('Develpr\AlexaApp\Http\Middleware\Request');
}

/**
* Gather the application middleware besides this one so that we can send
* our request through them, exactly how the developer wanted.
*
* @param \Illuminate\Contracts\Http\Kernel $kernel
*
* @return array
*/
protected function gatherAppMiddleware(Kernel $kernel)
{
$reflection = new ReflectionClass($kernel);

$property = $reflection->getProperty('middleware');
$property->setAccessible(true);

$middleware = $property->getValue($kernel);

return $middleware;
}


Expand Down
10 changes: 10 additions & 0 deletions src/Request/NonAlexaRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,15 @@ public function toLaunchRequest()
return null;
}

/**
* Get the unique Application Id
*
* @return mixed
*/
public function getAppId()
{
return null;
}


}

0 comments on commit e8ff4a7

Please sign in to comment.