Skip to content

add ktor server plugin module #1667

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

Merged
merged 8 commits into from
Feb 9, 2023
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
3 changes: 1 addition & 2 deletions examples/server/ktor-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ application {
}

dependencies {
implementation("com.expediagroup", "graphql-kotlin-server")
implementation(libs.ktor.server.core)
implementation("com.expediagroup", "graphql-kotlin-ktor-server")
implementation(libs.ktor.server.netty)
implementation(libs.logback)
implementation(libs.kotlinx.coroutines.jdk8)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,29 @@

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

import com.expediagroup.graphql.generator.extensions.toGraphQLContext
import com.expediagroup.graphql.examples.server.ktor.schema.models.User
import com.expediagroup.graphql.server.execution.GraphQLContextFactory
import com.expediagroup.graphql.generator.extensions.plus
import com.expediagroup.graphql.server.ktor.DefaultKtorGraphQLContextFactory
import io.ktor.server.request.ApplicationRequest
import graphql.GraphQLContext

/**
* Custom logic for how this example app should create its context given the [ApplicationRequest]
*/
class KtorGraphQLContextFactory : GraphQLContextFactory<ApplicationRequest> {
class CustomGraphQLContextFactory : DefaultKtorGraphQLContextFactory() {
override suspend fun generateContext(request: ApplicationRequest): GraphQLContext =
mutableMapOf<Any, Any>(
"user" to User(
email = "[email protected]",
firstName = "Someone",
lastName = "You Don't know",
universityId = 4
)
).also { map ->
request.headers["my-custom-header"]?.let { customHeader ->
map["customHeader"] = customHeader
super.generateContext(request).plus(
mutableMapOf<Any, Any>(
"user" to User(
email = "[email protected]",
firstName = "Someone",
lastName = "You Don't know",
universityId = 4
)
).also { map ->
request.headers["my-custom-header"]?.let { customHeader ->
map["customHeader"] = customHeader
}
}
}.toGraphQLContext()
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Expedia, Inc
* Copyright 2023 Expedia, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -13,40 +13,42 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import com.expediagroup.graphql.generator.extensions.print
import io.ktor.http.ContentType
import com.expediagroup.graphql.dataloader.KotlinDataLoaderRegistryFactory
import com.expediagroup.graphql.examples.server.ktor.schema.BookQueryService
import com.expediagroup.graphql.examples.server.ktor.schema.CourseQueryService
import com.expediagroup.graphql.examples.server.ktor.schema.HelloQueryService
import com.expediagroup.graphql.examples.server.ktor.schema.LoginMutationService
import com.expediagroup.graphql.examples.server.ktor.schema.UniversityQueryService
import com.expediagroup.graphql.examples.server.ktor.schema.dataloaders.BookDataLoader
import com.expediagroup.graphql.examples.server.ktor.schema.dataloaders.CourseDataLoader
import com.expediagroup.graphql.examples.server.ktor.schema.dataloaders.UniversityDataLoader
import com.expediagroup.graphql.server.ktor.GraphQL
import io.ktor.server.application.Application
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.response.respondText
import io.ktor.server.routing.Routing
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.routing

fun Application.graphQLModule() {
install(Routing)

routing {
post("graphql") {
KtorServer().handle(this.call)
install(GraphQL) {
schema {
packages = listOf("com.expediagroup.graphql.examples.server")
queries = listOf(
HelloQueryService(),
BookQueryService(),
CourseQueryService(),
UniversityQueryService(),
)
mutations = listOf(
LoginMutationService()
)
}

get("sdl") {
call.respondText(graphQLSchema.print())
engine {
dataLoaderRegistryFactory = KotlinDataLoaderRegistryFactory(
UniversityDataLoader, CourseDataLoader, BookDataLoader
)
}

get("playground") {
this.call.respondText(buildPlaygroundHtml("graphql", "subscriptions"), ContentType.Text.Html)
server {
contextFactory = CustomGraphQLContextFactory()
}
}
}

private fun buildPlaygroundHtml(graphQLEndpoint: String, subscriptionsEndpoint: String) =
Application::class.java.classLoader.getResource("graphql-playground.html")?.readText()
?.replace("\${graphQLEndpoint}", graphQLEndpoint)
?.replace("\${subscriptionsEndpoint}", subscriptionsEndpoint)
?: throw IllegalStateException("graphql-playground.html cannot be found in the classpath")

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "
ktor-client-content = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" }
ktor-client-serialization = { group = "io.ktor", name = "ktor-client-serialization", version.ref = "ktor" }
ktor-serialization-jackson = { group = "io.ktor", name = "ktor-serialization-jackson", version.ref = "ktor" }
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
ktor-server-content = { group = "io.ktor", name = "ktor-server-content-negotiation", version.ref = "ktor" }
maven-plugin-annotations = { group = "org.apache.maven.plugin-tools", name = "maven-plugin-annotations", version.ref = "maven-plugin-annotation" }
maven-plugin-api = { group = "org.apache.maven", name = "maven-plugin-api", version.ref = "maven-plugin-api" }
maven-project = { group = "org.apache.maven", name = "maven-project", version.ref = "maven-project" }
Expand All @@ -91,7 +93,6 @@ kotlinx-benchmark = { group = "org.jetbrains.kotlinx", name = "kotlinx-benchmark
kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
ktor-client-logging = { group = "io.ktor", name = "ktor-client-logging", version.ref = "ktor" }
ktor-client-okhttp = { group = "io.ktor", name = "ktor-client-okhttp", version.ref = "ktor" }
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
ktor-server-cio = { group = "io.ktor", name = "ktor-server-cio", version.ref = "ktor" }
ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty", version.ref = "ktor" }
ktor-server-test-host = { group = "io.ktor", name = "ktor-server-test-host", version.ref = "ktor" }
Expand Down
36 changes: 36 additions & 0 deletions servers/graphql-kotlin-ktor-server/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
description = "GraphQL plugin for Ktor servers"

plugins {
id("com.expediagroup.graphql.conventions")
}

dependencies {
api(projects.graphqlKotlinServer)
api(projects.graphqlKotlinFederation)
api(libs.ktor.serialization.jackson)
api(libs.ktor.server.core)
api(libs.ktor.server.content)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.ktor.client.content)
testImplementation(libs.ktor.server.cio)
testImplementation(libs.ktor.server.test.host)
}

tasks {
jacocoTestCoverageVerification {
violationRules {
rule {
limit {
counter = "INSTRUCTION"
value = "COVEREDRATIO"
minimum = "0.65".toBigDecimal()
}
limit {
counter = "BRANCH"
value = "COVEREDRATIO"
minimum = "0.45".toBigDecimal()
}
}
}
}
}
Loading