mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 18:47:03 +05:30
sync-backend: initialize barebones module
This is simply an import of the project generated by start.ktor.io cleaned of its ungodly wildcard import fetish and better integrated into our existing build system.
This commit is contained in:
parent
b0bae12e6b
commit
5db4a1ee8d
12 changed files with 338 additions and 2 deletions
7
detekt-baselines/sync-backend.xml
Normal file
7
detekt-baselines/sync-backend.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" ?>
|
||||
<SmellBaseline>
|
||||
<ManuallySuppressedIssues></ManuallySuppressedIssues>
|
||||
<CurrentIssues>
|
||||
<ID>MagicNumber:HTTP.kt$443</ID>
|
||||
</CurrentIssues>
|
||||
</SmellBaseline>
|
|
@ -9,6 +9,7 @@ coroutines = "1.6.4"
|
|||
dagger = "2.44.2"
|
||||
kotest = "5.5.4"
|
||||
kotlin = "1.7.21"
|
||||
ktor = "2.2.1"
|
||||
# @pin Needs to be aligned with Retrofit
|
||||
okhttp = "3.14.9"
|
||||
retrofit = "2.9.0"
|
||||
|
@ -72,6 +73,20 @@ kotest-runner-junit5 = { module = "io.kotest:kotest-runner-junit5", version.ref
|
|||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
|
||||
kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "serialization" }
|
||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
||||
ktor-serialization-kotlinx-json-jvm = { module = "io.ktor:ktor-serialization-kotlinx-json-jvm", version.ref = "ktor" }
|
||||
ktor-server-auth-jvm = { module = "io.ktor:ktor-server-auth-jvm", version.ref = "ktor" }
|
||||
ktor-server-call-id-jvm = { module = "io.ktor:ktor-server-call-id-jvm", version.ref = "ktor" }
|
||||
ktor-server-call-logging-jvm = { module = "io.ktor:ktor-server-call-logging-jvm", version.ref = "ktor" }
|
||||
ktor-server-content-negotiation-jvm = { module = "io.ktor:ktor-server-content-negotiation-jvm", version.ref = "ktor" }
|
||||
ktor-server-core-jvm = { module = "io.ktor:ktor-server-core-jvm", version.ref = "ktor" }
|
||||
ktor-server-host-common-jvm = { module = "io.ktor:ktor-server-host-common-jvm", version.ref = "ktor" }
|
||||
ktor-server-hsts-jvm = { module = "io.ktor:ktor-server-hsts-jvm", version.ref = "ktor" }
|
||||
ktor-server-http-redirect-jvm = { module = "io.ktor:ktor-server-http-redirect-jvm", version.ref = "ktor" }
|
||||
ktor-server-locations-jvm = { module = "io.ktor:ktor-server-locations-jvm", version.ref = "ktor" }
|
||||
ktor-server-netty-jvm = { module = "io.ktor:ktor-server-netty-jvm", version.ref = "ktor" }
|
||||
ktor-server-status-pages-jvm = { module = "io.ktor:ktor-server-status-pages-jvm", version.ref = "ktor" }
|
||||
ktor-server-tests-jvm = { module = "io.ktor:ktor-server-tests-jvm", version.ref = "ktor" }
|
||||
logback-classic = "ch.qos.logback:logback-classic:1.2.11"
|
||||
napier = "io.github.aakira:napier:2.6.1"
|
||||
okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
||||
okhttp-loggingInterceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
|
||||
|
@ -88,5 +103,6 @@ whetstone = { module = "com.deliveryhero.whetstone:whetstone", version.ref = "wh
|
|||
android-test = { id = "com.android.test", version.ref = "agp" }
|
||||
anvil = "com.squareup.anvil:2.4.3"
|
||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||
ktor = { id = "io.ktor.plugin", version.ref = "ktor" }
|
||||
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
|
||||
whetstone = { id = "dev.msfjarvis.whetstone", version.ref = "whetstone" }
|
||||
|
|
|
@ -30,10 +30,16 @@ pluginManagement {
|
|||
forRepository { gradlePluginPortal() }
|
||||
filter {
|
||||
includeModule("com.github.ben-manes", "gradle-versions-plugin")
|
||||
includeModule(
|
||||
"com.github.johnrengelman.shadow",
|
||||
"com.github.johnrengelman.shadow.gradle.plugin"
|
||||
)
|
||||
includeModule("com.github.jengelman.gradle.plugins", "shadow")
|
||||
includeModule("org.gradle.android.cache-fix", "org.gradle.android.cache-fix.gradle.plugin")
|
||||
includeModule("gradle.plugin.com.google.cloud.tools", "jib-gradle-plugin")
|
||||
includeModule("gradle.plugin.org.gradle.android", "android-cache-fix-gradle-plugin")
|
||||
includeModule("com.sergei-lapin.napt", "com.sergei-lapin.napt.gradle.plugin")
|
||||
includeModule("com.sergei-lapin.napt", "gradle")
|
||||
includeModule("io.ktor.plugin", "io.ktor.plugin.gradle.plugin")
|
||||
includeModule("io.ktor.plugin", "plugin")
|
||||
}
|
||||
}
|
||||
exclusiveContent {
|
||||
|
@ -133,4 +139,5 @@ include(
|
|||
"database",
|
||||
"metadata-extractor",
|
||||
"model",
|
||||
"sync-backend",
|
||||
)
|
||||
|
|
45
sync-backend/build.gradle.kts
Normal file
45
sync-backend/build.gradle.kts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
|
||||
|
||||
plugins {
|
||||
application
|
||||
kotlin("jvm")
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
id("dev.msfjarvis.claw.kotlin-common")
|
||||
alias(libs.plugins.ktor)
|
||||
}
|
||||
|
||||
group = "dev.msfjarvis.claw"
|
||||
|
||||
version = "0.0.1"
|
||||
|
||||
application {
|
||||
mainClass.set("dev.msfjarvis.claw.sync.ApplicationKt")
|
||||
|
||||
val isDevelopment: Boolean = providers.gradleProperty("development").isPresent
|
||||
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.ktor.serialization.kotlinx.json.jvm)
|
||||
implementation(libs.ktor.server.auth.jvm)
|
||||
implementation(libs.ktor.server.call.id.jvm)
|
||||
implementation(libs.ktor.server.call.logging.jvm)
|
||||
implementation(libs.ktor.server.content.negotiation.jvm)
|
||||
implementation(libs.ktor.server.core.jvm)
|
||||
implementation(libs.ktor.server.host.common.jvm)
|
||||
implementation(libs.ktor.server.hsts.jvm)
|
||||
implementation(libs.ktor.server.http.redirect.jvm)
|
||||
implementation(libs.ktor.server.locations.jvm)
|
||||
implementation(libs.ktor.server.netty.jvm)
|
||||
implementation(libs.ktor.server.status.pages.jvm)
|
||||
implementation(libs.ktor.server.tests.jvm)
|
||||
implementation(libs.logback.classic)
|
||||
testImplementation(libs.kotest.assertions.core)
|
||||
testImplementation(libs.kotest.runner.junit5)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.sync
|
||||
|
||||
import dev.msfjarvis.claw.sync.plugins.configureHTTP
|
||||
import dev.msfjarvis.claw.sync.plugins.configureMonitoring
|
||||
import dev.msfjarvis.claw.sync.plugins.configureRouting
|
||||
import dev.msfjarvis.claw.sync.plugins.configureSecurity
|
||||
import dev.msfjarvis.claw.sync.plugins.configureSerialization
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.engine.embeddedServer
|
||||
import io.ktor.server.netty.Netty
|
||||
|
||||
fun main() {
|
||||
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
|
||||
.start(wait = true)
|
||||
}
|
||||
|
||||
fun Application.module() {
|
||||
configureSerialization()
|
||||
configureMonitoring()
|
||||
configureHTTP()
|
||||
configureSecurity()
|
||||
configureRouting()
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.sync.plugins
|
||||
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.plugins.hsts.HSTS
|
||||
import io.ktor.server.plugins.httpsredirect.HttpsRedirect
|
||||
|
||||
fun Application.configureHTTP() {
|
||||
if (!developmentMode) {
|
||||
install(HttpsRedirect) {
|
||||
// The port to redirect to. By default 443, the default HTTPS port.
|
||||
sslPort = 443
|
||||
// 301 Moved Permanently, or 302 Found redirect.
|
||||
permanentRedirect = true
|
||||
}
|
||||
install(HSTS) { includeSubDomains = true }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.sync.plugins
|
||||
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.plugins.callid.CallId
|
||||
import io.ktor.server.plugins.callid.callIdMdc
|
||||
import io.ktor.server.plugins.callloging.CallLogging
|
||||
import io.ktor.server.request.path
|
||||
import org.slf4j.event.Level
|
||||
|
||||
fun Application.configureMonitoring() {
|
||||
install(CallLogging) {
|
||||
level = Level.INFO
|
||||
filter { call -> call.request.path().startsWith("/") }
|
||||
callIdMdc("call-id")
|
||||
}
|
||||
install(CallId) {
|
||||
header(HttpHeaders.XRequestId)
|
||||
verify { callId: String -> callId.isNotEmpty() }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
@file:OptIn(KtorExperimentalLocationsAPI::class)
|
||||
|
||||
package dev.msfjarvis.claw.sync.plugins
|
||||
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.server.locations.Location
|
||||
import io.ktor.server.locations.Locations
|
||||
import io.ktor.server.locations.get
|
||||
import io.ktor.server.plugins.autohead.AutoHeadResponse
|
||||
import io.ktor.server.plugins.doublereceive.DoubleReceive
|
||||
import io.ktor.server.plugins.statuspages.StatusPages
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.respondText
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.routing
|
||||
|
||||
fun Application.configureRouting() {
|
||||
install(StatusPages) {
|
||||
exception<AuthenticationException> { call, _ -> call.respond(HttpStatusCode.Unauthorized) }
|
||||
exception<AuthorizationException> { call, _ -> call.respond(HttpStatusCode.Forbidden) }
|
||||
}
|
||||
install(Locations) {}
|
||||
install(DoubleReceive)
|
||||
install(AutoHeadResponse)
|
||||
|
||||
routing {
|
||||
get("/") { call.respondText("Hello World!") }
|
||||
get<MyLocation> {
|
||||
call.respondText("Location: name=${it.name}, arg1=${it.arg1}, arg2=${it.arg2}")
|
||||
}
|
||||
// Register nested routes
|
||||
get<Type.Edit> { call.respondText("Inside $it") }
|
||||
get<Type.List> { call.respondText("Inside $it") }
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationException : RuntimeException()
|
||||
|
||||
class AuthorizationException : RuntimeException()
|
||||
|
||||
@Location("/location/{name}")
|
||||
class MyLocation(val name: String, val arg1: Int = 42, val arg2: String = "default")
|
||||
|
||||
@Location("/type/{name}")
|
||||
data class Type(val name: String) {
|
||||
@Location("/edit") data class Edit(val type: Type)
|
||||
|
||||
@Location("/list/{page}") data class List(val type: Type, val page: Int)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.sync.plugins
|
||||
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.auth.UserIdPrincipal
|
||||
import io.ktor.server.auth.authenticate
|
||||
import io.ktor.server.auth.authentication
|
||||
import io.ktor.server.auth.basic
|
||||
import io.ktor.server.auth.form
|
||||
import io.ktor.server.auth.principal
|
||||
import io.ktor.server.response.respondText
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.routing
|
||||
|
||||
fun Application.configureSecurity() {
|
||||
|
||||
authentication {
|
||||
basic(name = "myauth1") {
|
||||
realm = "Ktor Server"
|
||||
validate { credentials ->
|
||||
if (credentials.name == credentials.password) {
|
||||
UserIdPrincipal(credentials.name)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
form(name = "myauth2") {
|
||||
userParamName = "user"
|
||||
passwordParamName = "password"
|
||||
challenge {
|
||||
/**/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
routing {
|
||||
authenticate("myauth1") {
|
||||
get("/protected/route/basic") {
|
||||
val principal = call.principal<UserIdPrincipal>()
|
||||
call.respondText("Hello ${principal?.name}")
|
||||
}
|
||||
}
|
||||
authenticate("myauth2") {
|
||||
get("/protected/route/form") {
|
||||
val principal = call.principal<UserIdPrincipal>()
|
||||
call.respondText("Hello ${principal?.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.sync.plugins
|
||||
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.routing
|
||||
|
||||
fun Application.configureSerialization() {
|
||||
install(ContentNegotiation) { json() }
|
||||
|
||||
routing { get("/json/kotlinx-serialization") { call.respond(mapOf("hello" to "world")) } }
|
||||
}
|
12
sync-backend/src/main/resources/logback.xml
Normal file
12
sync-backend/src/main/resources/logback.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %X{call-id} %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="io.netty" level="INFO"/>
|
||||
</configuration>
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright © 2022 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.sync
|
||||
|
||||
import dev.msfjarvis.claw.sync.plugins.configureRouting
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.testing.testApplication
|
||||
|
||||
class ApplicationTest : FunSpec() {
|
||||
init {
|
||||
test("testRoot") {
|
||||
testApplication {
|
||||
application { configureRouting() }
|
||||
client.get("/").apply {
|
||||
status shouldBe HttpStatusCode.OK
|
||||
bodyAsText() shouldBe "Hello World!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue