Skip to content

Commit

Permalink
Added Proxy procedure (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
tabuna authored Nov 6, 2022
1 parent 1a32f25 commit 5f0c31b
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 6 deletions.
27 changes: 24 additions & 3 deletions src/Guide.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,17 @@ public function makeResponse($result = null, Request $request = null): Response
}

/**
* Search for a procedure and execute it.
*
* @param Request $request
* @param bool $notification
*
* @return Response
*/
public function handleProcedure(Request $request, bool $notification): Response
{
\request()->replace($request->getParams()->toArray());
request()->replace($request->getParams()->toArray());
app()->bind(Request::class, fn () => $request);

$procedure = $this->findProcedure($request);

Expand All @@ -117,6 +120,8 @@ public function handleProcedure(Request $request, bool $notification): Response
}

/**
* Find procedure by request.
*
* @param Request $request
*
* @return null|string
Expand All @@ -128,9 +133,25 @@ public function findProcedure(Request $request): ?string

return $this->map
->filter(fn (string $procedure) => $this->getProcedureName($procedure) === $class)
->filter(fn (string $procedure) => method_exists($procedure, $method))
->filter(fn (string $procedure) => $this->checkExistPublicMethod($procedure, $method))
->map(fn (string $procedure) => Str::finish($procedure, self::DEFAULT_DELIMITER.$method))
->whenEmpty(fn (Collection $collection) => $collection->push($this->findProxy($class)))
->first();
}

/**
* Fallback to the first procedure that implements the Proxy interface.
*
* @param string $class
*
* @return null|string
*/
public function findProxy(string $class): ?string
{
return $this->map
->filter(fn (string $procedure) => $this->getProcedureName($procedure) === $class)
->filter(fn (string $procedure) => is_subclass_of($procedure, Proxy::class))
->map(fn (string $procedure) => Str::finish($procedure, self::DEFAULT_DELIMITER.'__invoke'))
->first();
}

Expand All @@ -142,7 +163,7 @@ public function findProcedure(Request $request): ?string
*/
private function checkExistPublicMethod(string $procedure, string $method): bool
{
return (new ReflectionMethod($procedure, $method))->isPublic();
return method_exists($procedure, $method) && (new ReflectionMethod($procedure, $method))->isPublic();
}

/**
Expand Down
19 changes: 19 additions & 0 deletions src/Proxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Sajya\Server;

use Sajya\Server\Http\Request;

interface Proxy
{
/**
* The method used by request handlers.
*
* @param \Sajya\Server\Http\Request $request
*
* @return mixed
*/
public function __invoke(Request $request): mixed;
}
5 changes: 5 additions & 0 deletions tests/Expected/Requests/testFindMethod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jsonrpc": "2.0",
"method": "foobar",
"id": "1"
}
2 changes: 1 addition & 1 deletion tests/Expected/Requests/testFindProcedure.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"jsonrpc": "2.0",
"method": "foobar",
"method": "fixture@foobar",
"id": "1"
}
13 changes: 13 additions & 0 deletions tests/Expected/Requests/testProxyMethod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"jsonrpc": "2.0",
"method": "proxy@any",
"params": {
"firstname": "Vere",
"lastname": "Bonilla",
"city": "Padang",
"country": "Jordan",
"countryCode": "BE",
"group": "default"
},
"id": "1"
}
2 changes: 1 addition & 1 deletion tests/Expected/Responses/testBindDeepValue.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "1",
"result": "Alexandr",
"result": "binding@deepValue Alexandr",
"jsonrpc": "2.0"
}
9 changes: 9 additions & 0 deletions tests/Expected/Responses/testFindMethod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found",
"data": null
},
"id": "1"
}
12 changes: 12 additions & 0 deletions tests/Expected/Responses/testProxyMethod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"id": "1",
"result": {
"firstname": "Vere",
"lastname": "Bonilla",
"city": "Padang",
"country": "Jordan",
"countryCode": "BE",
"group": "default"
},
"jsonrpc": "2.0"
}
2 changes: 1 addition & 1 deletion tests/FixtureBindProcedure.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class FixtureBindProcedure extends Procedure
*/
public function deepValue(Request $request, string $nameDeepValue): string
{
return $nameDeepValue;
return $request->getMethod().' '.$nameDeepValue;
}

/**
Expand Down
32 changes: 32 additions & 0 deletions tests/FixtureProxyProcedure.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Sajya\Server\Tests;

use Sajya\Server\Http\Request;
use Sajya\Server\Procedure;
use Sajya\Server\Proxy;

class FixtureProxyProcedure extends Procedure implements Proxy
{
/**
* The name of the procedure that will be
* displayed and taken into account in the search.
*
* @var string
*/
public static string $name = 'proxy';

/**
* The method that will be called if there is no match.
*
* @param \Sajya\Server\Http\Request $request
*
* @return mixed
*/
public function __invoke(Request $request): mixed
{
return $request->getMethod();
}
}
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class TestCase extends \Orchestra\Testbench\TestCase
public array $mapProcedures = [
FixtureProcedure::class,
FixtureBindProcedure::class,
FixtureProxyProcedure::class,
];

/**
Expand Down
4 changes: 4 additions & 0 deletions tests/Unit/ExpectedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public function exampleCalls(): Generator
yield ['testBatchSum'];
yield ['testDelimiter', null, null, 'rpc.delimiter'];
yield ['testDependencyInjection'];
yield ['testFindMethod'];
yield ['testFindProcedure'];
yield ['testInvalidParams'];
yield ['testNotificationSum', static function () {
Expand Down Expand Up @@ -104,6 +105,9 @@ public function exampleCalls(): Generator
yield ['testBindModel', static function () {
RPC::model('fixtureModel', FixtureBind::class);
}];

// Proxy
yield ['testProxyMethod'];
}

/**
Expand Down

0 comments on commit 5f0c31b

Please sign in to comment.