Skip to content

Commit

Permalink
fix(graphql-java-kickstart#726): fix GraphiQL configuration
Browse files Browse the repository at this point in the history
There was some inconsistency in configuration handling. The
`GraphiQLProperties` were not used for headers and GraphiQL props.
Instead, the properties were manually loaded.

This part, however, was not updated with the starter reorganization,
and expected the variables in the old place
(`graphiql.props.variables.`).

This commit fixes this by using the props / headers from the
configuration properties.
  • Loading branch information
BlasiusSecundus committed Oct 13, 2021
1 parent c11a84f commit 629a55a
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 177 deletions.
47 changes: 24 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,29 +193,30 @@ Available Spring Boot configuration parameters (either `application.yml`
or `application.properties`):

```yaml
graphiql:
mapping: /graphiql
endpoint:
graphql: /graphql
subscriptions: /subscriptions
subscriptions:
timeout: 30
reconnect: false
basePath: /
enabled: true
pageTitle: GraphiQL
cdn:
enabled: false
version: latest
props:
resources:
query: query.graphql
defaultQuery: defaultQuery.graphql
variables: variables.graphql
variables:
editorTheme: "solarized light"
headers:
Authorization: "Bearer <your-token>"
graphql:
graphiql:
mapping: /graphiql
endpoint:
graphql: /graphql
subscriptions: /subscriptions
subscriptions:
timeout: 30
reconnect: false
basePath: /
enabled: true
pageTitle: GraphiQL
cdn:
enabled: false
version: latest
props:
resources:
query: query.graphql
defaultQuery: defaultQuery.graphql
variables: variables.json
variables:
editorTheme: "solarized light"
headers:
Authorization: "Bearer <your-token>"
```

By default GraphiQL is served from within the package. This can be configured to be served from CDN
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ public class GraphiQLAutoConfiguration {

@Bean(name = "graphiQLController")
@ConditionalOnWebApplication(type = SERVLET)
ServletGraphiQLController servletGraphiQLController() {
return new ServletGraphiQLController();
ServletGraphiQLController servletGraphiQLController(GraphiQLProperties properties) {
return new ServletGraphiQLController(properties);
}

@Bean(name = "graphiQLController")
@ConditionalOnMissingBean(ServletGraphiQLController.class)
@ConditionalOnWebApplication(type = REACTIVE)
ReactiveGraphiQLController reactiveGraphiQLController() {
return new ReactiveGraphiQLController();
ReactiveGraphiQLController reactiveGraphiQLController(GraphiQLProperties properties) {
return new ReactiveGraphiQLController(properties);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package graphql.kickstart.autoconfigure.editor.graphiql;

import static java.util.Objects.nonNull;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.kickstart.autoconfigure.editor.PropertyGroupReader;
import graphql.kickstart.autoconfigure.editor.PropsLoader;
import graphql.kickstart.autoconfigure.editor.graphiql.GraphiQLProperties.Props.GraphiQLVariables;
import graphql.kickstart.autoconfigure.editor.graphiql.GraphiQLProperties.Resources;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringSubstitutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.util.StreamUtils;
Expand All @@ -23,25 +27,22 @@

/** @author Andrew Potter */
@Slf4j
@RequiredArgsConstructor
public abstract class GraphiQLController {

private static final String CDNJS_CLOUDFLARE_COM_AJAX_LIBS = "//cdnjs.cloudflare.com/ajax/libs/";
private static final String CDN_JSDELIVR_NET_NPM = "//cdn.jsdelivr.net/npm/";
private static final String GRAPHIQL = "graphiql";
private static final String FAVICON_GRAPHQL_ORG = "//graphql.org/img/favicon.png";

@Autowired private Environment environment;

@Autowired private GraphiQLProperties graphiQLProperties;
private final GraphiQLProperties graphiQLProperties;

private String template;
private String props;
private Properties headerProperties;

public void onceConstructed() throws IOException {
loadTemplate();
loadProps();
loadHeaders();
}

private void loadTemplate() throws IOException {
Expand All @@ -52,35 +53,45 @@ private void loadTemplate() throws IOException {
}

private void loadProps() throws IOException {
props =
new PropsLoader(environment, "graphiql.props.resources.", "graphiql.props.variables.")
.load();
}

private void loadHeaders() {
PropertyGroupReader propertyReader = new PropertyGroupReader(environment, "graphiql.headers.");
headerProperties = propertyReader.load();
Resources resources = graphiQLProperties.getProps().getResources();
GraphiQLVariables combinedVariables = graphiQLProperties.getProps().getVariables();
if (nonNull(resources.getVariables())) {
combinedVariables = combinedVariables.withVariables(getContent(resources.getVariables()));
}
if (nonNull(resources.getDefaultQuery())) {
combinedVariables
= combinedVariables.withDefaultQuery(getContent(resources.getDefaultQuery()));
}
if (nonNull(resources.getQuery())) {
combinedVariables = combinedVariables.withQuery(getContent(resources.getQuery()));
}
this.props = new ObjectMapper().writeValueAsString(combinedVariables);
}

public byte[] graphiql(
String contextPath, @PathVariable Map<String, String> params, Object csrf) {
Map<String, String> finalHeaders = Optional.ofNullable(graphiQLProperties.getHeaders())
.orElseGet(Collections::emptyMap);
if (csrf != null) {
CsrfToken csrfToken = (CsrfToken) csrf;
headerProperties.setProperty(csrfToken.getHeaderName(), csrfToken.getToken());
finalHeaders = new HashMap<>(finalHeaders);
finalHeaders.put(csrfToken.getHeaderName(), csrfToken.getToken());
}

Map<String, String> replacements =
getReplacements(
constructGraphQlEndpoint(contextPath, params),
contextPath + graphiQLProperties.getEndpoint().getSubscriptions(),
contextPath + graphiQLProperties.getBasePath());
contextPath + graphiQLProperties.getBasePath(),
finalHeaders);

String populatedTemplate = StringSubstitutor.replace(template, replacements);
return populatedTemplate.getBytes(Charset.defaultCharset());
}

private Map<String, String> getReplacements(
String graphqlEndpoint, String subscriptionsEndpoint, String staticBasePath) {
String graphqlEndpoint, String subscriptionsEndpoint, String staticBasePath,
Map<String, String> headers) {
Map<String, String> replacements = new HashMap<>();
replacements.put("graphqlEndpoint", graphqlEndpoint);
replacements.put("subscriptionsEndpoint", subscriptionsEndpoint);
Expand Down Expand Up @@ -137,7 +148,7 @@ private Map<String, String> getReplacements(
joinJsDelivrPath("graphiql-subscriptions-fetcher", "0.0.2", "browser/client.js")));
replacements.put("props", props);
try {
replacements.put("headers", new ObjectMapper().writeValueAsString(headerProperties));
replacements.put("headers", new ObjectMapper().writeValueAsString(headers));
} catch (JsonProcessingException e) {
log.error("Cannot serialize headers", e);
}
Expand Down Expand Up @@ -191,4 +202,8 @@ private String constructGraphQlEndpoint(
}
return endpoint;
}

private String getContent(final ClassPathResource resource) throws IOException {
return new String(Files.readAllBytes(resource.getFile().toPath()), StandardCharsets.UTF_8);
}
}
Loading

0 comments on commit 629a55a

Please sign in to comment.