2013-03-11 4 views
16

У меня есть служба, которая возвращает один вариант [ProductDoc] в будущем (как Akka спросить)спрей маршрутизации 404 ответ

Как реагировать маршрутизации спрея, так что действительный repsonds продукт с продуктом, но неизвестно но хорошо сформированный возвращает 404?

Я хочу код, чтобы заполнить пробел здесь:

get { 
    path("products"/PathElement) { productID:String => 
     val productFuture = (productService ? ProductService.Get(productID)).mapTo[Option[ProductDoc]] 

     // THE CODE THAT GOES HERE SO THAT 
     // IF PRODUCT.ISDEFINED RETURN PRODUCT ELSE REJECT 

    } 
} 

Единственный способ, которым я могу получить, чтобы работать с этой мерзостью:

get { 
    path(PathElement) { productID:String => 
     val productFuture = (productService ? ProductService.Get(productID)).mapTo[Option[ProductDoc]] 
     provide(productFuture).unwrapFuture.hflatMap { 
     case x => provide(x) 
     } { hResponse:shapeless.::[Option[ProductDoc], HNil] => 
     hResponse.head match { 
      case Some(product) => complete(product) 
      case None => reject 
     } 
     } 
    } 
    } 

Это не может быть правильным способом для достижения этого, конечно? Это похоже на довольно простой шаблон, который, должно быть, кто-то уже решил!

ответ

17

Спрей уже имеет поддержку для вашего случая использования: Значение опциона None по умолчанию составлено по умолчанию EmptyEntity. Вероятно, это то, что вы видели, прежде чем вы внесли какие-либо изменения: 200 с пустым документом. Существует директива, которая преобразует пустой документ в 404, rejectEmptyResponse, который вы обертываете вокруг частей своего маршрута, где вы хотите этого поведения.

Ваш маршрут будет выглядеть так же, как это:

rejectEmptyResponse { 
    path("products"/PathElement) { productID:String => 
     val productFuture = // same as before 
     complete(productFuture) 
    } 
    } 

Конечно, вы можете поставить rejectEmptyResponse в пути в зависимости от того, хотите ли вы, чтобы обернуть несколько частей маршрута с ним.

Подробнее:

+0

Означает ли это, что мое обещание должно вернуть успех, но с пустым ответом, когда у меня есть ошибка в моей логике или слое dao? –

+0

Я не совсем понимаю, чего вы хотите достичь. Эта тема была о 'Future [Option [T]]'. Используя вышеприведенную структуру, вы можете вернуть 'Success (Some (x))' для регулярного ответа, 'Success (None)' for 404 и 'Failure (x)' для генерации ответа об ошибке. Это то, что вы просите? Если у вас есть более конкретный вопрос, пожалуйста, спросите в списке рассылки распылителя. – jrudolph

+0

Мне не кажется, что Spray действительно поддерживает этот прецедент. Что относительно 200 пустого ответа, например, команда удаления? Станет ли он 404? – dividebyzero

0

я та же проблема несколько дней назад и пришел к такому решению:

Я добавил этот метод к моему актеру

def failIfEmpty[T](item: Future[Option[T]], id: String) = { 
    (item map { 
     case Some(t) => t 
     case None => throw NotFoundException(Message(s"id '$id' could not be  found",`ERROR`)) 
    }) pipeTo sender 
} 

Конечно, вы можете выбрать исключение, вам нравится, NotFoundException это один мой собственный ...

Зова это на результате, чтобы ответить на спроси у вашего актера (это пример использования ReactiveMongo, замените collection.find(query).headOption с вашими Future[Option]):

failIfEmpty(collection.find(query).headOption, id) 

Затем добавьте ExceptionHandler к вашим услугам (где определен маршрут), как следующее:

implicit val klaraExceptionHandler = ExceptionHandler.fromPF { 
    case InternalServerErrorException(messages) => complete(InternalServerError, messages) 
    case NotFoundException(message) => complete(NotFound, message) 
    case ValidationException(messages) => complete(PreconditionFailed, messages) 
    [and so on] 
} 

Таким образом, вы можете обрабатывать несколько различных ошибок, которые происходят в моем будущих-результатах.

 Смежные вопросы

  • Нет связанных вопросов^_^