2
2
3
3
import com .fasterxml .jackson .core .JsonProcessingException ;
4
4
import com .fasterxml .jackson .databind .ObjectMapper ;
5
+ import lombok .extern .slf4j .Slf4j ;
5
6
import org .apache .commons .lang3 .StringUtils ;
6
7
import org .apache .commons .lang3 .text .StrSubstitutor ;
7
8
import org .springframework .beans .factory .annotation .Autowired ;
8
- import org .springframework .beans .factory .annotation .Value ;
9
9
import org .springframework .core .env .Environment ;
10
10
import org .springframework .core .io .ClassPathResource ;
11
11
import org .springframework .http .MediaType ;
12
+ import org .springframework .security .web .csrf .CsrfToken ;
12
13
import org .springframework .stereotype .Controller ;
13
14
import org .springframework .util .StreamUtils ;
15
+ import org .springframework .web .bind .annotation .GetMapping ;
14
16
import org .springframework .web .bind .annotation .PathVariable ;
15
- import org .springframework .web .bind .annotation .RequestMapping ;
16
17
import org .springframework .web .bind .annotation .RequestParam ;
17
18
18
19
import javax .annotation .PostConstruct ;
28
29
/**
29
30
* @author Andrew Potter
30
31
*/
32
+ @ Slf4j
31
33
@ Controller
32
34
public class GraphiQLController {
33
35
@@ -36,30 +38,6 @@ public class GraphiQLController {
36
38
private static final String GRAPHIQL = "graphiql" ;
37
39
private static final String FAVICON_GRAPHQL_ORG = "//graphql.org/img/favicon.png" ;
38
40
39
- @ Value ("${graphiql.endpoint.graphql:/graphql}" )
40
- private String graphqlEndpoint ;
41
-
42
- @ Value ("${graphiql.endpoint.subscriptions:/subscriptions}" )
43
- private String subscriptionsEndpoint ;
44
-
45
- @ Value ("${graphiql.static.basePath:/}" )
46
- private String staticBasePath ;
47
-
48
- @ Value ("${graphiql.pageTitle:GraphiQL}" )
49
- private String pageTitle ;
50
-
51
- @ Value ("${graphiql.cdn.enabled:false}" )
52
- private Boolean graphiqlCdnEnabled ;
53
-
54
- @ Value ("${graphiql.cdn.version:0.13.0}" )
55
- private String graphiqlCdnVersion ;
56
-
57
- @ Value ("${graphiql.subscriptions.timeout:30}" )
58
- private Integer subscriptionsTimeout ;
59
-
60
- @ Value ("${graphiql.subscriptions.reconnect:false}" )
61
- private Boolean subscriptionsReconnect ;
62
-
63
41
@ Autowired
64
42
private Environment environment ;
65
43
@@ -68,7 +46,7 @@ public class GraphiQLController {
68
46
69
47
private String template ;
70
48
private String props ;
71
- private String headers ;
49
+ private Properties headerProperties ;
72
50
73
51
@ PostConstruct
74
52
public void onceConstructed () throws IOException {
@@ -87,12 +65,11 @@ private void loadProps() throws IOException {
87
65
props = new PropsLoader (environment ).load ();
88
66
}
89
67
90
- private void loadHeaders () throws JsonProcessingException {
68
+ private void loadHeaders () {
91
69
PropertyGroupReader propertyReader = new PropertyGroupReader (environment , "graphiql.headers." );
92
- Properties headerProperties = propertyReader .load ();
70
+ headerProperties = propertyReader .load ();
93
71
addIfAbsent (headerProperties , "Accept" );
94
72
addIfAbsent (headerProperties , "Content-Type" );
95
- this .headers = new ObjectMapper ().writeValueAsString (headerProperties );
96
73
}
97
74
98
75
private void addIfAbsent (Properties headerProperties , String header ) {
@@ -101,26 +78,35 @@ private void addIfAbsent(Properties headerProperties, String header) {
101
78
}
102
79
}
103
80
104
- @ RequestMapping (value = "${graphiql.mapping:/graphiql}" )
81
+ @ GetMapping (value = "${graphiql.mapping:/graphiql}" )
105
82
public void graphiql (HttpServletRequest request , HttpServletResponse response , @ PathVariable Map <String , String > params ) throws IOException {
106
83
response .setContentType ("text/html; charset=UTF-8" );
84
+ Object csrf = request .getAttribute ("_csrf" );
85
+ if (csrf != null ) {
86
+ CsrfToken csrfToken = (CsrfToken ) csrf ;
87
+ headerProperties .setProperty (csrfToken .getHeaderName (), csrfToken .getToken ());
88
+ }
107
89
108
90
Map <String , String > replacements = getReplacements (
109
91
constructGraphQlEndpoint (request , params ),
110
- request .getContextPath () + subscriptionsEndpoint ,
111
- request .getContextPath () + staticBasePath
92
+ request .getContextPath () + graphiQLProperties . getEndpoint (). getSubscriptions () ,
93
+ request .getContextPath () + graphiQLProperties . getSTATIC (). getBasePath ()
112
94
);
113
95
114
96
String populatedTemplate = StrSubstitutor .replace (template , replacements );
115
97
response .getOutputStream ().write (populatedTemplate .getBytes (Charset .defaultCharset ()));
116
98
}
117
99
118
- private Map <String , String > getReplacements (String graphqlEndpoint , String subscriptionsEndpoint , String staticBasePath ) {
100
+ private Map <String , String > getReplacements (
101
+ String graphqlEndpoint ,
102
+ String subscriptionsEndpoint ,
103
+ String staticBasePath
104
+ ) {
119
105
Map <String , String > replacements = new HashMap <>();
120
106
replacements .put ("graphqlEndpoint" , graphqlEndpoint );
121
107
replacements .put ("subscriptionsEndpoint" , subscriptionsEndpoint );
122
108
replacements .put ("staticBasePath" , staticBasePath );
123
- replacements .put ("pageTitle" , pageTitle );
109
+ replacements .put ("pageTitle" , graphiQLProperties . getPageTitle () );
124
110
replacements .put ("pageFavicon" , getResourceUrl (staticBasePath , "favicon.ico" , FAVICON_GRAPHQL_ORG ));
125
111
replacements .put ("es6PromiseJsUrl" , getResourceUrl (staticBasePath , "es6-promise.auto.min.js" ,
126
112
joinCdnjsPath ("es6-promise" , "4.1.1" , "es6-promise.auto.min.js" )));
@@ -131,19 +117,23 @@ private Map<String, String> getReplacements(String graphqlEndpoint, String subsc
131
117
replacements .put ("reactDomJsUrl" , getResourceUrl (staticBasePath , "react-dom.min.js" ,
132
118
joinCdnjsPath ("react-dom" , "16.8.3" , "umd/react-dom.production.min.js" )));
133
119
replacements .put ("graphiqlCssUrl" , getResourceUrl (staticBasePath , "graphiql.min.css" ,
134
- joinJsDelivrPath (GRAPHIQL , graphiqlCdnVersion , "graphiql.css" )));
120
+ joinJsDelivrPath (GRAPHIQL , graphiQLProperties . getCdn (). getVersion () , "graphiql.css" )));
135
121
replacements .put ("graphiqlJsUrl" , getResourceUrl (staticBasePath , "graphiql.min.js" ,
136
- joinJsDelivrPath (GRAPHIQL , graphiqlCdnVersion , "graphiql.min.js" )));
122
+ joinJsDelivrPath (GRAPHIQL , graphiQLProperties . getCdn (). getVersion () , "graphiql.min.js" )));
137
123
replacements .put ("subscriptionsTransportWsBrowserClientUrl" , getResourceUrl (staticBasePath ,
138
124
"subscriptions-transport-ws-browser-client.js" ,
139
125
joinJsDelivrPath ("subscriptions-transport-ws" , "0.9.15" , "browser/client.js" )));
140
126
replacements .put ("graphiqlSubscriptionsFetcherBrowserClientUrl" , getResourceUrl (staticBasePath ,
141
127
"graphiql-subscriptions-fetcher-browser-client.js" ,
142
128
joinJsDelivrPath ("graphiql-subscriptions-fetcher" , "0.0.2" , "browser/client.js" )));
143
129
replacements .put ("props" , props );
144
- replacements .put ("headers" , headers );
145
- replacements .put ("subscriptionClientTimeout" , String .valueOf (subscriptionsTimeout * 1000 ));
146
- replacements .put ("subscriptionClientReconnect" , String .valueOf (subscriptionsReconnect ));
130
+ try {
131
+ replacements .put ("headers" , new ObjectMapper ().writeValueAsString (headerProperties ));
132
+ } catch (JsonProcessingException e ) {
133
+ log .error ("Cannot serialize headers" , e );
134
+ }
135
+ replacements .put ("subscriptionClientTimeout" , String .valueOf (graphiQLProperties .getSubscriptions ().getTimeout () * 1000 ));
136
+ replacements .put ("subscriptionClientReconnect" , String .valueOf (graphiQLProperties .getSubscriptions ().isReconnect ()));
147
137
replacements .put ("editorThemeCss" , getEditorThemeCssURL ());
148
138
return replacements ;
149
139
}
@@ -161,7 +151,7 @@ private String getEditorThemeCssURL() {
161
151
}
162
152
163
153
private String getResourceUrl (String staticBasePath , String staticFileName , String cdnUrl ) {
164
- if (graphiqlCdnEnabled && StringUtils .isNotBlank (cdnUrl )) {
154
+ if (graphiQLProperties . getCdn (). isEnabled () && StringUtils .isNotBlank (cdnUrl )) {
165
155
return cdnUrl ;
166
156
}
167
157
return joinStaticPath (staticBasePath , staticFileName );
@@ -180,7 +170,7 @@ private String joinJsDelivrPath(String library, String cdnVersion, String cdnFil
180
170
}
181
171
182
172
private String constructGraphQlEndpoint (HttpServletRequest request , @ RequestParam Map <String , String > params ) {
183
- String endpoint = graphqlEndpoint ;
173
+ String endpoint = graphiQLProperties . getEndpoint (). getGraphql () ;
184
174
for (Map .Entry <String , String > param : params .entrySet ()) {
185
175
endpoint = endpoint .replaceAll ("\\ {" + param .getKey () + "}" , param .getValue ());
186
176
}
0 commit comments