В этом блоге мы продемонстрируем отклонение в Akka HTTP и как оно помогает в обработке сценариев ошибок в нашем приложении. Давайте начнем.
Концепция отклонения в Akka HTTP помогает правильно справляться со сценариями ошибок. Например, с помощью директивы фильтрации, такой как директива get , она не позволяет запросу проходить через его внутренний маршрут. Поскольку условие фильтра не выполняется, вызывается концепция отклонения.
Оператор ~
(Тильда) также называется оператором связывания. Поскольку он используется для соединения двух или более путей, запрос позволяет проходить через структуру маршрутизации. И попробуйте найти другой маршрут, который может завершить его. Если запрос не находит какой-либо маршрут, он будет отклонен.
Вам также может понравиться: Обработка отклонений в Akka HTTP
По умолчанию ответ на отклоненные запросы был сгенерирован методом «handle not found » RejectionHandler
.
Scala
xxxxxxxxxx
1
trait RejectionHandler extends (immutable.Seq[Rejection] ⇒Option[Route])
Мы поймем это подробно на следующем примере:
Scala
xxxxxxxxxx
1
val route: Route =
2
path("hello") {
3
get {
4
complete(HttpResponse(entity = "Hello world"))
5
} } ~
6
path("ping") {
7
get {
8
complete(HttpResponse(entity = "PONG!")) }
9
}
Если мы получим доступ к пути с помощью «hello», то получим ответ «Hello world». В то же время мы получим ответ «PONG!» по маршруту «пинг».
У вас могут возникнуть такие вопросы, как: «Что произойдет, если мы выберем другой маршрут?» Мы получим следующий ответ: «Запрошенный ресурс не найден».
Если мы хотим, чтобы этот ответ был более описательным, мы можем настроить RejectionHandler
. Самый простой способ создать это с помощью Akka HTTP. RejectionHandler
RejectionHandler.newBuilder()
Обратитесь к следующему фрагменту кода:
Scala
xxxxxxxxxx
1
implicit def rejectionHandler = RejectionHandler.newBuilder()
2
.handleNotFound {
3
complete(HttpResponse(NotFound, entity = HttpEntity(ContentTypes.`application/json`, Json.stringify(
4
Json.toJson(
5
ErrorResponse(
6
NotFound.intValue, "NotFound", "The requested resource could not be found.")
7
)
8
)
9
)))
10
}
Мы получим ответ следующим образом:
Джава
xxxxxxxxxx
1
{
2
"code": 404,
3
"message": "NotFound",
4
"reason": "The requested resource could not be found."
5
}
Где ErrorResponse
класс дела:
case class ErrorResponse(code: Int, message: String, reason: String)
Есть три вспомогательных метода в RejectionHandler
:
1 handleNotFound(Route)
.:
Как описано в приведенном выше примере, «Ресурс не найден» является специальным. Так как он представлен с пустым набором отклонений, вспомогательный дескриптор not found позволяет вам указать «маршрут восстановления» для этого случая.
2 handle(PartialFunction[Rejection, Route])
.:
Ручки предоставили тип отклонения с заданной частичной функцией. Эта частичная функция создает маршрут, который запускается, когда происходит определенный отказ.
3 handleAll[T <: Rejection: ClassTag](f: immutable.Seq[T] => Route)
.:
Обрабатывает все отклонения определенного типа одновременно. Это полезно в тех случаях, когда вам необходим доступ не только к первому отклонению определенного типа, например, для выдачи сообщения об ошибке неподдерживаемому методу запроса.
Есть много предопределенных отклонений, которые предоставляются Akka HTTP. Они MethodRejection
, AuthorizationFailedRejection
, MissingCookieRejection
, и MissingQueryParamRejection
.
Мы вызывали эти вызовы дескрипторов через неявное определение, используя « newBuilder()
» для создания нового RejectionHandler
. Мы можем сказать этому обработчику, как обрабатывать тот или иной отказ.
1 MethodRejection
.:
Это отклонение происходит, когда пользователь использует неподдерживаемый метод для доступа к запросу. В следующем примере поддерживается метод get
. Это произведет отказ при попытке доступа с помощью post
, put
или любой другой метод.
Scala
xxxxxxxxxx
1
val route: Route =
2
path("hello") {
3
get {
4
complete(HttpResponse(OK, entity = HttpEntity(ContentTypes.`application/json`, Json.stringify(
5
Json.toJson(
6
ProperResponse(
7
OK.intValue,"Hello world")))
8
)))}
9
}
10
implicit def rejectionHandler = RejectionHandler.newBuilder()
11
.handleAll[MethodRejection] { methodRejections =>
13
val names = methodRejections.map(_.supported.name)
14
complete(HttpResponse(MethodNotAllowed, entity = HttpEntity(ContentTypes.`application/json`, Json.stringify(
15
Json.toJson(
16
ErrorResponse(
17
MethodNotAllowed.intValue, "Method Rejection", s"Method not supported! Supported for : ${names mkString "or"}!"))
18
)
19
)))
20
}
Для неподдерживаемого метода вывод будет:
Джава
xxxxxxxxxx
1
{
2
"code": 405,
3
"message": "Method Rejection",
4
"reason": "Method not supported! Supported for : GET!"
5
}
2 MissingQueryParamRejection
.:
MissingQueryParamRejection
возникает, когда пользователь не упоминает обязательные параметры в Request
.
В данном примере, если мы нажмем URL, localhost: 8080 / paint? Color = red .
В этом случае ответ будет:
В запросе отсутствует обязательный параметр запроса для = 'bgColor'.
И если мы нажмем URL, мы получим « localhost: 8080 / paint? BgColor = red .» Тогда ответ будет таким: «В запросе отсутствует обязательный параметр запроса для = 'color'».
Когда мы упоминаем оба параметра в URL localhost: 8080 / paint? BgColor = red & color = blue , мы получаем правильный результат:
Джава
xxxxxxxxxx
1
{
2
"code": 200,
3
"message": "You mention color is blue and background color is red"
4
}
3 AuthorizationFailedRejection
.:
Этот отказ создается директивой «санкционировать». Это означает, что запрос был отклонен, поскольку пользователь не авторизован.
Давайте посмотрим на пример:
Scala
xxxxxxxxxx
1
val route: Route =
2
path("login") {
3
parameters('username, 'password) {
4
(username, password) =>
5
if (username.equals("knoldus") && password.equals("pune")) {
6
complete(HttpResponse(NotFound,entity = HttpEntity(ContentTypes.`application/json`, Json.stringify(
7
Json.toJson(
8
ProperResponse(
9
OK.intValue, "Login Successful")))
10
)))}
11
else {
12
reject(AuthorizationFailedRejection)
13
} } }
14
implicit def rejectionHandler =
16
RejectionHandler.newBuilder()
17
.handle { case AuthorizationFailedRejection =>
18
complete(HttpResponse(BadRequest, entity = HttpEntity(ContentTypes.`application/json`, Json.stringify(
19
Json.toJson(
20
ErrorResponse(
21
BadRequest.intValue, "AuthorizationFailedRejection", "You have entered invalid credentials")
22
)
23
)
24
)))
25
}
26
Если мы найдем путь с правильными учетными значениями, такими как « localhost: 8080 / login? Username = knoldus & password = pune », мы получим ответ:
Джава
xxxxxxxxxx
1
{
2
"code": 200,
3
"message": "Login Successful"
4
}
Когда мы пытаемся предоставить доступ с неправильными значениями, такими как «localhost: 8080 / login? Username = software & password = abcd », мы получим ответ:
Джава
xxxxxxxxxx
1
{
2
"code": 400,
3
"message": "AuthorizationFailedRejection",
4
"reason": "You have entered invalid credentials"
5
}
В заключение, это то, как RejectionHandler
можно настроить обработку ошибок в коде. Вы можете просмотреть весь код на GitHub .
Спасибо за прочтение! Удачного кодирования!
Эта статья была первоначально опубликована на Блог Knoldus .