Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/server/spring-beans.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ can be customized by providing custom beans in your application context. See sec

| Bean | Description |
|:-------------------------------|:------------|
| ContextWebFilter | Default web filter that populates GraphQL context in the reactor subscriber context. |
| DataFetcherExceptionHandler | GraphQL exception handler used from the various execution strategies, defaults to [KotlinDataFetcherExceptionHandler](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/graphql-kotlin-spring-server/src/main/kotlin/com/expediagroup/graphql/spring/exception/KotlinDataFetcherExceptionHandler.kt). |
| GraphQL | GraphQL query execution engine generated using `GraphQLSchema` with default async execution strategies. GraphQL engine can be customized by optionally providing a list of [Instrumentation](https://www.graphql-java.com/documentation/v13/instrumentation/) beans (which can be ordered by implementing Spring Ordered interface), [ExecutionIdProvider](https://github.com/graphql-java/graphql-java/blob/master/src/main/java/graphql/execution/ExecutionIdProvider.java) and [PreparsedDocumentProvider](https://github.com/graphql-java/graphql-java/blob/master/src/main/java/graphql/execution/preparsed/PreparsedDocumentProvider.java) in the application context. |
| DataLoaderRegistryFactory | Factory used to create DataLoaderRegistry instance per query execution. See [graphql-java documentation](https://www.graphql-java.com/documentation/v13/batching/) for more details. |
Expand All @@ -30,7 +31,6 @@ can be customized by providing custom beans in your application context. See sec

The following beans are currently automatically created and cannot be disabled:

* Web filter for generating and populating GraphQL context
* Default routes for GraphQL queries/mutations and SDL endpoint
* Default route for [Prisma Labs Playground](https://github.com/prisma-labs/graphql-playground), created only if playground is enabled
* Default `ApolloSubscriptionProtocolHandler` for handling GraphQL subscriptions, created only if `Subscription` bean is available in the context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.core.Ordered
import org.springframework.web.server.WebFilter
import java.util.Optional

/**
Expand Down Expand Up @@ -119,8 +118,9 @@ class GraphQLAutoConfiguration {
fun graphQLContextFactory(): GraphQLContextFactory<*> = EmptyContextFactory

@Bean
@ConditionalOnMissingBean
fun contextWebFilter(
config: GraphQLConfigurationProperties,
graphQLContextFactory: GraphQLContextFactory<*>
): WebFilter = ContextWebFilter(config, graphQLContextFactory)
): ContextWebFilter = ContextWebFilter(config, graphQLContextFactory)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ const val GRAPHQL_CONTEXT_FILTER_ODER = 0
/**
* Default web filter that populates GraphQL context in the reactor subscriber context.
*/
class ContextWebFilter(config: GraphQLConfigurationProperties, private val contextFactory: GraphQLContextFactory<Any>) : WebFilter, Ordered {
private val graphQLRoute = "/${config.endpoint}"
private val subscriptionsRoute = "/${config.subscriptions.endpoint}"
open class ContextWebFilter(config: GraphQLConfigurationProperties, private val contextFactory: GraphQLContextFactory<Any>) : WebFilter, Ordered {
private val graphQLRoute = enforceAbsolutePath(config.endpoint)
private val subscriptionsRoute = enforceAbsolutePath(config.subscriptions.endpoint)

@Suppress("ForbiddenVoid")
override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> =
Expand All @@ -51,6 +51,8 @@ class ContextWebFilter(config: GraphQLConfigurationProperties, private val conte

override fun getOrder(): Int = GRAPHQL_CONTEXT_FILTER_ODER

internal fun isApplicable(path: String): Boolean =
open fun isApplicable(path: String): Boolean =
graphQLRoute.equals(path, ignoreCase = true) || subscriptionsRoute.equals(path, ignoreCase = true)

private fun enforceAbsolutePath(path: String) = if (path.startsWith("/")) { path } else { "/$path" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.expediagroup.graphql.spring

import com.expediagroup.graphql.SchemaGeneratorConfig
import com.expediagroup.graphql.TopLevelObject
import com.expediagroup.graphql.spring.execution.ContextWebFilter
import com.expediagroup.graphql.spring.execution.DataLoaderRegistryFactory
import com.expediagroup.graphql.spring.execution.GraphQLContextFactory
import com.expediagroup.graphql.spring.execution.QueryHandler
Expand Down Expand Up @@ -75,6 +76,7 @@ class SchemaConfigurationTest {

assertThat(ctx).hasSingleBean(DataLoaderRegistryFactory::class.java)
assertThat(ctx).hasSingleBean(QueryHandler::class.java)
assertThat(ctx).hasSingleBean(ContextWebFilter::class.java)
assertThat(ctx).hasSingleBean(GraphQLContextFactory::class.java)
}
}
Expand All @@ -85,6 +87,7 @@ class SchemaConfigurationTest {
.withPropertyValues("graphql.packages=com.expediagroup.graphql.spring")
.run { ctx ->
val customConfiguration = ctx.getBean(CustomConfiguration::class.java)
val graphQLProperties = ctx.getBean(GraphQLConfigurationProperties::class.java)

assertThat(ctx).hasSingleBean(SchemaGeneratorConfig::class.java)
assertThat(ctx).getBean(SchemaGeneratorConfig::class.java)
Expand All @@ -104,6 +107,10 @@ class SchemaConfigurationTest {

assertThat(ctx).hasSingleBean(QueryHandler::class.java)

assertThat(ctx).hasSingleBean(ContextWebFilter::class.java)
assertThat(ctx).getBean(ContextWebFilter::class.java)
.isSameAs(customConfiguration.myCustomContextWebFilter(graphQLProperties, customConfiguration.myCustomContextFactory()))

assertThat(ctx).hasSingleBean(GraphQLContextFactory::class.java)
assertThat(ctx).getBean(GraphQLContextFactory::class.java)
.isSameAs(customConfiguration.myCustomContextFactory())
Expand Down Expand Up @@ -152,6 +159,16 @@ class SchemaConfigurationTest {

@Bean
fun myDataLoaderRegistryFactory(): DataLoaderRegistryFactory = mockk()

@Bean
fun myCustomContextWebFilter(
config: GraphQLConfigurationProperties,
graphQLContextFactory: GraphQLContextFactory<*>
): ContextWebFilter = object : ContextWebFilter(config, graphQLContextFactory) {
private val regex = config.endpoint.toRegex()

override fun isApplicable(path: String): Boolean = regex.matches(path)
}
}

class BasicQuery : Query {
Expand Down