libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

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:
Mnexus/build.gradle | 6++++++
Anexus/src/main/kotlin/tech/libeufin/nexus/Main2.kt | 149+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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