-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Allow passing args in playground #3184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
b633496
2dfb31f
30db167
a93b330
cde0d89
37b5d9d
726032a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Modify url parsing to allow passing args through to query url |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,7 @@ use axum::{ | |
| extract::{ | ||
| DefaultBodyLimit, | ||
| Extension, | ||
| RawQuery, | ||
| }, | ||
| http::{ | ||
| HeaderValue, | ||
|
|
@@ -83,10 +84,7 @@ use std::{ | |
| TcpListener, | ||
| }, | ||
| pin::Pin, | ||
| sync::{ | ||
| Arc, | ||
| OnceLock, | ||
| }, | ||
| sync::Arc, | ||
| }; | ||
| use tokio_stream::StreamExt; | ||
| use tower::limit::ConcurrencyLimitLayer; | ||
|
|
@@ -323,8 +321,9 @@ where | |
| let graphql_endpoint = "/v1/graphql"; | ||
| let graphql_subscription_endpoint = "/v1/graphql-sub"; | ||
|
|
||
| let graphql_playground = | ||
| || render_graphql_playground(graphql_endpoint, graphql_subscription_endpoint); | ||
| let graphql_playground = |query: RawQuery| { | ||
| render_graphql_playground(graphql_endpoint, graphql_subscription_endpoint, query) | ||
| }; | ||
|
|
||
| let router = Router::new() | ||
| .route("/v1/playground", get(graphql_playground)) | ||
|
|
@@ -373,43 +372,54 @@ where | |
| )) | ||
| } | ||
|
|
||
| /// Single initialization of the GraphQL playground HTML. | ||
| /// This is because the rendering and replacing is expensive | ||
| static GRAPHQL_PLAYGROUND_HTML: OnceLock<Arc<String>> = OnceLock::new(); | ||
|
|
||
| fn _render_graphql_playground( | ||
| endpoint: &str, | ||
| subscription_endpoint: &str, | ||
| query: RawQuery, | ||
| ) -> impl IntoResponse + Send + Sync { | ||
| let html = GRAPHQL_PLAYGROUND_HTML.get_or_init(|| { | ||
| let raw_html = GraphiQLSource::build() | ||
| .endpoint(endpoint) | ||
| .subscription_endpoint(subscription_endpoint) | ||
| .title("Fuel Graphql Playground") | ||
| .finish(); | ||
|
|
||
| // this may not be necessary in the future, | ||
| // but we need it to patch: https://github.com/async-graphql/async-graphql/issues/1703 | ||
| let raw_html = raw_html.replace( | ||
| "https://unpkg.com/graphiql/graphiql.min.js", | ||
| "https://unpkg.com/graphiql@3/graphiql.min.js", | ||
| ); | ||
| let raw_html = raw_html.replace( | ||
| "https://unpkg.com/graphiql/graphiql.min.css", | ||
| "https://unpkg.com/graphiql@3/graphiql.min.css", | ||
| ); | ||
|
|
||
| Arc::new(raw_html) | ||
| }); | ||
| let qs = query | ||
| .0 | ||
| .as_deref() | ||
| .filter(|q| !q.is_empty()) | ||
| .map(|q| format!("?{q}")) | ||
| .unwrap_or_default(); | ||
|
|
||
| let endpoint = format!("{}{}", endpoint, qs); | ||
| let subscription_endpoint = format!("{}{}", subscription_endpoint, qs); | ||
|
|
||
| // let html = GRAPHQL_PLAYGROUND_HTML.get_or_init(|| { | ||
| let raw_html = GraphiQLSource::build() | ||
| .endpoint(&endpoint) | ||
| .subscription_endpoint(&subscription_endpoint) | ||
| .title("Fuel Graphql Playground") | ||
| .finish(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reflected XSS via unsanitized query string in HTMLMedium Severity User-controlled raw query string from |
||
|
|
||
| Html(html.as_str()) | ||
| // this may not be necessary in the future, | ||
| // but we need it to patch: https://github.com/async-graphql/async-graphql/issues/1703 | ||
| let raw_html = raw_html.replace( | ||
| "https://unpkg.com/graphiql/graphiql.min.js", | ||
| "https://unpkg.com/graphiql@3/graphiql.min.js", | ||
| ); | ||
| let raw_html = raw_html.replace( | ||
| "https://unpkg.com/graphiql/graphiql.min.css", | ||
| "https://unpkg.com/graphiql@3/graphiql.min.css", | ||
| ); | ||
|
|
||
| let raw_html = raw_html.replace( | ||
| "const url = new URL(endpoint, window.location.origin);", | ||
| r#"const url = new URL(endpoint, window.location.origin); | ||
| url.search = window.location.search;"#, | ||
| ); | ||
|
|
||
| Html(raw_html.clone()) | ||
| } | ||
|
|
||
| async fn render_graphql_playground( | ||
| endpoint: &str, | ||
| subscription_endpoint: &str, | ||
| raw_query: RawQuery, | ||
| ) -> impl IntoResponse + Send + Sync { | ||
| _render_graphql_playground(endpoint, subscription_endpoint) | ||
| _render_graphql_playground(endpoint, subscription_endpoint, raw_query) | ||
| } | ||
|
|
||
| async fn health() -> Json<serde_json::Value> { | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commented-out code left from OnceLock removal
Low Severity
The line
// let html = GRAPHQL_PLAYGROUND_HTML.get_or_init(|| {is a leftover comment from the removedOnceLockcaching mechanism. This dead commented-out code adds noise and could confuse future readers about the intended design.