Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Ui.GraphiQL/Internal/GraphiQLPageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public string Render() {
using (var streamReader = new StreamReader(manifestResourceStream)) {
var builder = new StringBuilder(streamReader.ReadToEnd());
builder.Replace("@Model.GraphQLEndPoint", this.settings.GraphQLEndPoint);
builder.Replace("@Model.GraphiQLPath", this.settings.GraphiQLPath);
graphiQLCSHtml = builder.ToString();
return this.Render();
}
Expand Down
37 changes: 23 additions & 14 deletions src/Ui.GraphiQL/Internal/graphiql.cshtml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!--
<!--
* Copyright (c) Facebook, Inc.
* All rights reserved.
*
Expand Down Expand Up @@ -96,25 +96,34 @@
function onEditOperationName(newOperationName) {
parameters.operationName = newOperationName;
updateURL();
Comment thread
pobisw marked this conversation as resolved.
}
}

function updateURL() {
var newSearch = '?' + Object.keys(parameters).filter(function (key) {
return Boolean(parameters[key]);
}).map(function (key) {
return encodeURIComponent(key) + '=' +
encodeURIComponent(parameters[key]);
}).join('&');
history.replaceState(null, null, newSearch);
}
function updateURL() {
var newSearch = '?' + Object.keys(parameters).filter(function (key) {
return Boolean(parameters[key]);
}).map(function (key) {
return encodeURIComponent(key) + '=' +
encodeURIComponent(parameters[key]);
}).join('&');
history.replaceState(null, null, newSearch);
}

function stripGraphQLUiEndPointFromPathName(graphQlUiEndpoint) {
var currentPathName = window.location.pathname;
var regex = new RegExp(graphQlUiEndpoint + "\/*");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the path name from the model variable is passed directly into a regular expression without encoding. Also seems wrong. Maybe this should not be using regexp at all and just perform a simple replace...

currentPathName = currentPathName.replace(regex, '');
return currentPathName;
}

var strippedCurrentPathName = stripGraphQLUiEndPointFromPathName("@Model.GraphiQLPath");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This injected variable appears to be encoded for HTML instead of for Javascript - correct? Or does Razor detect that it's within a <script> tag and encode it differently?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Razor? No Razor here 🤔 .

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cshtml are razor pages and @Model.GraphiQLPath is razor injecting a variable. By default it will format variables with html encoding. So I always use JavaScript encoding as shown below when injecting a variable into a script tag like this. Or encode it as json and then inject it. Or put it into a html tag and read the tag.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cshtml are razor pages

Yes but ... no Razor engine/stuff/handlers/compilers here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just good old string.Replace.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see. Then we should modify the string.Replace encode to javascript-encode the variables for use on the page. Probably not a critical fix as the url is controlled by the setup code, not user input.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


// Defines a GraphQL fetcher using the fetch API. You're not required to
// use fetch, and could instead implement graphQLFetcher however you like,
// as long as it returns a Promise or Observable.
function graphQLFetcher(graphQLParams) {
function graphQLFetcher(graphQLParams) {
// This example expects a GraphQL server at the path /graphql.
// Change this to point wherever you host your GraphQL server.
return fetch(window.location.protocol + "//" + window.location.host + '@Model.GraphQLEndPoint', {
return fetch(window.location.protocol + "//" + window.location.host + strippedCurrentPathName + '@Model.GraphQLEndPoint', {
Comment thread
Shane32 marked this conversation as resolved.
method: 'post',
headers: {
'Accept': 'application/json',
Expand All @@ -134,7 +143,7 @@
}

// Enable Subscriptions via WebSocket
var subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient((window.location.protocol === "http:" ? "ws://" : "wss://") + window.location.host + "@Model.GraphQLEndPoint", { reconnect: true });
var subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient((window.location.protocol === "http:" ? "ws://" : "wss://") + window.location.host + strippedCurrentPathName, { reconnect: true });
var subscriptionsFetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLFetcher);

// Render <GraphiQL /> into the body.
Expand Down
1 change: 1 addition & 0 deletions src/Ui.Playground/Internal/PlaygroundPageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public string Render() {
using (var streamReader = new StreamReader(manifestResourceStream)) {
var builder = new StringBuilder(streamReader.ReadToEnd());
builder.Replace("@Model.GraphQLEndPoint", this.settings.GraphQLEndPoint);
builder.Replace("@Model.PlaygroundPath", this.settings.Path);
playgroundCSHtml = builder.ToString();
return this.Render();
}
Expand Down
32 changes: 20 additions & 12 deletions src/Ui.Playground/Internal/playground.cshtml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
Expand Down Expand Up @@ -47,17 +47,25 @@
</div>
</div>
<script>
window.addEventListener('load', function (event) {
GraphQLPlayground.init(document.getElementById('root'),
{
setTitle: true,
endpoint: window.location.protocol + "//" + window.location.host + "@Model.GraphQLEndPoint",
subscriptionEndpoint: (window.location.protocol === "http:" ? "ws://" : "wss://") + window.location.host + "@Model.GraphQLEndPoint",
settings: {
'tracing.hideTracingResponse': false
}
});
})
window.addEventListener('load', function (event) {
var strippedCurrentPathName = stripGraphQLUiEndPointFromPathName("@Model.PlaygroundPath");

function updateURL() {
var newSearch = '?' + Object.keys(parameters).filter(function (key) {
return Boolean(parameters[key]);
}).map(function (key) {
return encodeURIComponent(key) + '=' +
encodeURIComponent(parameters[key]);
}).join('&');
history.replaceState(null, null, newSearch);
}

function stripGraphQLUiEndPointFromPathName(graphQlUiEndpoint) {
var currentPathName = window.location.pathname;
var regex = new RegExp(graphQlUiEndpoint + "\/*");
currentPathName = currentPathName.replace(regex, '');
return currentPathName;
}
</script>
</body>
</html>
1 change: 1 addition & 0 deletions src/Ui.Voyager/Internal/VoyagerPageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public string Render()
{
var builder = new StringBuilder(streamReader.ReadToEnd());
builder.Replace("@Model.GraphQLEndPoint", this.settings.GraphQLEndPoint);
builder.Replace("@Model.VoyagerPath", this.settings.Path);
voyagerCSHtml = builder.ToString();
return this.Render();
}
Expand Down
10 changes: 9 additions & 1 deletion src/Ui.Voyager/Internal/voyager.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
<div id="voyager" style="height: 100%;">Loading...</div>
<script>
function introspectionProvider(introspectionQuery) {
var strippedCurrentPathName = stripGraphQLUiEndPointFromPathName("@Model.VoyagerPath");
// This example expects a GraphQL server at the path /graphql.
// Change this to point wherever you host your GraphQL server.
return fetch(window.location.protocol + "//" + window.location.host + "@Model.GraphQLEndPoint", {
return fetch(window.location.protocol + "//" + window.location.host + strippedCurrentPathName + "@Model.GraphQLEndPoint", {
method: 'post',
headers: {
'Accept': 'application/json',
Expand All @@ -33,6 +34,13 @@
});
}

function stripGraphQLUiEndPointFromPathName(graphQlUiEndpoint) {
var currentPathName = window.location.pathname;
var regex = new RegExp(graphQlUiEndpoint + "\/*");
currentPathName = currentPathName.replace(regex, '');
return currentPathName;
}

// Render <Voyager />
GraphQLVoyager.init(document.getElementById('voyager'), {
introspection: introspectionProvider
Expand Down