commit 4695b221dbfd4b35ff97b70dc9dd5821269ea08e
parent fb58c4a2a23092fb464551aa5b554b72996a24ba
Author: Marcello Stanisci <ms@taler.net>
Date: Fri, 8 May 2020 15:17:29 +0200
Add new-API nexus (excluded from compile now).
Diffstat:
2 files changed, 155 insertions(+), 0 deletions(-)
diff --git a/nexus/build.gradle b/nexus/build.gradle
@@ -1,4 +1,5 @@
plugins {
+ id 'kotlin'
id 'java'
id 'application'
id 'org.jetbrains.kotlin.jvm'
@@ -13,6 +14,11 @@ plugins {
id "com.github.johnrengelman.shadow" version "5.2.0"
}
+sourceSets {
+ main.kotlin.srcDirs = ["src/main/kotlin"]
+ main.kotlin.excludes = ["**/Main2.kt"]
+}
+
task installToPrefix(type: Copy) {
dependsOn(installShadowDist)
from("build/install/nexus-shadow") {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main2.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main2.kt
@@ -0,0 +1,148 @@
+package tech.libeufin.nexus
+
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2019 Stanisci and Dold.
+
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
+ * Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+import io.ktor.application.ApplicationCallPipeline
+import io.ktor.application.call
+import io.ktor.application.install
+import io.ktor.client.HttpClient
+import io.ktor.features.*
+import io.ktor.gson.gson
+import io.ktor.http.ContentType
+import io.ktor.http.HttpStatusCode
+import io.ktor.request.ApplicationReceivePipeline
+import io.ktor.request.ApplicationReceiveRequest
+import io.ktor.request.receive
+import io.ktor.request.uri
+import io.ktor.response.respond
+import io.ktor.response.respondText
+import io.ktor.routing.get
+import io.ktor.routing.post
+import io.ktor.routing.routing
+import io.ktor.server.engine.embeddedServer
+import io.ktor.server.netty.Netty
+import io.ktor.util.KtorExperimentalAPI
+import kotlinx.coroutines.io.ByteReadChannel
+import kotlinx.coroutines.io.jvm.javaio.toByteReadChannel
+import kotlinx.coroutines.io.jvm.javaio.toInputStream
+import kotlinx.io.core.ExperimentalIoApi
+import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.transactions.transaction
+import org.joda.time.DateTime
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.slf4j.event.Level
+import tech.libeufin.util.*
+import tech.libeufin.util.ebics_h004.HTDResponseOrderData
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+import java.util.*
+import java.util.zip.InflaterInputStream
+import javax.crypto.EncryptedPrivateKeyInfo
+import javax.sql.rowset.serial.SerialBlob
+
+
+data class NexusError(val statusCode: HttpStatusCode, val reason: String) : Exception()
+
+val logger: Logger = LoggerFactory.getLogger("tech.libeufin.nexus")
+
+fun isProduction(): Boolean {
+ return System.getenv("NEXUS_PRODUCTION") != null
+}
+
+@ExperimentalIoApi
+@KtorExperimentalAPI
+fun main() {
+ dbCreateTables()
+ val client = HttpClient() {
+ expectSuccess = false // this way, it does not throw exceptions on != 200 responses.
+ }
+ val server = embeddedServer(Netty, port = 5001) {
+
+ install(CallLogging) {
+ this.level = Level.DEBUG
+ this.logger = tech.libeufin.nexus.logger
+ }
+ install(ContentNegotiation) {
+ gson {
+ setDateFormat(DateFormat.LONG)
+ setPrettyPrinting()
+ }
+ }
+ install(StatusPages) {
+ exception<NexusError> { cause ->
+ logger.error("Exception while handling '${call.request.uri}'", cause)
+ call.respondText(
+ cause.reason,
+ ContentType.Text.Plain,
+ cause.statusCode
+ )
+ }
+ exception<UtilError> { cause ->
+ logger.error("Exception while handling '${call.request.uri}'", cause)
+ call.respondText(
+ cause.reason,
+ ContentType.Text.Plain,
+ cause.statusCode
+ )
+ }
+ exception<Exception> { cause ->
+ logger.error("Uncaught exception while handling '${call.request.uri}'", cause)
+ logger.error(cause.toString())
+ call.respondText(
+ "Internal server error",
+ ContentType.Text.Plain,
+ HttpStatusCode.InternalServerError
+ )
+ }
+ }
+
+ intercept(ApplicationCallPipeline.Fallback) {
+ if (this.call.response.status() == null) {
+ call.respondText("Not found (no route matched).\n", ContentType.Text.Plain, HttpStatusCode.NotFound)
+ return@intercept finish()
+ }
+ }
+
+ receivePipeline.intercept(ApplicationReceivePipeline.Before) {
+ if (this.context.request.headers["Content-Encoding"] == "deflate") {
+ logger.debug("About to inflate received data")
+ val deflated = this.subject.value as ByteReadChannel
+ val inflated = InflaterInputStream(deflated.toInputStream())
+ proceedWith(ApplicationReceiveRequest(this.subject.typeInfo, inflated.toByteReadChannel()))
+ return@intercept
+ }
+ proceed()
+ return@intercept
+ }
+
+ routing {
+
+ /** GENERAL / DEBUG ENDPOINTS */
+
+ get("/") {
+ call.respondText("Hello by Nexus!\n")
+ return@get
+ }
+ }
+ logger.info("Up and running")
+ server.start(wait = true)
+ }
+}
+\ No newline at end of file