Shamrock: fix #68

This commit is contained in:
WhiteChi 2023-11-21 21:09:07 +08:00
parent 2c49b10772
commit fcf18bd3fd
3 changed files with 55 additions and 44 deletions

View File

@ -17,10 +17,12 @@ import moe.fuqiuluo.shamrock.remote.config.ECHO_KEY
import moe.fuqiuluo.shamrock.remote.entries.EmptyObject import moe.fuqiuluo.shamrock.remote.entries.EmptyObject
import moe.fuqiuluo.shamrock.remote.entries.IndexData import moe.fuqiuluo.shamrock.remote.entries.IndexData
import moe.fuqiuluo.shamrock.remote.entries.Status import moe.fuqiuluo.shamrock.remote.entries.Status
import moe.fuqiuluo.shamrock.tools.EmptyJsonObject
import moe.fuqiuluo.shamrock.tools.fetchOrNull import moe.fuqiuluo.shamrock.tools.fetchOrNull
import moe.fuqiuluo.shamrock.tools.fetchOrThrow import moe.fuqiuluo.shamrock.tools.fetchOrThrow
import moe.fuqiuluo.shamrock.tools.fetchPostJsonElement import moe.fuqiuluo.shamrock.tools.fetchPostJsonElement
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObject import moe.fuqiuluo.shamrock.tools.fetchPostJsonObject
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObjectOrNull
import moe.fuqiuluo.shamrock.tools.isJsonArray import moe.fuqiuluo.shamrock.tools.isJsonArray
import moe.fuqiuluo.shamrock.tools.isJsonObject import moe.fuqiuluo.shamrock.tools.isJsonObject
import moe.fuqiuluo.shamrock.tools.isJsonString import moe.fuqiuluo.shamrock.tools.isJsonString
@ -55,7 +57,7 @@ fun Routing.echoVersion() {
} }
call.attributes.put(ECHO_KEY, echo) call.attributes.put(ECHO_KEY, echo)
val params = fetchPostJsonObject("params") val params = fetchPostJsonObjectOrNull("params") ?: EmptyJsonObject
val handler = ActionManager[action] val handler = ActionManager[action]
if (handler == null) { if (handler == null) {

View File

@ -97,7 +97,7 @@ internal abstract class WebSocketTransmitServlet(
} }
val action = actionObject["action"].asString val action = actionObject["action"].asString
val echo = actionObject["echo"] ?: EmptyJsonString val echo = actionObject["echo"] ?: EmptyJsonString
val params = actionObject["params"].asJsonObject val params = actionObject["params"].asJsonObjectOrNull ?: EmptyJsonObject
val handler = ActionManager[action] val handler = ActionManager[action]
handler?.handle(ActionSession(params, echo)) handler?.handle(ActionSession(params, echo))

View File

@ -20,13 +20,10 @@ import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import moe.fuqiuluo.shamrock.helper.ParamsException import moe.fuqiuluo.shamrock.helper.ParamsException
import io.ktor.http.HttpMethod import io.ktor.http.HttpMethod
import io.ktor.http.decodeURLPart
import io.ktor.http.parseUrlEncodedParameters import io.ktor.http.parseUrlEncodedParameters
import io.ktor.server.request.httpMethod import io.ktor.server.request.httpMethod
import io.ktor.server.routing.route import io.ktor.server.routing.route
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.remote.entries.CommonResult import moe.fuqiuluo.shamrock.remote.entries.CommonResult
import moe.fuqiuluo.shamrock.remote.entries.EmptyObject import moe.fuqiuluo.shamrock.remote.entries.EmptyObject
import moe.fuqiuluo.shamrock.remote.entries.Status import moe.fuqiuluo.shamrock.remote.entries.Status
@ -38,9 +35,9 @@ import moe.fuqiuluo.shamrock.remote.entries.Status
annotation class ShamrockDsl annotation class ShamrockDsl
private val isJsonKey = AttributeKey<Boolean>("isJson") private val keyIsJson = AttributeKey<Boolean>("isJson")
private val jsonKey = AttributeKey<JsonObject>("paramsJson") private val keyJsonObject = AttributeKey<JsonObject>("paramsJson")
private val partsKey = AttributeKey<Parameters>("paramsParts") private val keyParts = AttributeKey<Parameters>("paramsParts")
suspend fun ApplicationCall.fetch(key: String): String { suspend fun ApplicationCall.fetch(key: String): String {
val isPost = request.httpMethod == HttpMethod.Post val isPost = request.httpMethod == HttpMethod.Post
@ -94,23 +91,23 @@ fun ApplicationCall.isJsonData(): Boolean {
} }
suspend fun ApplicationCall.fetchPostOrNull(key: String): String? { suspend fun ApplicationCall.fetchPostOrNull(key: String): String? {
if (attributes.contains(jsonKey)) { if (attributes.contains(keyJsonObject)) {
return attributes[jsonKey][key].asStringOrNull return attributes[keyJsonObject][key].asStringOrNull
} }
if (attributes.contains(partsKey)) { if (attributes.contains(keyParts)) {
return attributes[partsKey][key] return attributes[keyParts][key]
} }
return kotlin.runCatching { return kotlin.runCatching {
if (isJsonData()) { if (isJsonData()) {
Json.parseToJsonElement(receiveText()).jsonObject.also { Json.parseToJsonElement(receiveText()).jsonObject.also {
attributes.put(jsonKey, it) attributes.put(keyJsonObject, it)
attributes.put(isJsonKey, true) attributes.put(keyIsJson, true)
}[key].asStringOrNull }[key].asStringOrNull
} else if ( } else if (
ContentType.Application.FormUrlEncoded == request.contentType() ContentType.Application.FormUrlEncoded == request.contentType()
) { ) {
receiveParameters().also { receiveParameters().also {
attributes.put(partsKey, it) attributes.put(keyParts, it)
}[key] }[key]
} else { } else {
receiveTextAsUnknown(key) receiveTextAsUnknown(key)
@ -124,13 +121,13 @@ private suspend fun ApplicationCall.receiveTextAsUnknown(key: String): String? {
return receiveText().let { text -> return receiveText().let { text ->
if (text.startsWith("{") && text.endsWith("}")) { if (text.startsWith("{") && text.endsWith("}")) {
Json.parseToJsonElement(text).jsonObject.also { Json.parseToJsonElement(text).jsonObject.also {
attributes.put(jsonKey, it) attributes.put(keyJsonObject, it)
attributes.put(isJsonKey, true) attributes.put(keyIsJson, true)
}[key].asStringOrNull }[key].asStringOrNull
} else { } else {
text.parseUrlEncodedParameters().also { text.parseUrlEncodedParameters().also {
attributes.put(partsKey, it) attributes.put(keyParts, it)
attributes.put(isJsonKey, false) attributes.put(keyIsJson, false)
}[key] }[key]
} }
} // receiveText } // receiveText
@ -170,17 +167,17 @@ suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostOrThrow(key: String)
} }
fun PipelineContext<Unit, ApplicationCall>.isJsonData(): Boolean { fun PipelineContext<Unit, ApplicationCall>.isJsonData(): Boolean {
return ContentType.Application.Json == call.request.contentType() || (isJsonKey in call.attributes && call.attributes[isJsonKey]) return ContentType.Application.Json == call.request.contentType() || (keyIsJson in call.attributes && call.attributes[keyIsJson])
} }
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonString(key: String): Boolean { suspend fun PipelineContext<Unit, ApplicationCall>.isJsonString(key: String): Boolean {
if (!isJsonData()) return true if (!isJsonData()) return true
val data = if (jsonKey in call.attributes) { val data = if (keyJsonObject in call.attributes) {
call.attributes[jsonKey] call.attributes[keyJsonObject]
} else { } else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also { Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(jsonKey, it) call.attributes.put(keyJsonObject, it)
call.attributes.put(isJsonKey, true) call.attributes.put(keyIsJson, true)
} }
} }
return data[key] is JsonPrimitive return data[key] is JsonPrimitive
@ -188,11 +185,11 @@ suspend fun PipelineContext<Unit, ApplicationCall>.isJsonString(key: String): Bo
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonObject(key: String): Boolean { suspend fun PipelineContext<Unit, ApplicationCall>.isJsonObject(key: String): Boolean {
if (!isJsonData()) return false if (!isJsonData()) return false
val data = if (call.attributes.contains(jsonKey)) { val data = if (call.attributes.contains(keyJsonObject)) {
call.attributes[jsonKey] call.attributes[keyJsonObject]
} else { } else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also { Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(jsonKey, it) call.attributes.put(keyJsonObject, it)
} }
} }
return data[key] is JsonObject return data[key] is JsonObject
@ -200,56 +197,68 @@ suspend fun PipelineContext<Unit, ApplicationCall>.isJsonObject(key: String): Bo
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonArray(key: String): Boolean { suspend fun PipelineContext<Unit, ApplicationCall>.isJsonArray(key: String): Boolean {
if (!isJsonData()) return false if (!isJsonData()) return false
val data = if (call.attributes.contains(jsonKey)) { val data = if (call.attributes.contains(keyJsonObject)) {
call.attributes[jsonKey] call.attributes[keyJsonObject]
} else { } else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also { Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(jsonKey, it) call.attributes.put(keyJsonObject, it)
} }
} }
return data[key] is JsonArray return data[key] is JsonArray
} }
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonString(key: String): String { suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonString(key: String): String {
val data = if (call.attributes.contains(jsonKey)) { val data = if (call.attributes.contains(keyJsonObject)) {
call.attributes[jsonKey] call.attributes[keyJsonObject]
} else { } else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also { Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(jsonKey, it) call.attributes.put(keyJsonObject, it)
} }
} }
return data[key].asString return data[key].asString
} }
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonElement(key: String): JsonElement { suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonElement(key: String): JsonElement {
val data = if (call.attributes.contains(jsonKey)) { val data = if (call.attributes.contains(keyJsonObject)) {
call.attributes[jsonKey] call.attributes[keyJsonObject]
} else { } else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also { Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(jsonKey, it) call.attributes.put(keyJsonObject, it)
} }
} }
return data[key]!! return data[key]!!
} }
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObject(key: String): JsonObject { suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObject(key: String): JsonObject {
val data = if (call.attributes.contains(jsonKey)) { val data = if (call.attributes.contains(keyJsonObject)) {
call.attributes[jsonKey] call.attributes[keyJsonObject]
} else { } else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also { Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(jsonKey, it) call.attributes.put(keyJsonObject, it)
} }
} }
return data[key].asJsonObject return data[key].asJsonObject
} }
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonArray(key: String): JsonArray { suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObjectOrNull(key: String): JsonObject? {
val data = if (call.attributes.contains(jsonKey)) { val data = if (call.attributes.contains(keyJsonObject)) {
call.attributes[jsonKey] call.attributes[keyJsonObject]
} else { } else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also { Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(jsonKey, it) call.attributes.put(keyJsonObject, it)
call.attributes.put(isJsonKey, true) }
}
return data[key].asJsonObjectOrNull
}
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonArray(key: String): JsonArray {
val data = if (call.attributes.contains(keyJsonObject)) {
call.attributes[keyJsonObject]
} else {
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
call.attributes.put(keyJsonObject, it)
call.attributes.put(keyIsJson, true)
} }
} }
return data[key].asJsonArray return data[key].asJsonArray