Skip to content

Commit 2ab428a

Browse files
dariuszkucjmfayard
andauthored
add ktor server plugin module (ExpediaGroup#1667)
### 📝 Description Creates Ktor GraphQL Plugin with similar functionality as the existing SpringBoot auto-configuration module. ```kotlin fun Application.graphQLModule() { install(GraphQL) { schema { packages = listOf("com.example") queries = listOf(HelloWorldQuery()) } } } ``` ### 🔗 Related Issues Resolves: ExpediaGroup#1471 --------- Co-authored-by: Jean-Michel Fayard <jmfayard@gmail.com>
1 parent d013011 commit 2ab428a

File tree

27 files changed

+1773
-258
lines changed

27 files changed

+1773
-258
lines changed

examples/server/ktor-server/build.gradle.kts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ application {
1212
}
1313

1414
dependencies {
15-
implementation("com.expediagroup", "graphql-kotlin-server")
16-
implementation(libs.ktor.server.core)
15+
implementation("com.expediagroup", "graphql-kotlin-ktor-server")
1716
implementation(libs.ktor.server.netty)
1817
implementation(libs.logback)
1918
implementation(libs.kotlinx.coroutines.jdk8)
Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,29 @@
1616

1717
package com.expediagroup.graphql.examples.server.ktor
1818

19-
import com.expediagroup.graphql.generator.extensions.toGraphQLContext
2019
import com.expediagroup.graphql.examples.server.ktor.schema.models.User
21-
import com.expediagroup.graphql.server.execution.GraphQLContextFactory
20+
import com.expediagroup.graphql.generator.extensions.plus
21+
import com.expediagroup.graphql.server.ktor.DefaultKtorGraphQLContextFactory
2222
import io.ktor.server.request.ApplicationRequest
2323
import graphql.GraphQLContext
2424

2525
/**
2626
* Custom logic for how this example app should create its context given the [ApplicationRequest]
2727
*/
28-
class KtorGraphQLContextFactory : GraphQLContextFactory<ApplicationRequest> {
28+
class CustomGraphQLContextFactory : DefaultKtorGraphQLContextFactory() {
2929
override suspend fun generateContext(request: ApplicationRequest): GraphQLContext =
30-
mutableMapOf<Any, Any>(
31-
"user" to User(
32-
email = "fake@site.com",
33-
firstName = "Someone",
34-
lastName = "You Don't know",
35-
universityId = 4
36-
)
37-
).also { map ->
38-
request.headers["my-custom-header"]?.let { customHeader ->
39-
map["customHeader"] = customHeader
30+
super.generateContext(request).plus(
31+
mutableMapOf<Any, Any>(
32+
"user" to User(
33+
email = "fake@site.com",
34+
firstName = "Someone",
35+
lastName = "You Don't know",
36+
universityId = 4
37+
)
38+
).also { map ->
39+
request.headers["my-custom-header"]?.let { customHeader ->
40+
map["customHeader"] = customHeader
41+
}
4042
}
41-
}.toGraphQLContext()
43+
)
4244
}

examples/server/ktor-server/src/main/kotlin/com/expediagroup/graphql/examples/server/ktor/GraphQLModule.kt

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Expedia, Inc
2+
* Copyright 2023 Expedia, Inc
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,40 +13,42 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package com.expediagroup.graphql.examples.server.ktor
1817

19-
import com.expediagroup.graphql.generator.extensions.print
20-
import io.ktor.http.ContentType
18+
import com.expediagroup.graphql.dataloader.KotlinDataLoaderRegistryFactory
19+
import com.expediagroup.graphql.examples.server.ktor.schema.BookQueryService
20+
import com.expediagroup.graphql.examples.server.ktor.schema.CourseQueryService
21+
import com.expediagroup.graphql.examples.server.ktor.schema.HelloQueryService
22+
import com.expediagroup.graphql.examples.server.ktor.schema.LoginMutationService
23+
import com.expediagroup.graphql.examples.server.ktor.schema.UniversityQueryService
24+
import com.expediagroup.graphql.examples.server.ktor.schema.dataloaders.BookDataLoader
25+
import com.expediagroup.graphql.examples.server.ktor.schema.dataloaders.CourseDataLoader
26+
import com.expediagroup.graphql.examples.server.ktor.schema.dataloaders.UniversityDataLoader
27+
import com.expediagroup.graphql.server.ktor.GraphQL
2128
import io.ktor.server.application.Application
22-
import io.ktor.server.application.call
2329
import io.ktor.server.application.install
24-
import io.ktor.server.response.respondText
25-
import io.ktor.server.routing.Routing
26-
import io.ktor.server.routing.get
27-
import io.ktor.server.routing.post
28-
import io.ktor.server.routing.routing
2930

3031
fun Application.graphQLModule() {
31-
install(Routing)
32-
33-
routing {
34-
post("graphql") {
35-
KtorServer().handle(this.call)
32+
install(GraphQL) {
33+
schema {
34+
packages = listOf("com.expediagroup.graphql.examples.server")
35+
queries = listOf(
36+
HelloQueryService(),
37+
BookQueryService(),
38+
CourseQueryService(),
39+
UniversityQueryService(),
40+
)
41+
mutations = listOf(
42+
LoginMutationService()
43+
)
3644
}
37-
38-
get("sdl") {
39-
call.respondText(graphQLSchema.print())
45+
engine {
46+
dataLoaderRegistryFactory = KotlinDataLoaderRegistryFactory(
47+
UniversityDataLoader, CourseDataLoader, BookDataLoader
48+
)
4049
}
41-
42-
get("playground") {
43-
this.call.respondText(buildPlaygroundHtml("graphql", "subscriptions"), ContentType.Text.Html)
50+
server {
51+
contextFactory = CustomGraphQLContextFactory()
4452
}
4553
}
4654
}
47-
48-
private fun buildPlaygroundHtml(graphQLEndpoint: String, subscriptionsEndpoint: String) =
49-
Application::class.java.classLoader.getResource("graphql-playground.html")?.readText()
50-
?.replace("\${graphQLEndpoint}", graphQLEndpoint)
51-
?.replace("\${subscriptionsEndpoint}", subscriptionsEndpoint)
52-
?: throw IllegalStateException("graphql-playground.html cannot be found in the classpath")

examples/server/ktor-server/src/main/kotlin/com/expediagroup/graphql/examples/server/ktor/KtorGraphQLRequestParser.kt

Lines changed: 0 additions & 40 deletions
This file was deleted.

examples/server/ktor-server/src/main/kotlin/com/expediagroup/graphql/examples/server/ktor/KtorServer.kt

Lines changed: 0 additions & 48 deletions
This file was deleted.

examples/server/ktor-server/src/main/kotlin/com/expediagroup/graphql/examples/server/ktor/ktorGraphQLSchema.kt

Lines changed: 0 additions & 47 deletions
This file was deleted.

examples/server/ktor-server/src/main/resources/graphql-playground.html

Lines changed: 0 additions & 60 deletions
This file was deleted.

gradle/libs.versions.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "
6868
ktor-client-content = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" }
6969
ktor-client-serialization = { group = "io.ktor", name = "ktor-client-serialization", version.ref = "ktor" }
7070
ktor-serialization-jackson = { group = "io.ktor", name = "ktor-serialization-jackson", version.ref = "ktor" }
71+
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
72+
ktor-server-content = { group = "io.ktor", name = "ktor-server-content-negotiation", version.ref = "ktor" }
7173
maven-plugin-annotations = { group = "org.apache.maven.plugin-tools", name = "maven-plugin-annotations", version.ref = "maven-plugin-annotation" }
7274
maven-plugin-api = { group = "org.apache.maven", name = "maven-plugin-api", version.ref = "maven-plugin-api" }
7375
maven-project = { group = "org.apache.maven", name = "maven-project", version.ref = "maven-project" }
@@ -91,7 +93,6 @@ kotlinx-benchmark = { group = "org.jetbrains.kotlinx", name = "kotlinx-benchmark
9193
kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
9294
ktor-client-logging = { group = "io.ktor", name = "ktor-client-logging", version.ref = "ktor" }
9395
ktor-client-okhttp = { group = "io.ktor", name = "ktor-client-okhttp", version.ref = "ktor" }
94-
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
9596
ktor-server-cio = { group = "io.ktor", name = "ktor-server-cio", version.ref = "ktor" }
9697
ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty", version.ref = "ktor" }
9798
ktor-server-test-host = { group = "io.ktor", name = "ktor-server-test-host", version.ref = "ktor" }
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
description = "GraphQL plugin for Ktor servers"
2+
3+
plugins {
4+
id("com.expediagroup.graphql.conventions")
5+
}
6+
7+
dependencies {
8+
api(projects.graphqlKotlinServer)
9+
api(projects.graphqlKotlinFederation)
10+
api(libs.ktor.serialization.jackson)
11+
api(libs.ktor.server.core)
12+
api(libs.ktor.server.content)
13+
testImplementation(libs.kotlinx.coroutines.test)
14+
testImplementation(libs.ktor.client.content)
15+
testImplementation(libs.ktor.server.cio)
16+
testImplementation(libs.ktor.server.test.host)
17+
}
18+
19+
tasks {
20+
jacocoTestCoverageVerification {
21+
violationRules {
22+
rule {
23+
limit {
24+
counter = "INSTRUCTION"
25+
value = "COVEREDRATIO"
26+
minimum = "0.65".toBigDecimal()
27+
}
28+
limit {
29+
counter = "BRANCH"
30+
value = "COVEREDRATIO"
31+
minimum = "0.45".toBigDecimal()
32+
}
33+
}
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)