Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for route parameters #1067

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
19 changes: 19 additions & 0 deletions src/GraphQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Pipeline\Pipeline;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Validation\ValidationException;
use Rebing\GraphQL\Error\AuthorizationError;
Expand Down Expand Up @@ -657,6 +658,24 @@
return $schemaConfig;
}

public static function parseRoute(string $schemaName, array $schemaConfig, array $routeConfig, ?string $alias = null): \Illuminate\Routing\Route

Check failure on line 661 in src/GraphQL.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Rebing\GraphQL\GraphQL::parseRoute() has parameter $routeConfig with no value type specified in iterable type array.

Check failure on line 661 in src/GraphQL.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Rebing\GraphQL\GraphQL::parseRoute() has parameter $schemaConfig with no value type specified in iterable type array.
{
if (null !== $alias) {
$routeName = $alias ? ".$alias" : '';
} else {
$routeName = $schemaName ? ".$schemaName" : '';
}

return Route::match(
$schemaConfig['method'] ?? ['GET', 'POST'],
$alias ?? $schemaName,
$schemaConfig['controller'] ?? $routeConfig['controller'] ?? [GraphQLController::class, 'query'],
)->middleware(array_merge(
[GraphQLHttpMiddleware::class . ":$schemaName"],
$schemaConfig['middleware'] ?? []
))->name($routeName);
}

public function decorateExecutionResult(ExecutionResult $executionResult): ExecutionResult
{
$errorFormatter = $this->config->get('graphql.error_formatter', [static::class, 'formatError']);
Expand Down
16 changes: 1 addition & 15 deletions src/GraphQLController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Str;
use Laragraph\Utils\RequestParser;
use Rebing\GraphQL\Support\OperationParams;

class GraphQLController extends Controller
{
public function query(Request $request, RequestParser $parser, Repository $config, GraphQL $graphql): JsonResponse
{
$routePrefix = $config->get('graphql.route.prefix', 'graphql');
$schemaName = $this->findSchemaNameInRequest($request, "/$routePrefix") ?: $config->get('graphql.default_schema', 'default');

$schemaName = $request->server('graphql.schemaName');
$operations = $parser->parseRequest($request);

$headers = $config->get('graphql.headers', []);
Expand All @@ -38,7 +35,7 @@
function (BaseOperationParams $baseOperationParams) use ($schemaName, $graphql): array {
$operationParams = new OperationParams($baseOperationParams);

return $graphql->execute($schemaName, $operationParams);

Check failure on line 38 in src/GraphQLController.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Parameter #1 $schemaName of method Rebing\GraphQL\GraphQL::execute() expects string, array|string|null given.
},
$operations
);
Expand Down Expand Up @@ -73,15 +70,4 @@

return $data;
}

protected function findSchemaNameInRequest(Request $request, string $routePrefix): ?string
{
$path = $request->getPathInfo();

if (!Str::startsWith($path, $routePrefix)) {
return null;
}

return trim(Str::after($path, $routePrefix), '/');
}
}
22 changes: 22 additions & 0 deletions src/GraphQLHttpMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
declare(strict_types = 1);
namespace Rebing\GraphQL;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class GraphQLHttpMiddleware
{
/**
* Inject schemaName in server request.
*
* @param Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, string $schemaName): Response
{
$request->server->set('graphql.schemaName', $schemaName);

return $next($request);
}
}
74 changes: 19 additions & 55 deletions src/routes.php
Original file line number Diff line number Diff line change
@@ -1,64 +1,28 @@
<?php

Check failure on line 1 in src/routes.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Ignored error pattern #^Offset 'uses' might not exist on array\{uses\?\: mixed, middleware\?\: mixed\}\.$# in path /home/runner/work/graphql-laravel/graphql-laravel/src/routes.php was not matched in reported errors.

declare(strict_types = 1);

use Illuminate\Container\Container;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
use Rebing\GraphQL\GraphQL;
use Rebing\GraphQL\GraphQLController;

/** @var Repository $config */
$config = Container::getInstance()->make(Repository::class);
$routeConfig = config('graphql.route');

$routeConfig = $config->get('graphql.route');

if ($routeConfig) {
/** @var Router $router */
$router = app('router');

$routeGroupAttributes = array_merge(
[
'prefix' => $routeConfig['prefix'] ?? 'graphql',
'middleware' => $routeConfig['middleware'] ?? [],
],
$routeConfig['group_attributes'] ?? []
);

$router->group(
$routeGroupAttributes,
function (Router $router) use ($config, $routeConfig): void {
$schemas = GraphQL::getNormalizedSchemasConfiguration();
$defaultSchema = $config->get('graphql.default_schema', 'default');

foreach ($schemas as $schemaName => $schemaConfig) {
$method = $schemaConfig['method'] ?? ['GET', 'POST'];
$actions = array_filter([
'uses' => $schemaConfig['controller'] ?? $routeConfig['controller'] ?? GraphQLController::class . '@query',
'middleware' => $schemaConfig['middleware'] ?? $routeConfig['middleware'] ?? null,
]);

// Support array syntax: `[Some::class, 'method']`
if (\is_array($actions['uses']) && isset($actions['uses'][0], $actions['uses'][1])) {
$actions['uses'] = $actions['uses'][0] . '@' . $actions['uses'][1];
}

// Add route for each schema…
$router->addRoute(
$method,
$schemaName,
$actions + ['as' => "graphql.$schemaName"]
);
if (empty($routeConfig)) {
return;
}

// … and the default schema against the group itself
if ($schemaName === $defaultSchema) {
$router->addRoute(
$method,
'',
$actions + ['as' => 'graphql']
);
}
}
$defaultSchemaName = config('graphql.default_schema', 'default');
Route::group([
'prefix' => $routeConfig['prefix'] ?? 'graphql',
'middleware' => $routeConfig['middleware'] ?? [],
'as' => 'graphql',
...$routeConfig['group_attributes'] ?? [],
], function () use (&$defaultSchemaName, &$routeConfig): void {
foreach (GraphQL::getNormalizedSchemasConfiguration() as $schemaName => $schemaConfig) {
GraphQL::parseRoute($schemaName, $schemaConfig, $routeConfig);

if ($schemaName === $defaultSchemaName) {
GraphQL::parseRoute($schemaName, $schemaConfig, $routeConfig, '');
}
);
}
}
});
42 changes: 42 additions & 0 deletions tests/Unit/EndpointParamsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types = 1);
namespace Rebing\GraphQL\Tests\Unit;

use Rebing\GraphQL\Tests\TestCase;

class EndpointParamsTest extends TestCase
{
public function testGetDefaultSchemaWithRouteParameter(): void
{
$response = $this->call('GET', '/graphql/arbitrary_param', [
'query' => $this->queries['examples'],
]);

self::assertEquals(200, $response->getStatusCode());

$content = $response->getData(true);
self::assertArrayHasKey('data', $content);
self::assertEquals($content['data'], [
'examples' => $this->data,
]);
}
public function testGetCustomSchemaWithRouteParameter(): void
{
$response = $this->call('GET', '/graphql/arbitrary_param/custom', [
'query' => $this->queries['examplesCustom'],
]);
self::assertEquals(200, $response->getStatusCode());
$content = $response->getData(true);
self::assertArrayHasKey('data', $content);
self::assertEquals($content['data'], [
'examplesCustom' => $this->data,
]);
}

protected function getEnvironmentSetUp($app): void
{
parent::getEnvironmentSetUp($app);
$app['config']->set('graphql.route.prefix', 'graphql/{parameter}');
}
}
7 changes: 7 additions & 0 deletions tests/Unit/RoutesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use Illuminate\Routing\Route;
use Illuminate\Support\Collection;
use Rebing\GraphQL\GraphQLHttpMiddleware;
use Rebing\GraphQL\Tests\Support\Objects\ExampleMiddleware;
use Rebing\GraphQL\Tests\Support\Objects\ExampleSchema;
use Rebing\GraphQL\Tests\Support\Objects\ExampleSchemaWithMethod;
Expand Down Expand Up @@ -47,6 +48,7 @@ public function testRoutes(): void
],
'uri' => 'graphql_test',
'middleware' => [
GraphQLHttpMiddleware::class . ':default',
ExampleMiddleware::class,
],
],
Expand All @@ -58,6 +60,7 @@ public function testRoutes(): void
],
'uri' => 'graphql_test/default',
'middleware' => [
GraphQLHttpMiddleware::class . ':default',
ExampleMiddleware::class,
],
],
Expand All @@ -69,6 +72,7 @@ public function testRoutes(): void
],
'uri' => 'graphql_test/custom',
'middleware' => [
GraphQLHttpMiddleware::class . ':custom',
ExampleMiddleware::class,
],
],
Expand All @@ -78,6 +82,7 @@ public function testRoutes(): void
],
'uri' => 'graphql_test/with_methods',
'middleware' => [
GraphQLHttpMiddleware::class . ':with_methods',
ExampleMiddleware::class,
],
],
Expand All @@ -89,6 +94,7 @@ public function testRoutes(): void
],
'uri' => 'graphql_test/class_based',
'middleware' => [
GraphQLHttpMiddleware::class . ':class_based',
ExampleMiddleware::class,
],
],
Expand All @@ -98,6 +104,7 @@ public function testRoutes(): void
],
'uri' => 'graphql_test/class_based_with_methods',
'middleware' => [
GraphQLHttpMiddleware::class . ':class_based_with_methods',
ExampleMiddleware::class,
],
],
Expand Down
Loading