Skip to content

Commit

Permalink
enhancement(config api): Add graphql field to toggle graphql endpoi…
Browse files Browse the repository at this point in the history
…nt (#19645)

* OPW-195

* knit: param change

* docs

* trailing whitespaces

* rustfmt

* docs and test fix

* serialization skip for new field & typing

* passby clippy

* spacing

* nit
  • Loading branch information
sebastiantia authored Jan 22, 2024
1 parent f41ca86 commit 5bb4926
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 12 deletions.
3 changes: 3 additions & 0 deletions changelog.d/graphql_endpoint_toggle.enhancement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added a boolean `graphql` field to the api configuration to allow disabling the graphql endpoint.

Note that the `playground` endpoint will now only be enabled if the `graphql` endpoint is also enabled.
29 changes: 18 additions & 11 deletions src/api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use warp::{filters::BoxedFilter, http::Response, ws::Ws, Filter, Reply};

use super::{handler, schema, ShutdownTx};
use crate::{
config,
config::{self, api},
http::build_http_trace_layer,
internal_events::{SocketBindError, SocketMode},
topology,
Expand All @@ -38,7 +38,7 @@ impl Server {
running: Arc<AtomicBool>,
handle: &Handle,
) -> crate::Result<Self> {
let routes = make_routes(config.api.playground, watch_rx, running);
let routes = make_routes(config.api, watch_rx, running);

let (_shutdown, rx) = oneshot::channel();
// warp uses `tokio::spawn` and so needs us to enter the runtime context.
Expand Down Expand Up @@ -96,7 +96,7 @@ impl Server {
}

fn make_routes(
playground: bool,
api: api::Options,
watch_tx: topology::WatchRx,
running: Arc<AtomicBool>,
) -> BoxedFilter<(impl Reply,)> {
Expand All @@ -108,6 +108,7 @@ fn make_routes(
.and_then(handler::health);

// 404.
let not_found_graphql = warp::any().and_then(|| async { Err(warp::reject::not_found()) });
let not_found = warp::any().and_then(|| async { Err(warp::reject::not_found()) });

// GraphQL subscription handler. Creates a Warp WebSocket handler and for each connection,
Expand Down Expand Up @@ -140,16 +141,22 @@ fn make_routes(
// Handle GraphQL queries. Headers will first be parsed to determine whether the query is
// a subscription and if so, an attempt will be made to upgrade the connection to WebSockets.
// All other queries will fall back to the default HTTP handler.
let graphql_handler = warp::path("graphql").and(graphql_subscription_handler.or(
async_graphql_warp::graphql(schema::build_schema().finish()).and_then(
|(schema, request): (Schema<_, _, _>, Request)| async move {
Ok::<_, Infallible>(GraphQLResponse::from(schema.execute(request).await))
},
),
));
let graphql_handler = if api.graphql {
warp::path("graphql")
.and(graphql_subscription_handler.or(
async_graphql_warp::graphql(schema::build_schema().finish()).and_then(
|(schema, request): (Schema<_, _, _>, Request)| async move {
Ok::<_, Infallible>(GraphQLResponse::from(schema.execute(request).await))
},
),
))
.boxed()
} else {
not_found_graphql.boxed()
};

// Provide a playground for executing GraphQL queries/mutations/subscriptions.
let graphql_playground = if playground {
let graphql_playground = if api.playground && api.graphql {
warp::path("playground")
.map(move || {
Response::builder()
Expand Down
20 changes: 20 additions & 0 deletions src/config/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ pub struct Options {
/// Whether or not to expose the GraphQL playground on the API endpoint.
#[serde(default = "default_playground")]
pub playground: bool,

/// Whether or not the GraphQL endpoint is enabled
#[serde(default = "default_graphql", skip_serializing_if = "is_true")]
pub graphql: bool,
}

impl Default for Options {
Expand All @@ -27,10 +31,17 @@ impl Default for Options {
enabled: default_enabled(),
playground: default_playground(),
address: default_address(),
graphql: default_graphql(),
}
}
}

// serde passes struct fields as reference
#[allow(clippy::trivially_copy_pass_by_ref)]
const fn is_true(value: &bool) -> bool {
*value
}

const fn default_enabled() -> bool {
false
}
Expand All @@ -53,6 +64,10 @@ const fn default_playground() -> bool {
true
}

const fn default_graphql() -> bool {
true
}

impl Options {
pub fn merge(&mut self, other: Self) -> Result<(), String> {
// Merge options
Expand All @@ -78,6 +93,7 @@ impl Options {
address,
enabled: self.enabled | other.enabled,
playground: self.playground & other.playground,
graphql: self.graphql & other.graphql,
};

*self = options;
Expand All @@ -91,6 +107,7 @@ fn bool_merge() {
enabled: true,
address: None,
playground: false,
graphql: false,
};

a.merge(Options::default()).unwrap();
Expand All @@ -101,6 +118,7 @@ fn bool_merge() {
enabled: true,
address: default_address(),
playground: false,
graphql: false
}
);
}
Expand All @@ -112,6 +130,7 @@ fn bind_merge() {
enabled: true,
address: Some(address),
playground: true,
graphql: true,
};

a.merge(Options::default()).unwrap();
Expand All @@ -122,6 +141,7 @@ fn bind_merge() {
enabled: true,
address: Some(address),
playground: true,
graphql: true,
}
);
}
Expand Down
13 changes: 12 additions & 1 deletion website/cue/reference/api.cue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,18 @@ api: {
description: """
Whether the [GraphQL Playground](\(urls.graphql_playground)) is enabled
for the API. The Playground is accessible via the `/playground` endpoint
of the address set using the `bind` parameter.
of the address set using the `bind` parameter. Note that the `playground`
endpoint will only be enabled if the `graphql` endpoint is also enabled.
"""
}
graphql: {
common: true
required: false
type: bool: default: true
description: """
Whether the endpoint for receiving and processing GraphQL queries is
enabled for the API. The endpoint is accessible via the `/graphql`
endpoint of the address set using the `bind` parameter.
"""
}
}
Expand Down

0 comments on commit 5bb4926

Please sign in to comment.