|
@@ -8,8 +8,10 @@ import org.springframework.context.annotation.Configuration
|
|
import org.springframework.core.Ordered
|
|
import org.springframework.core.Ordered
|
|
import org.springframework.core.annotation.Order
|
|
import org.springframework.core.annotation.Order
|
|
import org.springframework.core.io.ResourceLoader
|
|
import org.springframework.core.io.ResourceLoader
|
|
|
|
+import org.springframework.http.HttpHeaders
|
|
import org.springframework.http.HttpMethod
|
|
import org.springframework.http.HttpMethod
|
|
import org.springframework.http.HttpStatus
|
|
import org.springframework.http.HttpStatus
|
|
|
|
+import org.springframework.messaging.handler.annotation.DestinationVariable
|
|
import org.springframework.messaging.handler.annotation.MessageMapping
|
|
import org.springframework.messaging.handler.annotation.MessageMapping
|
|
import org.springframework.messaging.handler.annotation.SendTo
|
|
import org.springframework.messaging.handler.annotation.SendTo
|
|
import org.springframework.messaging.simp.SimpMessagingTemplate
|
|
import org.springframework.messaging.simp.SimpMessagingTemplate
|
|
@@ -27,13 +29,14 @@ import java.io.File
|
|
import java.io.IOException
|
|
import java.io.IOException
|
|
import java.io.Serializable
|
|
import java.io.Serializable
|
|
import java.net.InetAddress
|
|
import java.net.InetAddress
|
|
|
|
+import java.time.Duration
|
|
import java.time.LocalDateTime
|
|
import java.time.LocalDateTime
|
|
-import java.time.format.DateTimeFormatter
|
|
|
|
import java.util.*
|
|
import java.util.*
|
|
import java.util.concurrent.TimeUnit
|
|
import java.util.concurrent.TimeUnit
|
|
import javax.servlet.*
|
|
import javax.servlet.*
|
|
import javax.servlet.http.HttpServletRequest
|
|
import javax.servlet.http.HttpServletRequest
|
|
import javax.servlet.http.HttpServletResponse
|
|
import javax.servlet.http.HttpServletResponse
|
|
|
|
+import kotlin.concurrent.fixedRateTimer
|
|
import kotlin.streams.toList
|
|
import kotlin.streams.toList
|
|
|
|
|
|
|
|
|
|
@@ -96,7 +99,7 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
|
|
rb.queryString = req.parameterMap
|
|
rb.queryString = req.parameterMap
|
|
Singletons.requestInstance[reqId] = RequestQue(reqId, rb, null)
|
|
Singletons.requestInstance[reqId] = RequestQue(reqId, rb, null)
|
|
template.convertAndSend("/topic/$client", RequestTrigger(reqId))
|
|
template.convertAndSend("/topic/$client", RequestTrigger(reqId))
|
|
-// template.convertAndSend("/topic/str/$client", rb)
|
|
|
|
|
|
+ template.convertAndSend("/topic/str/$client", rb)
|
|
var i = 0
|
|
var i = 0
|
|
while (Singletons.responseQue[reqId] == null) {
|
|
while (Singletons.responseQue[reqId] == null) {
|
|
TimeUnit.MILLISECONDS.sleep(100)
|
|
TimeUnit.MILLISECONDS.sleep(100)
|
|
@@ -138,12 +141,13 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
|
|
val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
|
|
val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
|
|
LogManager.getLogger("client.$client").info("Request Success. Time: $duration UA: " + req.getHeader("User-Agent") + " From: " + req.remoteAddr + " To: " + req.requestURL.toString() + "?" + req.queryString)
|
|
LogManager.getLogger("client.$client").info("Request Success. Time: $duration UA: " + req.getHeader("User-Agent") + " From: " + req.remoteAddr + " To: " + req.requestURL.toString() + "?" + req.queryString)
|
|
|
|
|
|
- ClientHolder.addSuccessRequest(client,duration)
|
|
|
|
|
|
+ ClientHolder.addSuccessRequest(client, duration)
|
|
return
|
|
return
|
|
|
|
|
|
} catch (e: Exception) {
|
|
} catch (e: Exception) {
|
|
|
|
+ e.printStackTrace()
|
|
res.status = HttpStatus.REQUEST_TIMEOUT.value()
|
|
res.status = HttpStatus.REQUEST_TIMEOUT.value()
|
|
- res.writer.write("{\"message\":\"Request timeout. Client not responding\"}")
|
|
|
|
|
|
+ res.writer.write("{\"message\":\"Request timeout. Unknown error\"}")
|
|
res.flushBuffer()
|
|
res.flushBuffer()
|
|
Singletons.requestInstance.remove(reqId)
|
|
Singletons.requestInstance.remove(reqId)
|
|
val endTime = System.nanoTime()
|
|
val endTime = System.nanoTime()
|
|
@@ -190,8 +194,40 @@ class Resp(val body: ByteArray?, val statusCode: Int, val headers: Map<String, A
|
|
object Singletons {
|
|
object Singletons {
|
|
val responseQue: MutableMap<String, Resp> by lazy { mutableMapOf<String, Resp>() }
|
|
val responseQue: MutableMap<String, Resp> by lazy { mutableMapOf<String, Resp>() }
|
|
val requestInstance: MutableMap<String, RequestQue> by lazy { mutableMapOf<String, RequestQue>() }
|
|
val requestInstance: MutableMap<String, RequestQue> by lazy { mutableMapOf<String, RequestQue>() }
|
|
|
|
+ val buildSocketChunkData: MutableMap<String, ChunkCollector> by lazy { mutableMapOf<String, ChunkCollector>() }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+class SocketChunkData(val body: ByteArray?, val header: HttpHeaders?, val status: Int, val part: Int, val totalPart: Int)
|
|
|
|
+
|
|
|
|
+class ChunkCollector(private val id: String) {
|
|
|
|
+ private val listSocketChunk = mutableListOf<SocketChunkData>()
|
|
|
|
+ fun add(dt: SocketChunkData) {
|
|
|
|
+ if (!listSocketChunk.any { it.part == dt.part }) {
|
|
|
|
+ listSocketChunk.add(dt)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dt.part == dt.totalPart - 1) {
|
|
|
|
+ val tStart = LocalDateTime.now()
|
|
|
|
+ fixedRateTimer("timer-$id", false, 0L, 100) {
|
|
|
|
+ if (listSocketChunk.size == dt.totalPart) {
|
|
|
|
+ val bodyList = listSocketChunk.sortedBy { it.part }.mapNotNull { it.body }
|
|
|
|
+ var bd = ByteArray(0)
|
|
|
|
+ bodyList.forEach { bd += it }
|
|
|
|
+ Singletons.responseQue[id] = Resp(
|
|
|
|
+ bd,
|
|
|
|
+ dt.status,
|
|
|
|
+ dt.header?.entries?.map { Pair(it.key, it.value.toTypedArray()) }?.toMap()
|
|
|
|
+ )
|
|
|
|
+ this.cancel()
|
|
|
|
+ }
|
|
|
|
+ if (Duration.between(tStart, LocalDateTime.now()).toMillis() > 6000) {
|
|
|
|
+ this.cancel()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
@Controller
|
|
@Controller
|
|
class SocketChecker {
|
|
class SocketChecker {
|
|
@@ -201,6 +237,38 @@ class SocketChecker {
|
|
fun greeting(message: MutableMap<*, *>): MutableMap<*, *> {
|
|
fun greeting(message: MutableMap<*, *>): MutableMap<*, *> {
|
|
return mutableMapOf(Pair("Hi", "I'am Ok"))
|
|
return mutableMapOf(Pair("Hi", "I'am Ok"))
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @MessageMapping("/response/{id}")
|
|
|
|
+ @SendTo("/topic/healthCheck")
|
|
|
|
+ @Throws(Exception::class)
|
|
|
|
+ fun responseMsg(message: SocketChunkData, @DestinationVariable("id") id: String): MutableMap<*, *> {
|
|
|
|
+ try {
|
|
|
|
+// println(message.body)
|
|
|
|
+// println(message.header)
|
|
|
|
+// println(message.status)
|
|
|
|
+// println(message.part)
|
|
|
|
+// println(message.totalPart)
|
|
|
|
+ if (message.totalPart == 1) {
|
|
|
|
+ Singletons.responseQue[id] = Resp(
|
|
|
|
+ message.body,
|
|
|
|
+ message.status,
|
|
|
|
+ message.header?.entries?.map { Pair(it.key, it.value.toTypedArray()) }?.toMap()
|
|
|
|
+ )
|
|
|
|
+ } else {
|
|
|
|
+ var sc = Singletons.buildSocketChunkData[id]
|
|
|
|
+
|
|
|
|
+ if (sc == null) {
|
|
|
|
+ Singletons.buildSocketChunkData[id] = ChunkCollector(id)
|
|
|
|
+ sc = Singletons.buildSocketChunkData[id]
|
|
|
|
+ }
|
|
|
|
+ sc?.add(message)
|
|
|
|
+ }
|
|
|
|
+ } catch (e: Exception) {
|
|
|
|
+ e.printStackTrace()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return mutableMapOf(Pair("Hi", "I'am Ok"))
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@RestController
|
|
@RestController
|
|
@@ -235,6 +303,7 @@ class BridgeRestController {
|
|
fun getClientData(): Map<String, Client> {
|
|
fun getClientData(): Map<String, Client> {
|
|
return ClientHolder.get()
|
|
return ClientHolder.get()
|
|
}
|
|
}
|
|
|
|
+
|
|
@GetMapping("/clientStat/{id}")
|
|
@GetMapping("/clientStat/{id}")
|
|
fun getClientDataOne(@PathVariable("id") id: String): Client? {
|
|
fun getClientDataOne(@PathVariable("id") id: String): Client? {
|
|
return ClientHolder.get()[id]
|
|
return ClientHolder.get()[id]
|