librecaptcha/src/main/scala/lc/server/Server.scala

89 lines
2.6 KiB
Scala

package lc.server
import org.json4s.jackson.JsonMethods.parse
import org.json4s.jvalue2extractable
import lc.core.CaptchaManager
import lc.core.ErrorMessageEnum
import lc.core.{Answer, ByteConvert, Error, Id, Parameters}
import lc.core.Config.formats
import org.limium.picoserve
import org.limium.picoserve.Server.{ByteResponse, ServerBuilder, StringResponse}
import scala.io.Source
import java.net.InetSocketAddress
import java.util
import scala.jdk.CollectionConverters._
class Server(address: String, port: Int, captchaManager: CaptchaManager, playgroundEnabled: Boolean, corsHeader: String) {
var headerMap: util.Map[String, util.List[String]] = _
if (corsHeader.nonEmpty) {
headerMap = Map("Access-Control-Allow-Origin" -> List(corsHeader).asJava).asJava
}
val serverBuilder: ServerBuilder = picoserve.Server
.builder()
.address(new InetSocketAddress(address, port))
.backlog(32)
.POST(
"/v1/captcha",
(request) => {
val json = parse(request.getBodyString())
val param = json.extract[Parameters]
val id = captchaManager.getChallenge(param)
getResponse(id, headerMap)
}
)
.GET(
"/v1/media",
(request) => {
val params = request.getQueryParams()
val result = if (params.containsKey("id")) {
val paramId = params.get("id").get(0)
val id = Id(paramId)
captchaManager.getCaptcha(id)
} else {
Left(Error(ErrorMessageEnum.INVALID_PARAM.toString + "=> id"))
}
getResponse(result, headerMap)
}
)
.POST(
"/v1/answer",
(request) => {
val json = parse(request.getBodyString())
val answer = json.extract[Answer]
val result = captchaManager.checkAnswer(answer)
getResponse(result, headerMap)
}
)
if (playgroundEnabled) {
serverBuilder.GET(
"/demo/index.html",
(_) => {
val resStream = getClass().getResourceAsStream("/index.html")
val str = Source.fromInputStream(resStream).mkString
new StringResponse(200, str)
}
)
}
val server: picoserve.Server = serverBuilder.build()
private def getResponse(
response: Either[Error, ByteConvert],
responseHeaders: util.Map[String, util.List[String]]
): ByteResponse = {
response match {
case Right(value) => {
new ByteResponse(200, value.toBytes(), responseHeaders)
}
case Left(value) => {
new ByteResponse(500, value.toBytes(), responseHeaders)
}
}
}
def start(): Unit = {
println("Starting server on " + address + ":" + port)
server.start()
}
}