这是我不断增长的validationRejectionHandler
我的Spray项目:
implicit def validationRejectionHandler = RejectionHandler {
case ValidationRejection(errMsg,_) :: _ =>
logger.info(s"received validation error: $errMsg")
complete(StatusCodes.Unauthorized,errMsg)
case MalformedQueryParamRejection(parameterName, errorMsg, cause) :: _ =>
logger.debug(s"received MalformedQueryParamRejection error: $errorMsg")
complete(BadRequest -> GenericMessageObj(s"The query parameter $parameterName was malformed: $errorMsg"))
case spray.routing.AuthorizationFailedRejection :: _ =>
//todo - this string shouldn't be here
logger.info("received authentication error")
complete(StatusCodes.Unauthorized, "User is not authorized to this resource")
case MalformedRequestContentRejection(msg, causeOpt) :: _ =>
complete {
causeOpt.map { cause =>
cause match {
case e: InvalidFormatException =>
val fieldNameMatcher = """\["(.+)"\]""".r.unanchored
val fieldTypeMatcher = """(\w+)$""".r.unanchored
e.getPath.toString match {
case fieldNameMatcher(fieldName) =>
e.getTargetType.toString match {
case fieldTypeMatcher(fieldType) =>
val fieldTypeLowerCase = fieldType.toLowerCase()
BadRequest -> GenericMessageObj(s"""Invalid data: "${fieldName}" must be a ${fieldTypeLowerCase} value, but received ${e.getValue}""")
case _ =>
BadRequest -> GenericMessageObj(s"""${e.getValue} is an improper type for field "${fieldName}""")
}
case _ =>
logger.debug(s"Failed pattern match: ${e.getPath.toString}")
BadRequest -> GenericMessageObj("Invalid payload format")
}
case e: UnrecognizedPropertyException => BadRequest -> GenericMessageObj(s"Unrecognized property: ${e.getPropertyName}")
case e: JsonMappingException =>
if(cause.getCause == null || cause.getCause.getMessage == null){
val deserializationMsgMatcher = """Can not deserialize instance of scala\.collection\.(Seq) out of (VALUE_NUMBER_INT) [\s\S]+"(name)":[+-]?\d\};[\s\S]+\["(\3)"\].+""".r.unanchored
cause.getMessage match {
case deserializationMsgMatcher(expected, actual, fieldName, _) =>
logger.debug(s"Desrializaiton error at $fieldName: Found $actual instead of $expected")
BadRequest -> GenericMessageObj(s"Invalid format for $fieldName")
case _ =>
BadRequest -> GenericMessageObj(s"${cause.getMessage}")
}
} else if (!cause.getCause.getMessage.isEmpty) {
BadRequest -> GenericMessageObj(cause.getCause.getMessage)
} else {
BadRequest -> GenericMessageObj(s"Invalid data format")
}
case _ => BadRequest -> GenericMessageObj(s"An unknown error occurred.")
}
}
}
case spray.routing.MissingHeaderRejection(headerName) :: _ =>
complete(BadRequest -> GenericMessageObj("%s header is missing.".format(headerName)))
}
}
这对我来说似乎很疯狂,这个复杂的代码 - 完全用正则数据来破译各种类型的错误 - 是在Spray中处理拒绝的方法,这样它就不会像这样将丑陋的消息吐回到API客户端:
{ "消息":"缺少所需的创作者属性'值' (索引2)\ n在[来源:{\ n \"来源\":\" k \",\ n \"值\" :[\ n {\ n \" dt \":\" 2015-10-15T16:27:42.014Z \",\ n \" id \& #34;:\" 0022A3000004E6E1 \",\ n \ n \"属性\":\" a \",\ n \&#34 ; _id \":\" 45809haoua \",\ n \" __ id \":\" a2p49t7ya4wop9h \",\ n \& #34; ___ id \":\" q2ph84yhtq4pthqg \" \ n}] \ n}; line:12,column:9](通过引用链:io.keenhome.device.models.DatumList [\" values \"] - > com.fasterxml.jackson.module.scala.deser。 BuilderWrapper [0])" }
如何处理这些错误消息(例如,将非垃圾返回给API客户端)而不必对可能发生变化的字符串执行正则表达式?
答案 0 :(得分:0)
啊,我明白了。这些疯狂的消息由Jackson生成(不是由Spray生成)。所以你有几个选择:
1)在handleExceptions指令中处理JSONObjectException
。
2)或者在到达路由之前捕获并转换JSONObjectException
到您的异常类中。然后我将使用自定义异常处理程序处理响应。
implicit def myExceptionHandler =
ExceptionHandler {
case ex: ExceptionWithUser => ctx => {
val user = ex.user
val cause = ex.getCause
logger.error(s"${cause.getClass.getSimpleName} for ${ex.user.name} [${ex.user.id}]", cause)
ctx.complete(StatusCodes.InternalServerError, ErrorResponse(ex.code, ex))
}
case ex: Throwable => ctx =>
logger.warning("Request {} could not be handled normally", ctx.request)
ctx.complete(StatusCodes.InternalServerError, ErrorResponse(StatusCodes.InternalServerError.intValue, ex))
}
对于拒绝,我使用自定义拒绝处理程序将默认文本akka-http拒绝转换为API客户期望的json响应(如果您愿意,我可以显示它)。