Skip to content

Commit e50e12b

Browse files
committed
Move GraphiQL's JS into a separate file for ease of CSP
1 parent 24ebc20 commit e50e12b

File tree

2 files changed

+121
-118
lines changed

2 files changed

+121
-118
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
(function() {
2+
3+
// Parse the cookie value for a CSRF token
4+
var csrftoken;
5+
var cookies = ('; ' + document.cookie).split('; csrftoken=');
6+
if (cookies.length == 2)
7+
csrftoken = cookies.pop().split(';').shift();
8+
9+
// Collect the URL parameters
10+
var parameters = {};
11+
window.location.hash.substr(1).split('&').forEach(function (entry) {
12+
var eq = entry.indexOf('=');
13+
if (eq >= 0) {
14+
parameters[decodeURIComponent(entry.slice(0, eq))] =
15+
decodeURIComponent(entry.slice(eq + 1));
16+
}
17+
});
18+
// Produce a Location fragment string from a parameter object.
19+
function locationQuery(params) {
20+
return '#' + Object.keys(params).map(function (key) {
21+
return encodeURIComponent(key) + '=' +
22+
encodeURIComponent(params[key]);
23+
}).join('&');
24+
}
25+
// Derive a fetch URL from the current URL, sans the GraphQL parameters.
26+
var graphqlParamNames = {
27+
query: true,
28+
variables: true,
29+
operationName: true
30+
};
31+
var otherParams = {};
32+
for (var k in parameters) {
33+
if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {
34+
otherParams[k] = parameters[k];
35+
}
36+
}
37+
38+
// If there are any fragment parameters, confirm the user wants to use them.
39+
var isReload = window.performance ? performance.navigation.type === 1 : false;
40+
var isQueryTrusted = Object.keys(parameters).length === 0 || isReload;
41+
42+
var fetchURL = locationQuery(otherParams);
43+
44+
// Defines a GraphQL fetcher using the fetch API.
45+
function graphQLFetcher(graphQLParams) {
46+
var isIntrospectionQuery = (
47+
graphQLParams.query !== parameters.query
48+
&& graphQLParams.query.indexOf('IntrospectionQuery') !== -1
49+
);
50+
51+
if (!isQueryTrusted
52+
&& !isIntrospectionQuery
53+
&& !window.confirm("This query was loaded from a link, are you sure you want to execute it?")) {
54+
return Promise.resolve('Aborting query.');
55+
}
56+
57+
// We don't want to set this for the introspection query
58+
if (!isIntrospectionQuery) {
59+
isQueryTrusted = true;
60+
}
61+
62+
var headers = {
63+
'Accept': 'application/json',
64+
'Content-Type': 'application/json'
65+
};
66+
if (csrftoken) {
67+
headers['X-CSRFToken'] = csrftoken;
68+
}
69+
return fetch(fetchURL, {
70+
method: 'post',
71+
headers: headers,
72+
body: JSON.stringify(graphQLParams),
73+
credentials: 'include',
74+
}).then(function (response) {
75+
return response.text();
76+
}).then(function (responseBody) {
77+
try {
78+
return JSON.parse(responseBody);
79+
} catch (error) {
80+
return responseBody;
81+
}
82+
});
83+
}
84+
// When the query and variables string is edited, update the URL bar so
85+
// that it can be easily shared.
86+
function onEditQuery(newQuery) {
87+
parameters.query = newQuery;
88+
updateURL();
89+
}
90+
function onEditVariables(newVariables) {
91+
parameters.variables = newVariables;
92+
updateURL();
93+
}
94+
function onEditOperationName(newOperationName) {
95+
parameters.operationName = newOperationName;
96+
updateURL();
97+
}
98+
function updateURL() {
99+
history.replaceState(null, null, locationQuery(parameters));
100+
}
101+
var options = {
102+
fetcher: graphQLFetcher,
103+
onEditQuery: onEditQuery,
104+
onEditVariables: onEditVariables,
105+
onEditOperationName: onEditOperationName,
106+
query: parameters.query,
107+
}
108+
if (parameters.variables) {
109+
options.variables = parameters.variables;
110+
}
111+
if (parameters.operation_name) {
112+
options.operationName = parameters.operation_name;
113+
}
114+
// Render <GraphiQL /> into the body.
115+
ReactDOM.render(
116+
React.createElement(GraphiQL, options),
117+
document.body
118+
);
119+
})();

graphene_django/templates/graphene/graphiql.html

Lines changed: 2 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
If you wish to receive JSON, provide the header "Accept: application/json" or
66
add "&raw" to the end of the URL within a browser.
77
-->
8+
{% load static %}
89
<!DOCTYPE html>
910
<html>
1011
<head>
@@ -23,123 +24,6 @@
2324
<script src="//cdn.jsdelivr.net/npm/graphiql@{{graphiql_version}}/graphiql.min.js"></script>
2425
</head>
2526
<body>
26-
<script>
27-
// Parse the cookie value for a CSRF token
28-
var csrftoken;
29-
var cookies = ('; ' + document.cookie).split('; csrftoken=');
30-
if (cookies.length == 2)
31-
csrftoken = cookies.pop().split(';').shift();
32-
33-
// Collect the URL parameters
34-
var parameters = {};
35-
window.location.hash.substr(1).split('&').forEach(function (entry) {
36-
var eq = entry.indexOf('=');
37-
if (eq >= 0) {
38-
parameters[decodeURIComponent(entry.slice(0, eq))] =
39-
decodeURIComponent(entry.slice(eq + 1));
40-
}
41-
});
42-
// Produce a Location fragment string from a parameter object.
43-
function locationQuery(params) {
44-
return '#' + Object.keys(params).map(function (key) {
45-
return encodeURIComponent(key) + '=' +
46-
encodeURIComponent(params[key]);
47-
}).join('&');
48-
}
49-
// Derive a fetch URL from the current URL, sans the GraphQL parameters.
50-
var graphqlParamNames = {
51-
query: true,
52-
variables: true,
53-
operationName: true
54-
};
55-
var otherParams = {};
56-
for (var k in parameters) {
57-
if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {
58-
otherParams[k] = parameters[k];
59-
}
60-
}
61-
62-
// If there are any fragment parameters, confirm the user wants to use them.
63-
var isReload = window.performance ? performance.navigation.type === 1 : false;
64-
var isQueryTrusted = Object.keys(parameters).length === 0 || isReload;
65-
66-
var fetchURL = locationQuery(otherParams);
67-
68-
// Defines a GraphQL fetcher using the fetch API.
69-
function graphQLFetcher(graphQLParams) {
70-
var isIntrospectionQuery = (
71-
graphQLParams.query !== parameters.query
72-
&& graphQLParams.query.indexOf('IntrospectionQuery') !== -1
73-
);
74-
75-
if (!isQueryTrusted
76-
&& !isIntrospectionQuery
77-
&& !window.confirm("This query was loaded from a link, are you sure you want to execute it?")) {
78-
return Promise.resolve('Aborting query.');
79-
}
80-
81-
// We don't want to set this for the introspection query
82-
if (!isIntrospectionQuery) {
83-
isQueryTrusted = true;
84-
}
85-
86-
var headers = {
87-
'Accept': 'application/json',
88-
'Content-Type': 'application/json'
89-
};
90-
if (csrftoken) {
91-
headers['X-CSRFToken'] = csrftoken;
92-
}
93-
return fetch(fetchURL, {
94-
method: 'post',
95-
headers: headers,
96-
body: JSON.stringify(graphQLParams),
97-
credentials: 'include',
98-
}).then(function (response) {
99-
return response.text();
100-
}).then(function (responseBody) {
101-
try {
102-
return JSON.parse(responseBody);
103-
} catch (error) {
104-
return responseBody;
105-
}
106-
});
107-
}
108-
// When the query and variables string is edited, update the URL bar so
109-
// that it can be easily shared.
110-
function onEditQuery(newQuery) {
111-
parameters.query = newQuery;
112-
updateURL();
113-
}
114-
function onEditVariables(newVariables) {
115-
parameters.variables = newVariables;
116-
updateURL();
117-
}
118-
function onEditOperationName(newOperationName) {
119-
parameters.operationName = newOperationName;
120-
updateURL();
121-
}
122-
function updateURL() {
123-
history.replaceState(null, null, locationQuery(parameters));
124-
}
125-
var options = {
126-
fetcher: graphQLFetcher,
127-
onEditQuery: onEditQuery,
128-
onEditVariables: onEditVariables,
129-
onEditOperationName: onEditOperationName,
130-
query: parameters.query,
131-
}
132-
if (parameters.variables) {
133-
options.variables = parameters.variables;
134-
}
135-
if (parameters.operation_name) {
136-
options.operationName = parameters.operation_name;
137-
}
138-
// Render <GraphiQL /> into the body.
139-
ReactDOM.render(
140-
React.createElement(GraphiQL, options),
141-
document.body
142-
);
143-
</script>
27+
<script src="{% static "graphene_django/graphiql.js" %}"></script>
14428
</body>
14529
</html>

0 commit comments

Comments
 (0)