Skip to content

Commit fc2087e

Browse files
authored
Merge pull request #1186 from alissn/AddSchemaAttibutes
feat: Add `route_attributes` support for GraphQL routes
2 parents cefe3fc + 04059c4 commit fc2087e

File tree

6 files changed

+137
-6
lines changed

6 files changed

+137
-6
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ CHANGELOG
33

44
[Next release](https://github.com/rebing/graphql-laravel/compare/9.10.0...master)
55

6+
## Added
7+
- Add `route_attributes` support for GraphQL routes [\#1186 / alissn](https://github.com/rebing/graphql-laravel/pull/1186)
8+
69
2025-05-17, 9.10.0
710
------------------
811

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ config/graphql.php
6363
- [GraphQL resolver middleware](#graphql-resolver-middleware)
6464
- [Schemas](#schemas)
6565
- [Schema classes](#schema-classes)
66+
- [Route attributes](#route-attributes)
6667
- [Creating a query](#creating-a-query)
6768
- [Creating a mutation](#creating-a-mutation)
6869
- [File uploads](#file-uploads)
@@ -275,6 +276,11 @@ them, in addition to the global middleware. For example:
275276
'execution_middleware' => [
276277
\Rebing\GraphQL\Support\ExecutionMiddleware\UnusedVariablesMiddleware::class,
277278
],
279+
// Route attributes applied to the generated HTTP route for this schema
280+
// Example: expose this schema on a dedicated subdomain
281+
'route_attributes' => [
282+
'domain' => 'api.example.com',
283+
],
278284
],
279285
],
280286
```
@@ -284,6 +290,24 @@ which it is accessible. Per the default configuration of `prefix = graphql`, the
284290
_default_ schema is accessible via `/graphql`.
285291

286292

293+
#### Route attributes
294+
295+
You can customize the HTTP route generated for a specific schema using the `route_attributes` key.
296+
This is useful for setting parameters supported by Laravel routes, e.g. a custom `domain`.
297+
298+
```php
299+
'schemas' => [
300+
'with_custom_domain' => [
301+
'query' => [
302+
App\GraphQL\Queries\UsersQuery::class,
303+
],
304+
'middleware' => ['auth:api'],
305+
'route_attributes' => [
306+
'domain' => 'api.example.com',
307+
],
308+
],
309+
]
310+
```
287311

288312

289313
#### Schema classes

config/config.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@
9393

9494
// An array of middlewares, overrides the global ones
9595
'execution_middleware' => null,
96+
97+
// Route attributes applied when generating the HTTP route for this schema
98+
// Example:
99+
// 'route_attributes' => [
100+
// 'domain' => 'api.example.com',
101+
// ]
102+
'route_attributes' => [],
96103
],
97104
],
98105

phpstan-baseline.neon

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -564,12 +564,6 @@ parameters:
564564
count: 1
565565
path: src/Support/UploadType.php
566566

567-
-
568-
message: '#^Offset ''uses'' might not exist on array\{uses\?\: mixed, middleware\?\: mixed\}\.$#'
569-
identifier: offsetAccess.notFound
570-
count: 1
571-
path: src/routes.php
572-
573567
-
574568
message: '#^Property Rebing\\GraphQL\\Tests\\Database\\AuthorizeArgsTests\\GraphQLContext\:\:\$data has no type specified\.$#'
575569
identifier: missingType.property

src/routes.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ function (Router $router) use ($config, $routeConfig): void {
3636
$actions = array_filter([
3737
'uses' => $schemaConfig['controller'] ?? $routeConfig['controller'] ?? GraphQLController::class . '@query',
3838
'middleware' => $schemaConfig['middleware'] ?? $routeConfig['middleware'] ?? null,
39+
...$schemaConfig['route_attributes'] ?? [],
3940
]);
4041

4142
// Support array syntax: `[Some::class, 'method']`

tests/Unit/RouteWithSchemaTest.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
namespace Rebing\GraphQL\Tests\Unit;
5+
6+
use Illuminate\Routing\Route;
7+
use Illuminate\Support\Collection;
8+
use Rebing\GraphQL\Tests\Support\Objects\ExampleMiddleware;
9+
use Rebing\GraphQL\Tests\TestCase;
10+
11+
class RouteWithSchemaTest extends TestCase
12+
{
13+
protected function getEnvironmentSetUp($app): void
14+
{
15+
// Laravel registers routes for local filesystems by default.
16+
// However, for the purpose of this test, we don't want it to register any routes.
17+
$app['config']->set('filesystems.disks.local.serve', false);
18+
19+
$app['config']->set('graphql', [
20+
'route' => [
21+
'prefix' => 'graphql_test',
22+
],
23+
24+
'schemas' => [
25+
'default' => [
26+
'middleware' => [ExampleMiddleware::class],
27+
],
28+
'with_route_attributes' => [
29+
'middleware' => [ExampleMiddleware::class],
30+
'route_attributes' => [
31+
'domain' => 'api.example.com',
32+
],
33+
],
34+
],
35+
]);
36+
}
37+
38+
public function testRoutesWithSchemaAttributes(): void
39+
{
40+
$expected = [
41+
'graphql' => [
42+
'methods' => [
43+
'GET',
44+
'POST',
45+
'HEAD',
46+
],
47+
'uri' => 'graphql_test',
48+
'middleware' => [
49+
ExampleMiddleware::class,
50+
],
51+
'domain' => null,
52+
'action_middleware' => [ExampleMiddleware::class],
53+
'action_excluded_middleware' => [],
54+
],
55+
'graphql.default' => [
56+
'methods' => [
57+
'GET',
58+
'POST',
59+
'HEAD',
60+
],
61+
'uri' => 'graphql_test/default',
62+
'middleware' => [
63+
ExampleMiddleware::class,
64+
],
65+
'domain' => null,
66+
'action_middleware' => [ExampleMiddleware::class],
67+
'action_excluded_middleware' => [],
68+
],
69+
'graphql.with_route_attributes' => [
70+
'methods' => [
71+
'GET',
72+
'POST',
73+
'HEAD',
74+
],
75+
'uri' => 'graphql_test/with_route_attributes',
76+
'middleware' => [
77+
ExampleMiddleware::class,
78+
],
79+
'domain' => 'api.example.com',
80+
'action_middleware' => [ExampleMiddleware::class],
81+
'action_excluded_middleware' => [],
82+
],
83+
];
84+
85+
$actual = Collection::make(
86+
app('router')->getRoutes()->getRoutesByName()
87+
)->map(function (Route $route) {
88+
$action = $route->getAction();
89+
90+
return [
91+
'methods' => $route->methods(),
92+
'uri' => $route->uri(),
93+
'middleware' => $route->middleware(),
94+
'domain' => $route->getDomain(),
95+
'action_middleware' => $action['middleware'] ?? [],
96+
'action_excluded_middleware' => $action['excluded_middleware'] ?? [],
97+
];
98+
})->all();
99+
100+
self::assertEquals($expected, $actual);
101+
}
102+
}

0 commit comments

Comments
 (0)