diff options
7 files changed, 191 insertions, 136 deletions
diff --git a/kvision-modules/kvision-common-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt b/kvision-modules/kvision-common-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt index 224a8542..514fb07d 100644 --- a/kvision-modules/kvision-common-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt +++ b/kvision-modules/kvision-common-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt @@ -23,13 +23,6 @@ package pl.treksoft.kvision.remote import kotlin.reflect.KClass -enum class RpcHttpMethod { - POST, - PUT, - DELETE, - OPTIONS -} - enum class HttpMethod { GET, POST, @@ -46,73 +39,73 @@ expect open class KVServiceManager<T : Any>(serviceClass: KClass<T>) { /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected inline fun <reified RET> bind( noinline function: suspend T.() -> RET, - route: String? = null, - method: RpcHttpMethod = RpcHttpMethod.POST + method: HttpMethod = HttpMethod.POST, + route: String? = null ) /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected inline fun <reified PAR, reified RET> bind( noinline function: suspend T.(PAR) -> RET, - route: String? = null, - method: RpcHttpMethod = RpcHttpMethod.POST + method: HttpMethod = HttpMethod.POST, + route: String? = null ) /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected inline fun <reified PAR1, reified PAR2, reified RET> bind( noinline function: suspend T.(PAR1, PAR2) -> RET, - route: String? = null, - method: RpcHttpMethod = RpcHttpMethod.POST + method: HttpMethod = HttpMethod.POST, + route: String? = null ) /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected inline fun <reified PAR1, reified PAR2, reified PAR3, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, - route: String? = null, - method: RpcHttpMethod = RpcHttpMethod.POST + method: HttpMethod = HttpMethod.POST, + route: String? = null ) /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, - route: String? = null, - method: RpcHttpMethod = RpcHttpMethod.POST + method: HttpMethod = HttpMethod.POST, + route: String? = null ) /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified PAR5, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, - route: String? = null, - method: RpcHttpMethod = RpcHttpMethod.POST + method: HttpMethod = HttpMethod.POST, + route: String? = null ) /** diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/CallAgent.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/CallAgent.kt index 4a086e2a..e9f0dd15 100644 --- a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/CallAgent.kt +++ b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/CallAgent.kt @@ -56,37 +56,41 @@ open class CallAgent { fun jsonRpcCall( url: String, data: List<String?> = listOf(), - method: RpcHttpMethod = RpcHttpMethod.POST + method: HttpMethod = HttpMethod.POST ): Promise<String> { val jsonRpcRequest = JsonRpcRequest(counter++, url, data) - val jsonData = JSON.plain.stringify(jsonRpcRequest) + val jsonData = if (method == HttpMethod.GET) { + obj { id = jsonRpcRequest.id } + } else { + JSON.plain.stringify(jsonRpcRequest) + } return Promise { resolve, reject -> jQuery.ajax(url, obj { this.contentType = "application/json" this.data = jsonData this.method = method.name this.success = - { data: dynamic, _: Any, _: Any -> - when { - data.id != jsonRpcRequest.id -> reject(Exception("Invalid response ID")) - data.error != null -> reject(Exception(data.error.toString())) - data.result != null -> resolve(data.result) - else -> reject(Exception("Invalid response")) - } + { data: dynamic, _: Any, _: Any -> + when { + data.id != jsonRpcRequest.id -> reject(Exception("Invalid response ID")) + data.error != null -> reject(Exception(data.error.toString())) + data.result != null -> resolve(data.result) + else -> reject(Exception("Invalid response")) } + } this.error = - { xhr: JQueryXHR, _: String, errorText: String -> - val message = if (xhr.responseJSON != null && xhr.responseJSON != undefined) { - xhr.responseJSON.toString() - } else { - errorText - } - if (xhr.status.toInt() == HTTP_UNAUTHORIZED) { - reject(SecurityException(message)) - } else { - reject(Exception(message)) - } + { xhr: JQueryXHR, _: String, errorText: String -> + val message = if (xhr.responseJSON != null && xhr.responseJSON != undefined) { + xhr.responseJSON.toString() + } else { + errorText + } + if (xhr.status.toInt() == HTTP_UNAUTHORIZED) { + reject(SecurityException(message)) + } else { + reject(Exception(message)) } + } }) } } @@ -112,22 +116,22 @@ open class CallAgent { this.data = data this.method = method.name this.success = - { data: dynamic, _: Any, _: Any -> - resolve(data) - } + { data: dynamic, _: Any, _: Any -> + resolve(data) + } this.error = - { xhr: JQueryXHR, _: String, errorText: String -> - val message = if (xhr.responseJSON != null && xhr.responseJSON != undefined) { - xhr.responseJSON.toString() - } else { - errorText - } - if (xhr.status.toInt() == HTTP_UNAUTHORIZED) { - reject(SecurityException(message)) - } else { - reject(Exception(message)) - } + { xhr: JQueryXHR, _: String, errorText: String -> + val message = if (xhr.responseJSON != null && xhr.responseJSON != undefined) { + xhr.responseJSON.toString() + } else { + errorText + } + if (xhr.status.toInt() == HTTP_UNAUTHORIZED) { + reject(SecurityException(message)) + } else { + reject(Exception(message)) } + } this.beforeSend = beforeSend }) } diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt index c13c4c18..4ca6a4a5 100644 --- a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt +++ b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt @@ -28,18 +28,18 @@ import kotlin.reflect.KClass */ actual open class KVServiceManager<T : Any> actual constructor(serviceClass: KClass<T>) { - protected val calls: MutableMap<String, Pair<String, RpcHttpMethod>> = mutableMapOf() + protected val calls: MutableMap<String, Pair<String, HttpMethod>> = mutableMapOf() var counter: Int = 0 /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected actual inline fun <reified RET> bind( noinline function: suspend T.() -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { val routeDef = route ?: "route${this::class.simpleName}${counter++}" calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) @@ -48,13 +48,15 @@ actual open class KVServiceManager<T : Any> actual constructor(serviceClass: KCl /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected actual inline fun <reified PAR, reified RET> bind( noinline function: suspend T.(PAR) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) } @@ -62,13 +64,15 @@ actual open class KVServiceManager<T : Any> actual constructor(serviceClass: KCl /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected actual inline fun <reified PAR1, reified PAR2, reified RET> bind( noinline function: suspend T.(PAR1, PAR2) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) } @@ -76,13 +80,15 @@ actual open class KVServiceManager<T : Any> actual constructor(serviceClass: KCl /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) } @@ -90,13 +96,15 @@ actual open class KVServiceManager<T : Any> actual constructor(serviceClass: KCl /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) } @@ -104,15 +112,16 @@ actual open class KVServiceManager<T : Any> actual constructor(serviceClass: KCl /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified PAR5, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, - route: String?, - method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) } @@ -125,12 +134,12 @@ actual open class KVServiceManager<T : Any> actual constructor(serviceClass: KCl function: T.(String?, String?) -> List<RemoteSelectOption> ) { val routeDef = "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", RpcHttpMethod.POST) + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", HttpMethod.POST) } /** * Returns the map of defined paths. */ - fun getCalls(): Map<String, Pair<String, RpcHttpMethod>> = calls + fun getCalls(): Map<String, Pair<String, HttpMethod>> = calls } diff --git a/kvision-modules/kvision-server-jooby/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt b/kvision-modules/kvision-server-jooby/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt index bff27798..3617463b 100644 --- a/kvision-modules/kvision-server-jooby/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt +++ b/kvision-modules/kvision-server-jooby/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt @@ -54,18 +54,22 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified RET> bind( noinline function: suspend T.() -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { val routeDef = route ?: "route${this::class.simpleName}${counter++}" routes.add { call(method, "/kv/$routeDef") { req, res -> - val jsonRpcRequest = req.body(JsonRpcRequest::class.java) + val jsonRpcRequest = if (method == HttpMethod.GET) { + JsonRpcRequest(req.param("id").intValue(), "", listOf()) + } else { + req.body(JsonRpcRequest::class.java) + } val service = req.require(serviceClass.java) val injector = req.require(Injector::class.java) injector.injectMembers(service) @@ -90,14 +94,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR, reified RET> bind( noinline function: suspend T.(PAR) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" routes.add { call(method, "/kv/$routeDef") { req, res -> @@ -131,14 +137,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified RET> bind( noinline function: suspend T.(PAR1, PAR2) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" routes.add { call(method, "/kv/$routeDef") { req, res -> @@ -173,14 +181,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" routes.add { call(method, "/kv/$routeDef") { req, res -> @@ -217,14 +227,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" routes.add { call(method, "/kv/$routeDef") { req, res -> @@ -262,16 +274,17 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified PAR5, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, - route: String?, - method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" routes.add { call(method, "/kv/$routeDef") { req, res -> @@ -317,7 +330,7 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: ) { val routeDef = "route${this::class.simpleName}${counter++}" routes.add { - call(RpcHttpMethod.POST, "/kv/$routeDef") { req, res -> + call(HttpMethod.POST, "/kv/$routeDef") { req, res -> val jsonRpcRequest = req.body(JsonRpcRequest::class.java) val service = req.require(serviceClass.java) val injector = req.require(Injector::class.java) @@ -347,16 +360,17 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: } fun call( - method: RpcHttpMethod, + method: HttpMethod, path: String, handler: (Request, Response) -> Unit ): Kooby.() -> Unit { return { when (method) { - RpcHttpMethod.POST -> post(path, handler) - RpcHttpMethod.PUT -> put(path, handler) - RpcHttpMethod.DELETE -> delete(path, handler) - RpcHttpMethod.OPTIONS -> options(path, handler) + HttpMethod.GET -> get(path, handler) + HttpMethod.POST -> post(path, handler) + HttpMethod.PUT -> put(path, handler) + HttpMethod.DELETE -> delete(path, handler) + HttpMethod.OPTIONS -> options(path, handler) } } } diff --git a/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt b/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt index fbc94f64..4b67bf43 100644 --- a/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt +++ b/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt @@ -28,6 +28,7 @@ import io.ktor.request.receive import io.ktor.response.respond import io.ktor.routing.Route import io.ktor.routing.delete +import io.ktor.routing.get import io.ktor.routing.options import io.ktor.routing.post import io.ktor.routing.put @@ -49,6 +50,7 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: val LOG: Logger = LoggerFactory.getLogger(KVServiceManager::class.java.name) } + val getRequests: MutableMap<String, suspend PipelineContext<Unit, ApplicationCall>.(Unit) -> Unit> = mutableMapOf() val postRequests: MutableMap<String, suspend PipelineContext<Unit, ApplicationCall>.(Unit) -> Unit> = mutableMapOf() val putRequests: MutableMap<String, suspend PipelineContext<Unit, ApplicationCall>.(Unit) -> Unit> = mutableMapOf() val deleteRequests: MutableMap<String, suspend PipelineContext<Unit, ApplicationCall>.(Unit) -> Unit> = @@ -64,18 +66,22 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified RET> bind( noinline function: suspend T.() -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { val service = call.injector.getInstance(serviceClass.java) - val jsonRpcRequest = call.receive<JsonRpcRequest>() + val jsonRpcRequest = if (method == HttpMethod.GET) { + JsonRpcRequest(call.request.queryParameters["id"]?.toInt() ?: 0, "", listOf()) + } else { + call.receive() + } try { val result = function.invoke(service) call.respond( @@ -99,14 +105,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR, reified RET> bind( noinline function: suspend T.(PAR) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { val service = call.injector.getInstance(serviceClass.java) @@ -144,14 +152,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified RET> bind( noinline function: suspend T.(PAR1, PAR2) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { val service = call.injector.getInstance(serviceClass.java) @@ -190,14 +200,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { val service = call.injector.getInstance(serviceClass.java) @@ -238,14 +250,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { val service = call.injector.getInstance(serviceClass.java) @@ -287,16 +301,17 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified PAR5, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, - route: String?, - method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { val service = call.injector.getInstance(serviceClass.java) @@ -345,7 +360,7 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: function: T.(String?, String?) -> List<RemoteSelectOption> ) { val routeDef = "route${this::class.simpleName}${counter++}" - addRoute(RpcHttpMethod.POST, "/kv/$routeDef") { + addRoute(HttpMethod.POST, "/kv/$routeDef") { val service = call.injector.getInstance(serviceClass.java) val jsonRpcRequest = call.receive<JsonRpcRequest>() if (jsonRpcRequest.params.size == 2) { @@ -380,15 +395,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: } fun addRoute( - method: RpcHttpMethod, + method: HttpMethod, path: String, handler: suspend PipelineContext<Unit, ApplicationCall>.(Unit) -> Unit ) { when (method) { - RpcHttpMethod.POST -> postRequests[path] = handler - RpcHttpMethod.PUT -> putRequests[path] = handler - RpcHttpMethod.DELETE -> deleteRequests[path] = handler - RpcHttpMethod.OPTIONS -> optionsRequests[path] = handler + HttpMethod.GET -> getRequests[path] = handler + HttpMethod.POST -> postRequests[path] = handler + HttpMethod.PUT -> putRequests[path] = handler + HttpMethod.DELETE -> deleteRequests[path] = handler + HttpMethod.OPTIONS -> optionsRequests[path] = handler } } @@ -404,6 +420,9 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: } fun <T : Any> Route.applyRoutes(serviceManager: KVServiceManager<T>) { + serviceManager.getRequests.forEach { (path, handler) -> + get(path, handler) + } serviceManager.postRequests.forEach { (path, handler) -> post(path, handler) } diff --git a/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVController.kt b/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVController.kt index 50544dc1..86789705 100644 --- a/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVController.kt +++ b/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVController.kt @@ -36,12 +36,13 @@ open class KVController { @RequestMapping( "/kv/**", - method = [RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS] + method = [RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS] ) open fun kVMapping(req: HttpServletRequest, res: HttpServletResponse) { val routeUrl = req.requestURI val route = kvServer.services.mapNotNull { when (req.method) { + "GET" -> it.getRequests[routeUrl] "POST" -> it.postRequests[routeUrl] "PUT" -> it.putRequests[routeUrl] "DELETE" -> it.deleteRequests[routeUrl] diff --git a/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt b/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt index 4820fb2e..4705b0b1 100644 --- a/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt +++ b/kvision-modules/kvision-server-spring-boot/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt @@ -44,6 +44,7 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: val LOG: Logger = LoggerFactory.getLogger(KVServiceManager::class.java.name) } + val getRequests: MutableMap<String, (HttpServletRequest, HttpServletResponse) -> Unit> = mutableMapOf() val postRequests: MutableMap<String, (HttpServletRequest, HttpServletResponse) -> Unit> = mutableMapOf() val putRequests: MutableMap<String, (HttpServletRequest, HttpServletResponse) -> Unit> = mutableMapOf() val deleteRequests: MutableMap<String, (HttpServletRequest, HttpServletResponse) -> Unit> = mutableMapOf() @@ -57,18 +58,22 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified RET> bind( noinline function: suspend T.() -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { req, res -> val service = SpringContext.getBean(serviceClass.java) - val jsonRpcRequest = mapper.readValue(req.inputStream, JsonRpcRequest::class.java) + val jsonRpcRequest = if (method == HttpMethod.GET) { + JsonRpcRequest(req.getParameter("id")?.toInt() ?: 0, "", listOf()) + } else { + mapper.readValue(req.inputStream, JsonRpcRequest::class.java) + } GlobalScope.launch(start = CoroutineStart.UNDISPATCHED) { try { val result = function.invoke(service) @@ -98,14 +103,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR, reified RET> bind( noinline function: suspend T.(PAR) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { req, res -> val service = SpringContext.getBean(serviceClass.java) @@ -151,14 +158,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified RET> bind( noinline function: suspend T.(PAR1, PAR2) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { req, res -> val service = SpringContext.getBean(serviceClass.java) @@ -205,14 +214,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { req, res -> val service = SpringContext.getBean(serviceClass.java) @@ -261,14 +272,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, - route: String?, method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { req, res -> val service = SpringContext.getBean(serviceClass.java) @@ -318,16 +331,17 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: /** * Binds a given route with a function of the receiver. * @param function a function of the receiver - * @param route a route * @param method a HTTP method + * @param route a route */ @Suppress("TooGenericExceptionCaught") protected actual inline fun <reified PAR1, reified PAR2, reified PAR3, reified PAR4, reified PAR5, reified RET> bind( noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, - route: String?, - method: RpcHttpMethod + method: HttpMethod, route: String? ) { + if (method == HttpMethod.GET) + throw UnsupportedOperationException("GET method is only supported for methods without parameters") val routeDef = route ?: "route${this::class.simpleName}${counter++}" addRoute(method, "/kv/$routeDef") { req, res -> val service = SpringContext.getBean(serviceClass.java) @@ -384,7 +398,7 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: function: T.(String?, String?) -> List<RemoteSelectOption> ) { val routeDef = "route${this::class.simpleName}${counter++}" - addRoute(RpcHttpMethod.POST, "/kv/$routeDef") { req, res -> + addRoute(HttpMethod.POST, "/kv/$routeDef") { req, res -> val service = SpringContext.getBean(serviceClass.java) val jsonRpcRequest = mapper.readValue(req.inputStream, JsonRpcRequest::class.java) if (jsonRpcRequest.params.size == 2) { @@ -425,15 +439,16 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: } fun addRoute( - method: RpcHttpMethod, + method: HttpMethod, path: String, handler: (HttpServletRequest, HttpServletResponse) -> Unit ) { when (method) { - RpcHttpMethod.POST -> postRequests[path] = handler - RpcHttpMethod.PUT -> putRequests[path] = handler - RpcHttpMethod.DELETE -> deleteRequests[path] = handler - RpcHttpMethod.OPTIONS -> optionsRequests[path] = handler + HttpMethod.GET -> getRequests[path] = handler + HttpMethod.POST -> postRequests[path] = handler + HttpMethod.PUT -> putRequests[path] = handler + HttpMethod.DELETE -> deleteRequests[path] = handler + HttpMethod.OPTIONS -> optionsRequests[path] = handler } } |