Skip to content

Commit 5c920d5

Browse files
authored
Merge pull request #65 from mcg-web/multiple_endpoints
Enable multiple schema
2 parents 0ef2a6b + 5a02c2b commit 5c920d5

File tree

12 files changed

+234
-53
lines changed

12 files changed

+234
-53
lines changed

Controller/GraphController.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,44 @@
1717

1818
class GraphController extends Controller
1919
{
20-
public function endpointAction(Request $request)
20+
public function endpointAction(Request $request, $schemaName = null)
2121
{
22-
$payload = $this->processNormalQuery($request);
22+
$payload = $this->processNormalQuery($request, $schemaName);
2323

2424
return new JsonResponse($payload, 200);
2525
}
2626

27-
public function batchEndpointAction(Request $request)
27+
public function batchEndpointAction(Request $request, $schemaName = null)
2828
{
29-
$payloads = $this->processBatchQuery($request);
29+
$payloads = $this->processBatchQuery($request, $schemaName);
3030

3131
return new JsonResponse($payloads, 200);
3232
}
3333

34-
private function processBatchQuery(Request $request)
34+
private function processBatchQuery(Request $request, $schemaName = null)
3535
{
3636
$queries = $this->get('overblog_graphql.request_batch_parser')->parse($request);
3737
$payloads = [];
3838

3939
foreach ($queries as $query) {
40-
$payloadResult = $this->get('overblog_graphql.request_executor')->execute([
41-
'query' => $query['query'],
42-
'variables' => $query['variables'],
43-
]);
40+
$payloadResult = $this->get('overblog_graphql.request_executor')->execute(
41+
[
42+
'query' => $query['query'],
43+
'variables' => $query['variables'],
44+
],
45+
[],
46+
$schemaName
47+
);
4448
$payloads[] = ['id' => $query['id'], 'payload' => $payloadResult->toArray()];
4549
}
4650

4751
return $payloads;
4852
}
4953

50-
private function processNormalQuery(Request $request)
54+
private function processNormalQuery(Request $request, $schemaName = null)
5155
{
5256
$params = $this->get('overblog_graphql.request_parser')->parse($request);
53-
$data = $this->get('overblog_graphql.request_executor')->execute($params)->toArray();
57+
$data = $this->get('overblog_graphql.request_executor')->execute($params, [], $schemaName)->toArray();
5458

5559
return $data;
5660
}

Controller/GraphiQLController.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@
1515

1616
class GraphiQLController extends Controller
1717
{
18-
public function indexAction()
18+
public function indexAction($schemaName = null)
1919
{
20+
if (null === $schemaName) {
21+
$endpoint = $this->generateUrl('overblog_graphql_endpoint');
22+
} else {
23+
$endpoint = $this->generateUrl('overblog_graphql_multiple_endpoint', ['schemaName' => $schemaName]);
24+
}
25+
2026
return $this->render(
2127
$this->getParameter('overblog_graphql.graphiql_template'),
2228
[
23-
'endpoint' => $this->generateUrl('overblog_graphql_endpoint'),
29+
'endpoint' => $endpoint,
2430
'versions' => [
2531
'graphiql' => $this->getParameter('overblog_graphql.versions.graphiql'),
2632
'react' => $this->getParameter('overblog_graphql.versions.react'),

DependencyInjection/Configuration.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,26 @@ public function getConfigTreeBuilder()
4646
->scalarNode('internal_error_message')->defaultNull()->end()
4747
->booleanNode('config_validation')->defaultValue($this->debug)->end()
4848
->arrayNode('schema')
49-
->addDefaultsIfNotSet()
50-
->children()
51-
->scalarNode('query')->defaultNull()->end()
52-
->scalarNode('mutation')->defaultNull()->end()
53-
->scalarNode('subscription')->defaultNull()->end()
49+
->beforeNormalization()
50+
->ifTrue(function ($v) {
51+
$needNormalization = isset($v['query']) && is_string($v['query']) ||
52+
isset($v['mutation']) && is_string($v['mutation']) ||
53+
isset($v['subscription']) && is_string($v['subscription']);
54+
55+
return $needNormalization;
56+
})
57+
->then(function ($v) {
58+
return ['default' => $v];
59+
})
60+
->end()
61+
->useAttributeAsKey('name')
62+
->prototype('array')
63+
->addDefaultsIfNotSet()
64+
->children()
65+
->scalarNode('query')->defaultNull()->end()
66+
->scalarNode('mutation')->defaultNull()->end()
67+
->scalarNode('subscription')->defaultNull()->end()
68+
->end()
5469
->end()
5570
->end()
5671
->arrayNode('mappings')
@@ -142,8 +157,8 @@ public function getConfigTreeBuilder()
142157
->arrayNode('versions')
143158
->addDefaultsIfNotSet()
144159
->children()
145-
->scalarNode('graphiql')->defaultValue('0.7.1')->end()
146-
->scalarNode('react')->defaultValue('15.0.2')->end()
160+
->scalarNode('graphiql')->defaultValue('0.7.8')->end()
161+
->scalarNode('react')->defaultValue('15.3.2')->end()
147162
->end()
148163
->end()
149164
->end();

DependencyInjection/OverblogGraphQLExtension.php

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
use Overblog\GraphQLBundle\Config\TypeWithOutputFieldsDefinition;
1515
use Symfony\Component\Config\FileLocator;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Definition;
1718
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
1819
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
20+
use Symfony\Component\DependencyInjection\Reference;
1921
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
2022

2123
class OverblogGraphQLExtension extends Extension implements PrependExtensionInterface
@@ -120,13 +122,18 @@ private function setSchemaBuilderArguments(array $config, ContainerBuilder $cont
120122
private function setSchemaArguments(array $config, ContainerBuilder $container)
121123
{
122124
if (isset($config['definitions']['schema'])) {
123-
$container
124-
->getDefinition($this->getAlias().'.schema')
125-
->replaceArgument(0, $config['definitions']['schema']['query'])
126-
->replaceArgument(1, $config['definitions']['schema']['mutation'])
127-
->replaceArgument(2, $config['definitions']['schema']['subscription'])
128-
->setPublic(true)
129-
;
125+
$executorDefinition = $container->getDefinition($this->getAlias().'.request_executor');
126+
127+
foreach ($config['definitions']['schema'] as $schemaName => $schemaConfig) {
128+
$schemaID = sprintf('%s.schema_%s', $this->getAlias(), $schemaName);
129+
$definition = new Definition('GraphQL\Schema');
130+
$definition->setFactory([new Reference('overblog_graphql.schema_builder'), 'create']);
131+
$definition->setArguments([$schemaConfig['query'], $schemaConfig['mutation'], $schemaConfig['subscription']]);
132+
$definition->setPublic(false);
133+
$container->setDefinition($schemaID, $definition);
134+
135+
$executorDefinition->addMethodCall('addSchema', [$schemaName, new Reference($schemaID)]);
136+
}
130137
}
131138
}
132139

@@ -153,7 +160,7 @@ public function getConfiguration(array $config, ContainerBuilder $container)
153160
/**
154161
* Returns a list of custom exceptions mapped to error/warning classes.
155162
*
156-
* @param array $config
163+
* @param array $exceptionConfig
157164
* @return array Custom exception map, [exception => UserError/UserWarning].
158165
*/
159166
private function buildExceptionMap(array $exceptionConfig)

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,38 @@ Batching
903903
Batching can help decrease io between server and client.
904904
The default route of batching is `/batch`.
905905

906+
Multiple schema endpoint
907+
------------------------
908+
909+
```yaml
910+
#app/config/config.yml
911+
912+
overblog_graphql:
913+
definitions:
914+
schema:
915+
foo:
916+
query: fooQuery
917+
bar:
918+
query: barQuery
919+
mutation: barMutation
920+
```
921+
922+
**foo** schema endpoint can be access:
923+
924+
type | Path
925+
-----| -----
926+
simple request | `/graphql/foo`
927+
batch request | `/graphql/foo/batch`
928+
graphiQL | `/graphiql/foo`
929+
930+
**bar** schema endpoint can be access:
931+
932+
type | Path
933+
-----| -----
934+
simple request | `/graphql/bar`
935+
batch request | `/graphql/bar/batch`
936+
graphiQL | `/graphiql/bar`
937+
906938
Contribute
907939
----------
908940

Request/Executor.php

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020
use Overblog\GraphQLBundle\Event\Events;
2121
use Overblog\GraphQLBundle\Event\ExecutorContextEvent;
2222
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
23+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
2324

2425
class Executor
2526
{
26-
private $schema;
27+
/**
28+
* @var Schema[]
29+
*/
30+
private $schemas;
2731

2832
/**
2933
* @var EventDispatcherInterface|null
@@ -36,14 +40,20 @@ class Executor
3640
/** @var ErrorHandler|null */
3741
private $errorHandler;
3842

39-
public function __construct(Schema $schema, EventDispatcherInterface $dispatcher = null, $throwException = false, ErrorHandler $errorHandler = null)
43+
public function __construct(EventDispatcherInterface $dispatcher = null, $throwException = false, ErrorHandler $errorHandler = null)
4044
{
41-
$this->schema = $schema;
4245
$this->dispatcher = $dispatcher;
4346
$this->throwException = (bool) $throwException;
4447
$this->errorHandler = $errorHandler;
4548
}
4649

50+
public function addSchema($name, Schema $schema)
51+
{
52+
$this->schemas[$name] = $schema;
53+
54+
return $this;
55+
}
56+
4757
public function setMaxQueryDepth($maxQueryDepth)
4858
{
4959
/** @var QueryDepth $queryDepth */
@@ -70,16 +80,18 @@ public function setThrowException($throwException)
7080
return $this;
7181
}
7282

73-
public function execute(array $data, array $context = [])
83+
public function execute(array $data, array $context = [], $schemaName = null)
7484
{
7585
if (null !== $this->dispatcher) {
7686
$event = new ExecutorContextEvent($context);
7787
$this->dispatcher->dispatch(Events::EXECUTOR_CONTEXT, $event);
7888
$context = $event->getExecutorContext();
7989
}
8090

91+
$schema = $this->getSchema($schemaName);
92+
8193
$executionResult = GraphQL::executeAndReturnResult(
82-
$this->schema,
94+
$schema,
8395
isset($data[ParserInterface::PARAM_QUERY]) ? $data[ParserInterface::PARAM_QUERY] : null,
8496
$context,
8597
$context,
@@ -93,4 +105,27 @@ public function execute(array $data, array $context = [])
93105

94106
return $executionResult;
95107
}
108+
109+
/**
110+
* @param string|null $name
111+
*
112+
* @return Schema
113+
*/
114+
public function getSchema($name = null)
115+
{
116+
if (empty($this->schemas)) {
117+
throw new \RuntimeException('At least one schema should be declare.');
118+
}
119+
120+
if (null === $name) {
121+
$schema = array_values($this->schemas)[0];
122+
} else {
123+
if (!isset($this->schemas[$name])) {
124+
throw new NotFoundHttpException(sprintf('Could not found "%s" schema.', $name));
125+
}
126+
$schema = $this->schemas[$name];
127+
}
128+
129+
return $schema;
130+
}
96131
}

Resources/config/routing/graphiql.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@ overblog_graphql_graphiql:
22
path: /graphiql
33
defaults:
44
_controller: OverblogGraphQLBundle:GraphiQL:index
5+
6+
overblog_graphql_graphiql_multiple:
7+
path: /graphiql/{schemaName}
8+
defaults:
9+
_controller: OverblogGraphQLBundle:GraphiQL:index

Resources/config/routing/graphql.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,15 @@ overblog_graphql_batch_endpoint:
99
defaults:
1010
_controller: OverblogGraphQLBundle:Graph:batchEndpoint
1111
_format: "json"
12+
13+
overblog_graphql_multiple_endpoint:
14+
path: /graphql/{schemaName}
15+
defaults:
16+
_controller: OverblogGraphQLBundle:Graph:endpoint
17+
_format: "json"
18+
19+
overblog_graphql_batch_multiple_endpoint:
20+
path: /graphql/{schemaName}/batch
21+
defaults:
22+
_controller: OverblogGraphQLBundle:Graph:batchEndpoint
23+
_format: "json"

Resources/config/services.yml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ services:
1414
overblog_graphql.request_executor:
1515
class: Overblog\GraphQLBundle\Request\Executor
1616
arguments:
17-
- "@overblog_graphql.schema"
1817
- "@event_dispatcher"
1918
- "%kernel.debug%"
2019
- "@overblog_graphql.error_handler"
@@ -28,15 +27,6 @@ services:
2827
overblog_graphql.request_batch_parser:
2928
class: Overblog\GraphQLBundle\Request\BatchParser
3029

31-
overblog_graphql.schema:
32-
class: GraphQL\Schema
33-
public: false
34-
factory: ["@overblog_graphql.schema_builder", create]
35-
arguments:
36-
- ~
37-
- ~
38-
- ~
39-
4030
overblog_graphql.schema_builder:
4131
class: Overblog\GraphQLBundle\Definition\Builder\SchemaBuilder
4232
public: false

0 commit comments

Comments
 (0)