提交 8b622426 编写于 作者: 梦境迷离's avatar 梦境迷离

搬运undertow 等工具类

上级 89412f72
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* [1.1.5 八大排序算法](src/main/java/cn/edu/jxnu/questions/Sort.md) * [1.1.5 八大排序算法](src/main/java/cn/edu/jxnu/questions/Sort.md)
* 1.2 Scala * 1.2 Scala
* [1.2.1 Scala语法基础](src/main/java/cn/edu/jxnu/scala/ScalaBasic.md) * [1.2.1 Scala语法基础](src/main/java/cn/edu/jxnu/scala/ScalaBasic.md)
* [1.2.2 Scala常用工具类](src/main/java/cn/edu/jxnu/scala/utils/README.md) * [1.2.2 Scala常用工具类](src/main/java/cn/edu/jxnu/utils/README.md)
* [1.2.3 Scala Akka基本使用](src/main/java/cn/edu/jxnu/scala/ScalaAkkaBasic.md) * [1.2.3 Scala Akka基本使用](src/main/java/cn/edu/jxnu/scala/ScalaAkkaBasic.md)
* [1.2.4 Scala Future解读](src/main/java/cn/edu/jxnu/scala/Future.md) * [1.2.4 Scala Future解读](src/main/java/cn/edu/jxnu/scala/Future.md)
......
...@@ -43,6 +43,10 @@ dependencies { ...@@ -43,6 +43,10 @@ dependencies {
compile group: 'com.typesafe.play', name: 'play-ws_2.12', version: '2.7.0' compile group: 'com.typesafe.play', name: 'play-ws_2.12', version: '2.7.0'
compile group: 'com.typesafe.play', name: 'play-akka-http-server_2.12', version: '2.7.0' compile group: 'com.typesafe.play', name: 'play-akka-http-server_2.12', version: '2.7.0'
compile group: 'com.typesafe.play', name: 'play-ahc-ws_2.12', version: '2.7.0' compile group: 'com.typesafe.play', name: 'play-ahc-ws_2.12', version: '2.7.0'
compile group: 'com.google.inject', name: 'guice', version: '3.0'
compile group: 'io.undertow', name: 'undertow-core', version: '2.0.24.Final'
compile group: 'org.scalikejdbc', name: 'scalikejdbc_2.12', version: '3.3.4'
compile group: 'com.zaxxer', name: 'HikariCP', version: '3.1.0'
testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3' testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3'
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
| Java | Scala | Java | Scala
| :--- | :--- | | :--- | :--- |
| [计算机网络](../questions/Network.md) | [Scala语法基础](../scala/ScalaBasic.md) | | [计算机网络](../questions/Network.md) | [Scala语法基础](../scala/ScalaBasic.md) |
| [SQL、MySQL](../questions/MySQL.md) | [Scala常用工具类](../scala/utils) | | [SQL、MySQL](../questions/MySQL.md) | [Scala常用工具类](../utils) |
| [操作系统](../questions/OS.md) | [Scala Akka基本使用](../scala/ScalaAkkaBasic.md) | | [操作系统](../questions/OS.md) | [Scala Akka基本使用](../scala/ScalaAkkaBasic.md) |
| [Java线程基础](../questions/Threads.md) | [Scala Play例子](https://github.com/jxnu-liguobin/scala_micro_service) | | [Java线程基础](../questions/Threads.md) | [Scala Play例子](https://github.com/jxnu-liguobin/scala_micro_service) |
| [八大排序算法](../questions/Sort.md) | [Scala布隆过滤器](https://github.com/jxnu-liguobin/Scala-BloomFilter) | | [八大排序算法](../questions/Sort.md) | [Scala布隆过滤器](https://github.com/jxnu-liguobin/Scala-BloomFilter) |
......
Scala 开发过程中收集的工具类 Scala 开发过程中收集的工具类
--- ---
[Scala Spring开发工具类 @deprecated](./ScalaUtil.md) [Scala Spring开发工具类 已废弃](../scala/utils/ScalaUtil.md)
Scala服务端开发,但包含并不限于 Scala服务端开发,但包含并不限于
...@@ -12,7 +12,8 @@ Scala服务端开发,但包含并不限于 ...@@ -12,7 +12,8 @@ Scala服务端开发,但包含并不限于
* Json操作 * Json操作
* HTTP处理 * HTTP处理
* 字符串处理 * 字符串处理
* 对象处理
* Java工具类 * Java工具类
* 其他 * 其他
不支持在Gitbook中查看,请移步[GitHub](https://github.com/jxnu-liguobin/cs-summary-reflection/tree/master/src/main/java/cn/edu/jxnu/scala/utils) 不支持在Gitbook中查看,请移步[GitHub](https://github.com/jxnu-liguobin/cs-summary-reflection/tree/master/src/main/java/cn/edu/jxnu/utils)
package cn.edu.jxnu.utils.concurrent
import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NonFatal
/**
* 线程执行器
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
trait Executable {
def executeSafely[T](block: => Future[T], exceptionCaught: Throwable => Unit)(implicit ec: ExecutionContext): Unit = {
try {
block.recover {
case NonFatal(t) => exceptionCaught(t)
}
} catch {
case NonFatal(t) => exceptionCaught(t)
}
}
}
package cn.edu.jxnu.utils.config
import com.typesafe.config.Config
import scala.collection.JavaConverters._
import scala.concurrent.duration.{Duration, _}
import scala.language.implicitConversions
import scala.util.{Failure, Success, Try}
/**
* typesafe config 转化
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
object ConfigConversions {
implicit class ConfigWrapper(config: Config) {
implicit def getIntOpt(path: String): Option[Int] = getOpt(config.getInt(path))
implicit def getLongOpt(path: String): Option[Long] = getOpt(config.getLong(path))
implicit def getDoubleOpt(path: String): Option[Double] = getOpt(config.getDouble(path))
implicit def getStringOpt(path: String): Option[String] = getOpt(config.getString(path))
implicit def getConfigOpt(path: String): Option[Config] = getOpt(config.getConfig(path))
implicit def getBooleanOpt(path: String): Option[Boolean] = getOpt(config.getBoolean(path))
implicit def getStringSeqOpt(path: String): Option[Seq[String]] = getOpt(config.getStringList(path).asScala)
implicit def getIntSeqOpt(path: String): Option[Seq[Int]] = getOpt(config.getIntList(path).asScala.map(_.intValue()))
implicit def getDurationOpt(path: String): Option[Duration] = getOpt(config.getDuration(path)).map(d d.toNanos.nanos)
implicit def getLongSeqOpt(path: String): Option[Seq[Long]] = getOpt(config.getLongList(path).asScala.map(_.longValue()))
implicit def getDoubleSeqOpt(path: String): Option[Seq[Double]] = getOpt(config.getDoubleList(path).asScala.map(_.doubleValue()))
private[this] def getOpt[T](f: T): Option[T] = {
Try(f) match {
case Success(value) Some(value)
case Failure(_) None
}
}
}
}
package cn.edu.jxnu.utils.guice
import java.util.Objects
import com.google.common.reflect.ClassPath
import com.google.inject.AbstractModule
import scala.collection.JavaConverters._
/**
* guice将包下所有类实例化并绑定到对应的接口
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
abstract class AbstractModuleSupport extends AbstractModule {
private[this] final val CLASS_PATH = ClassPath.from(this.getClass.getClassLoader)
def bindComponents(packageName: String): Unit = {
CLASS_PATH.getTopLevelClasses(packageName).asScala.foreach { classInfo
val clazz = classInfo.load()
val interfaces = clazz.getInterfaces
val interfaceOpt = interfaces.find { irfe
clazz.getSimpleName.contains(irfe.getSimpleName) && clazz.getPackage.getName.contains(irfe.getPackage.getName)
}
if (Objects.nonNull(interfaces) && interfaces.nonEmpty && interfaceOpt.isDefined) {
bind(interfaceOpt.get.asInstanceOf[Class[Any]]).to(clazz.asInstanceOf[Class[Any]])
}
}
}
def loadClasses(packageName: String): Set[Class[_]] = {
CLASS_PATH.getTopLevelClasses(packageName).asScala.map(_.load()).toSet
}
}
\ No newline at end of file
package cn.edu.jxnu.utils.http
import java.nio.file.Paths
import com.google.common.reflect.{ClassPath, TypeToken}
import com.google.inject.Injector
import scala.collection.JavaConverters._
/**
* undertow 获取待注册的请求路由
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
object Routes {
def getRoutingHandlers(injector: Injector, packageName: String): Set[RoutingHandler] = {
val classPath = ClassPath.from(this.getClass.getClassLoader)
val routingHandlerClazz: Class[RoutingHandler] = classOf[RoutingHandler]
val classes = classPath.getTopLevelClassesRecursive(packageName).asScala
classes.map(_.load()).filter { clazz =>
val types = TypeToken.of(clazz).getTypes.asScala
types.exists(_.getRawType == routingHandlerClazz)
}.map { clazz =>
val constructor = clazz.getConstructors.head
val parameters = constructor.getParameterTypes.map {
case c if c == classOf[Injector] => injector
case c => injector.getInstance(c).asInstanceOf[Object]
}
constructor.newInstance(parameters: _*).asInstanceOf[RoutingHandler]
}.toSet
}
def getRegexRoutes(handlers: Set[RoutingHandler], versioning: Option[String] = None): Set[String] = {
handlers.map { routing =>
val pattern = routing.pattern.getOrElse(routing.route)
val router = versioning.fold(pattern)(version Paths.get("/", version, pattern).toString)
router.replaceAll("\\{\\w+\\}", """([\\\\w|-]+)""")
}
}
}
package cn.edu.jxnu.utils.http
/**
* undertow 处理器接口
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
trait RoutingHandler {
def route: String
def methods: Set[String]
def pattern: Option[String] = None
def single(method: String): Set[String] = Set(method)
def multi(methods: String*): Set[String] = methods.toSet
}
package cn.edu.jxnu.scala.utils; package cn.edu.jxnu.utils.other;
/** /**
* 字节 2进制 16进制 * 字节 2进制 16进制
......
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import scala.concurrent.Future import scala.concurrent.Future
......
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
...@@ -304,4 +304,4 @@ object DateUtils { ...@@ -304,4 +304,4 @@ object DateUtils {
implicit def toStr(localDateTime: Option[LocalDateTime]) = localDateTimeToString(localDateTime) implicit def toStr(localDateTime: Option[LocalDateTime]) = localDateTimeToString(localDateTime)
implicit def toStrNoMS(localDateTime: Option[LocalDateTime]) = localDateTimeToStringNoMS(localDateTime) implicit def toStrNoMS(localDateTime: Option[LocalDateTime]) = localDateTimeToStringNoMS(localDateTime)
} }
\ No newline at end of file
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import java.security.MessageDigest import java.security.MessageDigest
......
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import java.io._ import java.io._
import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.{ExecutionContext, Future}
import scala.io.Source import scala.io.Source
import scala.language.reflectiveCalls import scala.util.control.Exception.ignoring
import scala.util.control.Exception._
/** /**
* 文件处理工具 * 文件处理工具
......
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import play.api.http.{ContentTypeOf, ContentTypes, Writeable} import play.api.http.{ContentTypeOf, ContentTypes, Writeable}
import play.api.libs.json.Writes import play.api.libs.json.Writes
......
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import java.io.FileOutputStream import java.io.FileOutputStream
import java.lang.reflect.{InvocationHandler, Method, Proxy} import java.lang.reflect.{InvocationHandler, Method, Proxy}
import sun.misc.ProxyGenerator import sun.misc.ProxyGenerator
/** /**
* Scala JDK代理 * Scala JDK代理
* *
......
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import play.api.libs.json.Json import play.api.libs.json.Json
......
package cn.edu.jxnu.utils.other
/**
* 对象工具
*
* @author 梦境迷离
* @time 2019-08-18
* @version v2.0
*/
object ObjectUtils {
/**
* 获取对象的所有属性转换为Map
*
* @param obj
* @param excludes
* @return
*/
def properties(obj: Any, excludes: String*): Map[String, Any] = {
val fields = obj.getClass.getDeclaredFields.map { field
field.setAccessible(true)
field.getName field.get(obj)
}.toMap
if (excludes.nonEmpty) {
fields.filterNot(entry excludes.contains(entry._1))
} else {
fields
}
}
}
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import scala.collection.mutable import scala.collection.mutable
import scala.util.Try
/** /**
* @author 梦境迷离 * @author 梦境迷离
...@@ -15,14 +16,19 @@ object StringUtils { ...@@ -15,14 +16,19 @@ object StringUtils {
*/ */
def query(queryParams: String): mutable.HashMap[String, String] = { def query(queryParams: String): mutable.HashMap[String, String] = {
val map = mutable.HashMap[String, String]() //可变 Map val map = mutable.HashMap[String, String]() //可变 Map
if (queryParams.isEmpty || !queryParams.contains("&") && !queryParams.contains("=")) map if (queryParams.isEmpty || !queryParams.contains("=")) map
else { else {
val params = queryParams.split("&") val params = queryParams.split("&")
for (p <- params) { params.foreach {
val kv = p.split("=") p =>
if (kv.length == 2) { if (params.isEmpty) {
map.+=(kv(0) -> kv(1)) Try(map += (queryParams.split("=")(0) -> queryParams.split("=")(1)))
} } else {
val kv = p.split("=")
if (kv.length == 2) {
map.+=(kv(0) -> kv(1))
}
}
} }
map map
} }
...@@ -35,17 +41,19 @@ object StringUtils { ...@@ -35,17 +41,19 @@ object StringUtils {
* @return * @return
*/ */
def query(queryParams: String, key: String): String = { def query(queryParams: String, key: String): String = {
val map = mutable.HashMap[String, String]() //不用Option
if (queryParams.isEmpty || !queryParams.contains("&") && !queryParams.contains("=")) "" query(queryParams).getOrElse(key, null)
else { }
val params = queryParams.split("&")
for (p <- params) { def toOption(str: String): Option[String] = {
val kv = p.split("=") if (java.util.Objects.isNull(str) || str.trim.isEmpty) None else Option(str)
if (kv.length == 2) { }
map.+=(kv(0) -> kv(1))
} def avoidBlank(stringOpt: Option[String]): Option[String] = {
} stringOpt.flatMap(s => if (s.trim.isEmpty) None else stringOpt)
map.getOrElse(key, "")
}
} }
def nonEmpty(stringOpt: Option[String]): Boolean = !isEmpty(stringOpt)
def isEmpty(stringOpt: Option[String]): Boolean = avoidBlank(stringOpt).isEmpty
} }
package cn.edu.jxnu.scala.utils package cn.edu.jxnu.utils.other
import play.api.mvc.{Action, Results} import play.api.mvc.{Action, Results}
import play.api.routing.sird._
import play.api.test.WsTestClient import play.api.test.WsTestClient
import play.core.server.Server import play.core.server.Server
import scala.concurrent.Await import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration import scala.concurrent.duration.Duration
/** /**
......
package cn.edu.jxnu.utils.scalikejdbc
import java.util.Properties
import com.typesafe.config.{Config, ConfigFactory}
import com.typesafe.scalalogging.LazyLogging
import com.zaxxer.hikari.{HikariConfig, HikariDataSource}
import scalikejdbc.{ConnectionPool, DB, DBSession, DataSourceConnectionPool, using}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
/**
* scalikejdbc 数据库连接池支持
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
trait RepositorySupport extends LazyLogging {
import RepositorySupport._
def readOnly[A](execution: DBSession A): Future[A] = concurrent.Future {
using(getDB) { db: DB =>
db.readOnly((session: DBSession) => execution(session))
}
}
def localTx[A](execution: DBSession A): Future[A] = concurrent.Future {
using(getDB) { db: DB =>
db.localTx((session: DBSession) => execution(session))
}
}
@deprecated
def localTxWithoutFuture[A](execution: DBSession A): A =
using(getDB) { db: DB =>
db.localTx((session: DBSession) => execution(session))
}
def getAutoCommitSession = getDB.autoCommitSession()
def getReadOnlySession = getDB.readOnlySession()
}
/**
* 数据库连接池,启动服务时需要执行init方法初始化数据库
*/
object RepositorySupport extends RepositorySupport {
def getConnectionPool: ConnectionPool = {
ConnectionPool.get()
}
def getDB: DB = {
DB(ConnectionPool.get().borrow())
}
private final lazy val defaultConfig = ConfigFactory.load("application.conf")
def init(config: Config = defaultConfig): Unit = {
logger.info("Init connection pool from config scalike")
val dataSourceConfig = getScalikeDatasourceProperties("seckill", config)
val _config = new HikariConfig(dataSourceConfig)
val dataSource = new HikariDataSource(_config)
ConnectionPool.singleton(new DataSourceConnectionPool(dataSource))
}
private def getScalikeDatasourceProperties(databaseName: String, config: Config): Properties = {
import scala.collection.JavaConverters._
val properties = new Properties()
properties.setProperty("dataSourceClassName", config.getString("scalike.dataSourceClassName"))
val databaseConfig = config.getConfig("scalike").getConfig(databaseName)
databaseConfig.entrySet().asScala.foreach { e =>
properties.setProperty(e.getKey, e.getValue.unwrapped().toString)
}
properties
}
}
\ No newline at end of file
package cn.edu.jxnu.utils.undertow
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.{Objects, UUID}
import com.google.common.net.HttpHeaders
import com.typesafe.scalalogging.Logger
import io.undertow.server.{ExchangeCompletionListener, HttpHandler, HttpServerExchange}
import io.undertow.util.HeaderValues
/**
* undertow 访问日志处理器
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
class AccessLogHandler(next: HttpHandler, service: Option[String]) extends HttpHandler {
private[this] val logger: Logger = Logger("access")
private[this] lazy val serviceName = service.getOrElse("-")
private[this] val listener: ExchangeCompletionListener =
(exchange: HttpServerExchange, nextListener: ExchangeCompletionListener.NextListener) => {
try {
val requestId = getRequestId(exchange)
logger.info(accessLogMessage(requestId, exchange))
} finally {
nextListener.proceed()
}
}
override def handleRequest(exchange: HttpServerExchange): Unit = {
exchange.addExchangeCompleteListener(listener)
next.handleRequest(exchange)
}
private[this] def getRequestId(exchange: HttpServerExchange): String = {
val requestId = exchange.getRequestHeaders.get("X-Request-Id")
if (isEmpty(requestId)) {
UUID.randomUUID().getLeastSignificantBits.toHexString
} else {
requestId.getFirst
}
}
private[this] def accessLogMessage(requestId: String, exchange: HttpServerExchange): String = {
val cost = (System.nanoTime() - exchange.getRequestStartTime) / 1000000.0
val path = exchange.getRequestPath
val status = exchange.getStatusCode
val headers = exchange.getRequestHeaders
val protocol = exchange.getProtocol.toString
val bytesSent = exchange.getResponseBytesSent
val method = exchange.getRequestMethod.toString
val referer = headers.get(HttpHeaders.REFERER)
val ua = headers.getFirst(HttpHeaders.USER_AGENT)
val now = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
val referred = if (isEmpty(referer)) "-" else referer.getFirst
val address = exchange.getSourceAddress.getAddress.getHostAddress
s"""$address $serviceName $requestId - [$now] "$method $path $protocol" $status $bytesSent $cost "$referred" "$ua""""
}
private[this] def isEmpty(values: HeaderValues): Boolean = Objects.isNull(values) || values.isEmpty
}
object AccessLogHandler {
def apply(next: HttpHandler): AccessLogHandler = new AccessLogHandler(next, None)
def apply(next: HttpHandler, service: String): AccessLogHandler = new AccessLogHandler(next, Option(service))
}
\ No newline at end of file
package cn.edu.jxnu.utils.undertow
import io.undertow.server.HttpServerExchange
/**
* undertow 异常处理器
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
trait ExceptionHandler {
def handleException(exchange: HttpServerExchange, cause: Throwable): Unit
}
package cn.edu.jxnu.utils.undertow
import java.nio.ByteBuffer
import java.util.concurrent.{Executor, Executors}
import cn.edu.jxnu.utils.concurrent.Executable
import com.typesafe.scalalogging.LazyLogging
import io.undertow.security.api.AuthenticationMechanism.AuthenticationMechanismOutcome
import io.undertow.server.{HttpHandler, HttpServerExchange}
import io.undertow.util.Methods._
import io.undertow.util.{Headers, StatusCodes}
import scala.concurrent.{ExecutionContext, Future}
import scala.runtime.BoxedUnit
/**
* undertow restful处理器接口
*
* @author 梦境迷离
* @time 2019-08-18
* @version v1.0
*/
trait RestfulHandler extends HttpHandler with Executable with LazyLogging {
private[this] lazy val contentType = "application/json;charset=utf-8"
private[this] implicit lazy val ec: ExecutionContext = ExecutionContext.fromExecutor(workers)
protected lazy val workers: Executor = Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors())
protected val exceptionHandler: ExceptionHandler
override def handleRequest(exchange: HttpServerExchange): Unit = {
exchange.dispatch(workers, () => {
lazy val exceptionCaught = (t: Throwable) => {
exceptionHandler.handleException(exchange, t)
exchange.endExchange()
logger.error(t.getLocalizedMessage, t)
}
executeSafely(
authenticate(exchange).map {
case AuthenticationMechanismOutcome.AUTHENTICATED =>
executeSafely({
val future = exchange.getRequestMethod match {
case GET => get(exchange)
case PUT => put(exchange)
case POST => post(exchange)
case PATCH => patch(exchange)
case DELETE => delete(exchange)
}
future.map {
case () | _: BoxedUnit =>
exchange.setStatusCode(StatusCodes.NO_CONTENT)
exchange.endExchange()
case result =>
exchange.getResponseHeaders.put(Headers.CONTENT_TYPE, contentType)
exchange.setStatusCode(getResponseStatusCode(exchange))
exchange.getResponseSender.send(ByteBuffer.wrap(writeAsBytes(result)))
}
}, exceptionCaught)
case outcome: AuthenticationMechanismOutcome =>
val (status, bytes) = authenticateFailureResponse(exchange, outcome)
exchange.setStatusCode(status)
if (bytes.nonEmpty) {
exchange.getResponseHeaders.put(Headers.CONTENT_TYPE, contentType)
exchange.getResponseSender.send(ByteBuffer.wrap(bytes))
}
exchange.endExchange()
}, exceptionCaught)
})
}
def writeAsBytes(result: Any): Array[Byte]
def getResponseStatusCode(exchange: HttpServerExchange): Int = {
exchange.getRequestMethod match {
case GET => StatusCodes.OK
case PUT => StatusCodes.OK
case POST => StatusCodes.CREATED
case PATCH => StatusCodes.NO_CONTENT
case DELETE => StatusCodes.NO_CONTENT
}
}
def authenticateFailureResponse(exchange: HttpServerExchange, outcome: AuthenticationMechanismOutcome): (Int, Array[Byte]) = {
val status = outcome match {
case AuthenticationMechanismOutcome.NOT_ATTEMPTED => StatusCodes.FORBIDDEN
case AuthenticationMechanismOutcome.NOT_AUTHENTICATED => StatusCodes.UNAUTHORIZED
case AuthenticationMechanismOutcome.AUTHENTICATED => throw new IllegalStateException("Request has authenticated")
}
status -> Array.emptyByteArray
}
def authenticate(exchange: HttpServerExchange): Future[AuthenticationMechanismOutcome] = {
Future.successful(AuthenticationMechanismOutcome.AUTHENTICATED)
}
def get(exchange: HttpServerExchange): Future[Any] = Future.failed(new UnsupportedOperationException)
def put(exchange: HttpServerExchange): Future[Any] = Future.failed(new UnsupportedOperationException)
def patch(exchange: HttpServerExchange): Future[Unit] = Future.failed(new UnsupportedOperationException)
def post(exchange: HttpServerExchange): Future[Any] = Future.failed(new UnsupportedOperationException)
def delete(exchange: HttpServerExchange): Future[Unit] = Future.failed(new UnsupportedOperationException)
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册