Skip to content

Commit

Permalink
Support middleware invoker.
Browse files Browse the repository at this point in the history
  • Loading branch information
youmingdot committed Aug 22, 2018
1 parent f98d03a commit 16f729d
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 8 deletions.
64 changes: 64 additions & 0 deletions src/Homer/Calling/Invokers/MiddlewareInvoker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
namespace Lawoole\Homer\Calling\Invokers;

use Lawoole\Homer\Calling\Invocation;
use Lawoole\Homer\Calling\Pipeline;

class MiddlewareInvoker extends Invoker
{
/**
* The container implementation.
*
* @var \Illuminate\Contracts\Container\Container
*/
protected $container;

/**
* The invoker to be called.
*
* @var \Lawoole\Homer\Calling\Invokers\Invoker
*/
protected $invoker;

/**
* The middleware for the invoker.
*
* @var array
*/
protected $middleware;

/**
* Create a concrete invoker instance.
*
* @param \Illuminate\Contracts\Container\Container $container
* @param string $interface
* @param \Lawoole\Homer\Calling\Invokers\Invoker $invoker
* @param array $middleware
* @param array $options
*/
public function __construct($container, $interface, $invoker, $middleware, array $options = [])
{
parent::__construct($interface, $options);

$this->container = $container;
$this->invoker = $invoker;
$this->middleware = $middleware;
}

/**
* Do invoking and get the result.
*
* @param \Lawoole\Homer\Calling\Invocation $invocation
*
* @return \Lawoole\Homer\Calling\Result
*/
protected function doInvoke(Invocation $invocation)
{
return (new Pipeline($this->container))
->send($invocation)
->through($this->middleware)
->then(function ($invocation) {
return $this->invoker->invoke($invocation);
});
}
}
79 changes: 79 additions & 0 deletions src/Homer/Calling/Pipeline.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
namespace Lawoole\Homer\Calling;

use Closure;
use Exception;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Pipeline\Pipeline as BasePipeline;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Throwable;

class Pipeline extends BasePipeline
{
/**
* {@inheritdoc}
*/
protected function prepareDestination(Closure $destination)
{
return function ($passable) use ($destination) {
try {
return $destination($passable);
} catch (Exception $e) {
return $this->handleException($passable, $e);
} catch (Throwable $e) {
return $this->handleException($passable, new FatalThrowableError($e));
}
};
}

/**
* {@inheritdoc}
*/
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
try {
$slice = parent::carry();

$callable = $slice($stack, $pipe);

return $callable($passable);
} catch (Exception $e) {
return $this->handleException($passable, $e);
} catch (Throwable $e) {
return $this->handleException($passable, new FatalThrowableError($e));
}
};
};
}

/**
* Handle the given exception.
*
* @param mixed $passable
* @param \Exception $e
*
* @return mixed
*/
protected function handleException($passable, Exception $e)
{
$handler = $this->container->make(ExceptionHandler::class);

$handler->report($e);

return $this->createExceptionResult($e);
}

/**
* Create an excepted calling result.
*
* @param \Throwable $e
*
* @return \Lawoole\Homer\Calling\Result
*/
protected function createExceptionResult($e)
{
return new Result(null, $e);
}
}
40 changes: 40 additions & 0 deletions src/Homer/Components/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Lawoole\Homer\Components;

use Illuminate\Contracts\Container\Container;
use Lawoole\Homer\Calling\Invokers\MiddlewareInvoker;

abstract class Component
{
Expand All @@ -12,6 +13,13 @@ abstract class Component
*/
protected $container;

/**
* The invoking middleware.
*
* @var array
*/
protected $middleware;

/**
* The component config.
*
Expand All @@ -30,4 +38,36 @@ public function __construct(Container $container, array $config = [])
$this->container = $container;
$this->config = $config;
}

/**
* The invoking middleware.
*
* @param array $middleware
*
* @return $this
*/
public function setMiddleware(array $middleware)
{
$this->middleware = $middleware;

return $this;
}

/**
* Add middleware to the invoker.
*
* @param \Lawoole\Homer\Calling\Invokers\Invoker $invoker
* @param string $interface
* @param array $config
*
* @return \Lawoole\Homer\Calling\Invokers\Invoker
*/
protected function withMiddleware($invoker, $interface, $config)
{
if (empty($this->middleware)) {
return $invoker;
}

return new MiddlewareInvoker($this->container, $interface, $invoker, $this->middleware, $config);
}
}
2 changes: 2 additions & 0 deletions src/Homer/Components/ReferenceComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ protected function createProxy()

$invoker = new RemoteInvoker($this->context, $client, $interface, $config);

$invoker = $this->withMiddleware($invoker, $interface, $config);

return $this->proxyFactory->proxy($invoker);
}
}
4 changes: 3 additions & 1 deletion src/Homer/Components/ServiceComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ protected function createInvoker()
$interface = Arr::pull($config, 'interface');
$concrete = Arr::pull($config, 'refer', $interface);

return new ConcreteInvoker($this->context, $interface, $concrete, $config);
$invoker = new ConcreteInvoker($this->context, $interface, $concrete, $config);

return $this->withMiddleware($invoker, $interface, $config);
}
}
30 changes: 30 additions & 0 deletions src/Homer/HomerManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Lawoole\Homer;

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use InvalidArgumentException;
use Lawoole\Contracts\Homer\Homer as HomerContract;
use Lawoole\Contracts\Homer\Registrar;
Expand Down Expand Up @@ -106,6 +107,23 @@ public function boot()
$this->resolveReferences();
}

/**
* Gather the middleware for the invoker with resolved class names.
*
* @param array $middleware
*
* @return array
*/
protected function gatherInvokerMiddleware($middleware)
{
$nameMiddleware = $this->config['name_middleware'] ?? [];
$middlewareGroups = $this->config['middleware_groups'] ?? [];

return Collection::make($middleware)->map(function ($middleware) use ($nameMiddleware, $middlewareGroups) {
return (array) MiddlewareNameResolver::resolve($middleware, $nameMiddleware, $middlewareGroups);
})->flatten()->all();
}

/**
* Resolve and register all configured services.
*/
Expand Down Expand Up @@ -134,9 +152,15 @@ protected function resolveServices()
*/
public function resolveService(array $config)
{
$middleware = $this->gatherInvokerMiddleware(array_merge(
$this->config['middleware'] ?? [],
$config['middleware'] ?? []
));

return (new ServiceComponent($this->app, $config))
->setContext($this->context)
->setDispatcher($this->dispatcher)
->setMiddleware($middleware)
->export();
}

Expand Down Expand Up @@ -167,10 +191,16 @@ public function resolveReference(array $config)
{
$config = $this->normalizeClientConfig($config);

$middleware = $this->gatherInvokerMiddleware(array_merge(
$config['client']['middleware'] ?? [],
$config['middleware'] ?? []
));

return (new ReferenceComponent($this->app, $config))
->setContext($this->context)
->setProxyFactory($this->proxyFactory)
->setClientFactory($this->clientFactory)
->setMiddleware($middleware)
->refer();
}

Expand Down
73 changes: 73 additions & 0 deletions src/Homer/MiddlewareNameResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
namespace Lawoole\Homer;

use Closure;

class MiddlewareNameResolver
{
/**
* Resolve the middleware name to a class name(s) preserving passed parameters.
*
* @param string $name
* @param array $nameMiddleware
* @param array $middlewareGroups
*
* @return \Closure|string|array
*/
public static function resolve($name, $nameMiddleware, $middlewareGroups)
{
if ($name instanceof Closure) {
return $name;
}

if (isset($nameMiddleware[$name]) && $nameMiddleware[$name] instanceof Closure) {
return $nameMiddleware[$name];
}

if (isset($middlewareGroups[$name])) {
return static::parseMiddlewareGroup($name, $nameMiddleware, $middlewareGroups);
}

[$middleware, $parameters] = array_pad(explode(':', $name, 2), 2, null);

if (isset($nameMiddleware[$middleware])) {
$middleware = $nameMiddleware[$middleware];
}

return $middleware.($parameters ? ':'.$parameters : '');
}

/**
* Parse the middleware group and format it for usage.
*
* @param string $name
* @param array $nameMiddleware
* @param array $middlewareGroups
*
* @return array
*/
protected static function parseMiddlewareGroup($name, $nameMiddleware, $middlewareGroups)
{
$results = [];

foreach ($middlewareGroups[$name] as $middleware) {
if (isset($middlewareGroups[$middleware])) {
$results = array_merge($results, static::parseMiddlewareGroup(
$middleware, $nameMiddleware, $middlewareGroups
));

continue;
}

[$middleware, $parameters] = array_pad(explode(':', $middleware, 2), 2, null);

if (isset($nameMiddleware[$middleware])) {
$middleware = $nameMiddleware[$middleware];
}

$results[] = $middleware.($parameters ? ':'.$parameters : '');
}

return $results;
}
}
8 changes: 1 addition & 7 deletions src/Homer/Transport/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ protected function getClientKey(array $config)
{
$url = Arr::pull($config, 'url');

$parameters = array_map(function ($value) {
return is_bool($value) ? var_export($value, true) : (string) $value;
}, $config);

ksort($parameters);

return $url.'?'.http_build_query($parameters);
return $url.':'.json_encode($config);
}
}

0 comments on commit 16f729d

Please sign in to comment.