Для обработки ошибок верните ошибочный Future
. Например, сделайте проверку заголовка как Future
, а затем соедините ваши фьючерсы с .and_then
. Хитрость заключается в том, чтобы сохранить типы ошибок в будущем одинаковыми, чтобы избежать map_err
. Например:
fn handler(req: HttpRequest) -> impl Future<Item = HttpResponse, Error = Error> {
has_client_header(&req)
.and_then(|client| operation_that_returns_future(client))
.map(|result| HttpResponse::Ok().body(result))
}
fn has_client_header(req: &HttpRequest) -> impl Future<Item = String, Error = Error> {
if let Some(Ok(client)) = req.headers().get("x-client-id").map(|h| h.to_str()) {
future::ok(client.to_owned())
} else {
future::failed(ErrorBadRequest("invalid x-client-id header"))
}
}
fn operation_that_returns_future(client: String) -> impl Future<Item = String, Error = Error> {
future::ok(client)
}
Результат:
$ curl localhost:8000
invalid x-client-id header⏎
$ curl localhost:8000 -H 'x-client-id: asdf'
asdf⏎
Когда operation_that_returns_future
имеет другой тип ошибки:
fn handler(req: HttpRequest) -> impl Future<Item = HttpResponse, Error = Error> {
has_client_header(&req)
.and_then(|client| {
operation_that_returns_future(client)
.map_err(|_| ErrorInternalServerError("operation failed"))
})
.map(|result| HttpResponse::Ok().body(result))
}
Другой прием заключается в использовании ящика с ошибками , который предоставляет failure::Error::from
, который отображает все ошибки в один тип, failure::Error
.
Наконец, вы можете найти actix_web::guards
полезным для проверки значений заголовка:
.guard(guard::Header("x-client-id", "special client"))