Skip to content

Commit

Permalink
Support http forward (temp impl)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryoii committed Oct 9, 2023
1 parent ea1cc79 commit d640266
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,53 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/

package net.mamoe.mirai.api.http.adapter.http.support
package net.mamoe.mirai.api.http.adapter.http.plugin

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.request.*
import io.ktor.util.*
import io.ktor.util.pipeline.*


val HttpForwardAttributeKey = AttributeKey<HttpForwardContext>("HttpForward")
val HttpForwardPhase = PipelinePhase("Forward")
val HttpForward = createApplicationPlugin("HttpForward", ::HttpForwardConfig) {
application.insertPhaseAfter(ApplicationCallPipeline.Call, HttpForwardPhase)

application.interceptorsForPhase(ApplicationCallPipeline.Call).forEach { interceptor ->
application.intercept(HttpForwardPhase, interceptor)

application.intercept(HttpForwardPhase) {
val forwardContext = call.attributes.getOrNull(HttpForwardAttributeKey) ?: return@intercept
val forwardCall = ApplicationForwardCall(call, forwardContext.router, forwardContext.body)
val callInterceptors = application.interceptorsForPhase(ApplicationCallPipeline.Call)


}
}

class HttpForwardConfig {
var forward: String = ""
}

data class HttpForwardContext(val router: String, val body: Any?)

suspend fun ApplicationCall.forward(forward: String) {
application.execute(ApplicationForwardCall(this, forward))
// application.execute(ApplicationForwardCall(this, forward))
attributes.put(HttpForwardAttributeKey, HttpForwardContext(forward, null))
}

suspend fun ApplicationCall.forward(forward: String, body: Any) {
application.execute(ApplicationForwardCall(this, forward, body))
// application.execute(ApplicationForwardCall(this, forward, body))
attributes.put(HttpForwardAttributeKey, HttpForwardContext(forward, body))
}

internal fun forwardReceivePipeline(body: Any): ApplicationReceivePipeline = ApplicationReceivePipeline().apply {
intercept(ApplicationReceivePipeline.Transform) { proceedWith(body) }
intercept(ApplicationReceivePipeline.Transform) {
proceedWith(body)
}
}

internal class ApplicationForwardCall(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ internal object Monitor : Hook<suspend (ApplicationCall) -> Unit> {
}
}

internal object ReceiveBodyTransforming : Hook<suspend (ApplicationCall, Any) -> Any> {
override fun install(
pipeline: ApplicationCallPipeline,
handler: suspend (call: ApplicationCall, state: Any) -> Any
) {
pipeline.receivePipeline.intercept(ApplicationReceivePipeline.Before) {
val body = handler(call, it)
proceedWith(body)
}
}
}

internal object ReceiveBodyTransformed : Hook<suspend (ApplicationCall, Any) -> Any> {
override fun install(
pipeline: ApplicationCallPipeline,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package net.mamoe.mirai.api.http.adapter.http.plugin
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
Expand All @@ -19,7 +20,11 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.testing.*
import net.mamoe.mirai.api.http.adapter.http.support.forward
import io.ktor.util.reflect.*
import io.ktor.utils.io.*
import io.ktor.utils.io.charsets.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import net.mamoe.mirai.api.http.adapter.internal.dto.parameter.LongTargetDTO
import net.mamoe.mirai.api.http.adapter.internal.dto.parameter.NudgeDTO
import net.mamoe.mirai.api.http.adapter.internal.serializer.BuiltinJsonSerializer
Expand Down Expand Up @@ -127,4 +132,48 @@ class HttpForwardTest {
assertEquals("321", it.bodyAsText())
}
}


@Serializable
private data class NeatedDto(
val router: String,
val body: JsonElement,
)

@Test
fun testPostRequestForwardNestedBody() = testApplication {
// No need for DoubleReceive
install(GlobalExceptionHandler) { printTrace = true }
install(DoubleReceive)
install(HttpRouterMonitor)
install(ContentNegotiation) {
json(json=BuiltinJsonSerializer.buildJson())
register(ContentType.Application.Json, object : ContentConverter {
override suspend fun deserialize(charset: Charset, typeInfo: TypeInfo, content: ByteReadChannel): Any? {
TODO("Not yet implemented")
}
})
}

routing {
post("/test") {
val receive = call.receive<NeatedDto>()
assertEquals("/forward", receive.router)
call.forward("/forward", receive.body)
}

post("/forward") {
val receive = call.receive<LongTargetDTO>()
call.respondText(receive.target.toString())
}
}

client.post("/test") {
contentType(ContentType.Application.Json)
setBody("""{"router":"/forward","body":{"target":321}}""")
}.also {
assertEquals(HttpStatusCode.OK, it.status)
assertEquals("321", it.bodyAsText())
}
}
}

0 comments on commit d640266

Please sign in to comment.