All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.javalin.websocket.WsContext.kt Maven / Gradle / Ivy

/*
 * Javalin - https://javalin.io
 * Copyright 2017 David Åse
 * Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
 */

package io.javalin.websocket

import io.javalin.http.Context
import io.javalin.jetty.upgradeContextKey
import io.javalin.jetty.upgradeSessionAttrsKey
import io.javalin.plugin.json.jsonMapper
import org.eclipse.jetty.websocket.api.CloseStatus
import org.eclipse.jetty.websocket.api.RemoteEndpoint
import org.eclipse.jetty.websocket.api.Session
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest
import java.nio.ByteBuffer

/**
 * The [WsContext] class holds Jetty's [Session] and provides (convenient) delegate methods.
 * It adds functionality similar to the API found in [io.javalin.http.Context].
 * It also adds a [send] method, which calls [RemoteEndpoint.sendString] on [Session.getRemote]
 */
abstract class WsContext(val sessionId: String, @JvmField val session: Session) {

    internal val upgradeReq by lazy { session.upgradeRequest as ServletUpgradeRequest }
    internal val upgradeCtx by lazy { upgradeReq.httpServletRequest.getAttribute(upgradeContextKey) as Context }
    internal val sessionAttributes by lazy { upgradeReq.httpServletRequest.getAttribute(upgradeSessionAttrsKey) as Map? }

    fun matchedPath() = upgradeCtx.matchedPath

    fun send(message: Any) = send(upgradeCtx.jsonMapper().toJsonString(message))
    fun send(message: String) = session.remote.sendStringByFuture(message)
    fun send(message: ByteBuffer) = session.remote.sendBytesByFuture(message)

    @JvmOverloads fun sendPing(message: ByteBuffer? = null) = session.remote.sendPing(message ?: ByteBuffer.allocate(0))

    fun queryString(): String? = upgradeCtx.queryString()
    fun queryParamMap(): Map> = upgradeCtx.queryParamMap()
    fun queryParams(key: String): List = upgradeCtx.queryParams(key)
    fun queryParam(key: String): String? = upgradeCtx.queryParam(key)
    fun  queryParamAsClass(key: String, clazz: Class) = upgradeCtx.queryParamAsClass(key, clazz)
    inline fun  queryParamAsClass(key: String) = queryParamAsClass(key, T::class.java)

    fun pathParamMap(): Map = upgradeCtx.pathParamMap()
    fun pathParam(key: String): String = upgradeCtx.pathParam(key)
    fun  pathParamAsClass(key: String, clazz: Class) = upgradeCtx.pathParamAsClass(key, clazz)
    inline fun  pathParamAsClass(key: String) = pathParamAsClass(key, T::class.java)

    fun host() = upgradeReq.host // why can't we get this from upgradeCtx?

    fun header(header: String): String? = upgradeCtx.header(header)
    fun headerMap(): Map = upgradeCtx.headerMap()

    fun cookie(name: String) = upgradeCtx.cookie(name)
    fun cookieMap(): Map = upgradeCtx.cookieMap()

    fun attribute(key: String, value: Any?) = upgradeCtx.attribute(key, value)
    fun  attribute(key: String): T? = upgradeCtx.attribute(key)
    fun attributeMap(): Map = upgradeCtx.attributeMap()

    fun  sessionAttribute(key: String): T? = sessionAttributeMap()[key] as T
    fun sessionAttributeMap(): Map = sessionAttributes ?: mapOf()

    fun closeSession() = session.close()
    fun closeSession(closeStatus: CloseStatus) = session.close(closeStatus)
    fun closeSession(code: Int, reason: String?) = session.close(code, reason)

    override fun equals(other: Any?) = session == (other as WsContext).session
    override fun hashCode() = session.hashCode()
}

class WsConnectContext(sessionId: String, session: Session) : WsContext(sessionId, session)

class WsErrorContext(sessionId: String, session: Session, private val error: Throwable?) : WsContext(sessionId, session) {
    fun error() = error
}

class WsCloseContext(sessionId: String, session: Session, private val statusCode: Int, private val reason: String?) : WsContext(sessionId, session) {
    fun status() = statusCode
    fun reason() = reason
}

class WsBinaryMessageContext(sessionId: String, session: Session, private val data: ByteArray, private val offset: Int, private val length: Int) : WsContext(sessionId, session) {
    fun data() = data
    fun offset() = offset
    fun length() = length
}

class WsMessageContext(sessionId: String, session: Session, private val message: String) : WsContext(sessionId, session) {
    fun message(): String = message
    fun  messageAsClass(clazz: Class): T = upgradeCtx.jsonMapper().fromJsonString(message, clazz)
    inline fun  messageAsClass(): T = messageAsClass(T::class.java)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy