Skip to content

Commit 6e47bba

Browse files
authored
Add possibility to change GraphiQL path and default IDE for the entrypoint (#2956)
1 parent 9aba732 commit 6e47bba

File tree

20 files changed

+231
-65
lines changed

20 files changed

+231
-65
lines changed

src/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ final class SwaggerUiAction
5454
private $swaggerUiEnabled;
5555
private $reDocEnabled;
5656
private $graphqlEnabled;
57+
private $graphiQlEnabled;
5758

58-
public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '', string $version = '', $formats = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthScopes = [], bool $showWebby = true, bool $swaggerUiEnabled = false, bool $reDocEnabled = false, bool $graphqlEnabled = false)
59+
public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '', string $version = '', $formats = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthScopes = [], bool $showWebby = true, bool $swaggerUiEnabled = false, bool $reDocEnabled = false, bool $graphqlEnabled = false, bool $graphiQlEnabled = false)
5960
{
6061
$this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
6162
$this->resourceMetadataFactory = $resourceMetadataFactory;
@@ -77,6 +78,7 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName
7778
$this->swaggerUiEnabled = $swaggerUiEnabled;
7879
$this->reDocEnabled = $reDocEnabled;
7980
$this->graphqlEnabled = $graphqlEnabled;
81+
$this->graphiQlEnabled = $graphiQlEnabled;
8082

8183
if (\is_array($formats)) {
8284
$this->formats = $formats;
@@ -119,6 +121,7 @@ private function getContext(Request $request, Documentation $documentation): arr
119121
'swaggerUiEnabled' => $this->swaggerUiEnabled,
120122
'reDocEnabled' => $this->reDocEnabled,
121123
'graphqlEnabled' => $this->graphqlEnabled,
124+
'graphiQlEnabled' => $this->graphiQlEnabled,
122125
];
123126

124127
$swaggerContext = ['spec_version' => $request->query->getInt('spec_version', 2)];

src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,12 +369,13 @@ private function registerGraphQlConfiguration(ContainerBuilder $container, array
369369
$enabled = $this->isConfigEnabled($container, $config['graphql']);
370370

371371
$container->setParameter('api_platform.graphql.enabled', $enabled);
372+
$container->setParameter('api_platform.graphql.graphiql.enabled', $enabled && $this->isConfigEnabled($container, $config['graphql']['graphiql']));
372373

373374
if (!$enabled) {
374375
return;
375376
}
376377

377-
$container->setParameter('api_platform.graphql.graphiql.enabled', $this->isConfigEnabled($container, $config['graphql']['graphiql']));
378+
$container->setParameter('api_platform.graphql.default_ide', $config['graphql']['default_ide']);
378379

379380
$loader->load('graphql.xml');
380381

src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ private function addGraphQlSection(ArrayNodeDefinition $rootNode): void
222222
->{class_exists(GraphQL::class) ? 'canBeDisabled' : 'canBeEnabled'}()
223223
->addDefaultsIfNotSet()
224224
->children()
225+
->scalarNode('default_ide')->defaultValue('graphiql')->end()
225226
->arrayNode('graphiql')
226227
->{class_exists(GraphQL::class) && class_exists(TwigBundle::class) ? 'canBeDisabled' : 'canBeEnabled'}()
227228
->end()

src/Bridge/Symfony/Bundle/Resources/config/api.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
<argument>%api_platform.graphql.enabled%</argument>
4343
<argument>%api_platform.enable_entrypoint%</argument>
4444
<argument>%api_platform.enable_docs%</argument>
45+
<argument>%api_platform.graphql.graphiql.enabled%</argument>
4546

4647
<tag name="routing.loader" />
4748
</service>

src/Bridge/Symfony/Bundle/Resources/config/graphql.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,16 @@
112112
<service id="api_platform.graphql.action.entrypoint" class="ApiPlatform\Core\GraphQl\Action\EntrypointAction" public="true">
113113
<argument type="service" id="api_platform.graphql.schema_builder" />
114114
<argument type="service" id="api_platform.graphql.executor" />
115-
<argument type="service" id="twig" />
115+
<argument type="service" id="api_platform.graphql.action.graphiql" />
116116
<argument>%kernel.debug%</argument>
117117
<argument>%api_platform.graphql.graphiql.enabled%</argument>
118+
<argument>%api_platform.graphql.default_ide%</argument>
119+
</service>
120+
121+
<service id="api_platform.graphql.action.graphiql" class="ApiPlatform\Core\GraphQl\Action\GraphiQlAction" public="true">
122+
<argument type="service" id="twig" />
123+
<argument type="service" id="api_platform.router" />
124+
<argument>%api_platform.graphql.graphiql.enabled%</argument>
118125
<argument>%api_platform.title%</argument>
119126
</service>
120127

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<routes xmlns="http://symfony.com/schema/routing"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/routing
6+
http://symfony.com/schema/routing/routing-1.0.xsd">
7+
8+
<route id="api_graphql_graphiql" path="/graphql/graphiql">
9+
<default key="_controller">api_platform.graphql.action.graphiql</default>
10+
</route>
11+
12+
</routes>

src/Bridge/Symfony/Bundle/Resources/config/swagger-ui.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<argument>%api_platform.enable_swagger_ui%</argument>
3333
<argument>%api_platform.enable_re_doc%</argument>
3434
<argument>%api_platform.graphql.enabled%</argument>
35+
<argument>%api_platform.graphql.graphiql.enabled%</argument>
3536
</service>
3637

3738
</services>
Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,39 @@
1-
// Parse the search string to get url parameters.
2-
var search = window.location.search;
3-
var parameters = {};
4-
search.substr(1).split('&').forEach(function (entry) {
5-
var eq = entry.indexOf('=');
6-
if (eq >= 0) {
7-
parameters[decodeURIComponent(entry.slice(0, eq))] =
8-
decodeURIComponent(entry.slice(eq + 1));
9-
}
10-
});
11-
12-
// If variables was provided, try to format it.
13-
if (parameters.variables) {
14-
try {
15-
parameters.variables =
16-
JSON.stringify(JSON.parse(parameters.variables), null, 2);
17-
} catch (e) {
18-
// Do nothing, we want to display the invalid JSON as a string, rather
19-
// than present an error.
20-
}
21-
}
1+
var initParameters = {};
2+
var entrypoint = null;
223

23-
// When the query and variables string is edited, update the URL bar so
24-
// that it can be easily shared
254
function onEditQuery(newQuery) {
26-
parameters.query = newQuery;
5+
initParameters.query = newQuery;
276
updateURL();
287
}
298

309
function onEditVariables(newVariables) {
31-
parameters.variables = newVariables;
10+
initParameters.variables = newVariables;
3211
updateURL();
3312
}
3413

3514
function onEditOperationName(newOperationName) {
36-
parameters.operationName = newOperationName;
15+
initParameters.operationName = newOperationName;
3716
updateURL();
3817
}
3918

4019
function updateURL() {
41-
var newSearch = '?' + Object.keys(parameters).filter(function (key) {
42-
return Boolean(parameters[key]);
20+
var newSearch = '?' + Object.keys(initParameters).filter(function (key) {
21+
return Boolean(initParameters[key]);
4322
}).map(function (key) {
44-
return encodeURIComponent(key) + '=' +
45-
encodeURIComponent(parameters[key]);
23+
return encodeURIComponent(key) + '=' + encodeURIComponent(initParameters[key]);
4624
}).join('&');
4725
history.replaceState(null, null, newSearch);
4826
}
4927

50-
// Defines a GraphQL fetcher using the fetch API.
5128
function graphQLFetcher(graphQLParams) {
52-
return fetch(window.location.pathname, {
29+
return fetch(entrypoint, {
5330
method: 'post',
5431
headers: {
5532
'Accept': 'application/json',
56-
'Content-Type': 'application/json',
33+
'Content-Type': 'application/json'
5734
},
5835
body: JSON.stringify(graphQLParams),
59-
credentials: 'include',
36+
credentials: 'include'
6037
}).then(function (response) {
6138
return response.text();
6239
}).then(function (responseBody) {
@@ -68,16 +45,36 @@ function graphQLFetcher(graphQLParams) {
6845
});
6946
}
7047

71-
// Render <GraphiQL /> into the body.
72-
ReactDOM.render(
73-
React.createElement(GraphiQL, {
74-
fetcher: graphQLFetcher,
75-
query: parameters.query,
76-
variables: parameters.variables,
77-
operationName: parameters.operationName,
78-
onEditQuery: onEditQuery,
79-
onEditVariables: onEditVariables,
80-
onEditOperationName: onEditOperationName
81-
}),
82-
document.getElementById('graphiql')
83-
);
48+
window.onload = function() {
49+
var data = JSON.parse(document.getElementById('graphiql-data').innerText);
50+
entrypoint = data.entrypoint;
51+
52+
var search = window.location.search;
53+
search.substr(1).split('&').forEach(function (entry) {
54+
var eq = entry.indexOf('=');
55+
if (eq >= 0) {
56+
initParameters[decodeURIComponent(entry.slice(0, eq))] = decodeURIComponent(entry.slice(eq + 1));
57+
}
58+
});
59+
60+
if (initParameters.variables) {
61+
try {
62+
initParameters.variables = JSON.stringify(JSON.parse(initParameters.variables), null, 2);
63+
} catch (e) {
64+
// Do nothing, we want to display the invalid JSON as a string, rather than present an error.
65+
}
66+
}
67+
68+
ReactDOM.render(
69+
React.createElement(GraphiQL, {
70+
fetcher: graphQLFetcher,
71+
query: initParameters.query,
72+
variables: initParameters.variables,
73+
operationName: initParameters.operationName,
74+
onEditQuery: onEditQuery,
75+
onEditVariables: onEditVariables,
76+
onEditOperationName: onEditOperationName
77+
}),
78+
document.getElementById('graphiql')
79+
);
80+
}

src/Bridge/Symfony/Bundle/Resources/views/Graphiql/index.html.twig

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

77
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/graphiql/graphiql.css') }}">
88
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/graphiql-style.css') }}">
9+
10+
{# json_encode(65) is for JSON_UNESCAPED_SLASHES|JSON_HEX_TAG to avoid JS XSS #}
11+
<script id="graphiql-data" type="application/json">{{ graphiql_data|json_encode(65)|raw }}</script>
912
</head>
1013

1114
<body>

0 commit comments

Comments
 (0)