2014-11-11 2 views
1

Когда я используюКак получить код ответа при использовании пользовательского объекта вместо HTTPResponse

val pipeline: HttpRequest => Future[HttpResponse] = addHeader(.......) ~> sendReceive ~>  unmarshal[HttpResponse]   

то я могу получить код состояния как это объект HttpResponse с помощью

val futureResponse = pipeline(Post(url, body)) futureResponse.map(_.status) 

Однако, когда Я использую пользовательский unmarshaller как:

val pipeline: HttpRequest => Future[MyResponse] = addHeader(.......) ~> sendReceive ~>  unmarshal[MyResponse] 

использованием

val myfutureResponse = pipeline(Post(url, body)) 
myutureResponse.map(_.status) 

не компилируется, поскольку он не может найти статус. Как получить код статуса здесь? Мне нужно использовать настраиваемый unmarshaller, чтобы иметь возможность десериализовать мой json-результат.

ответ

0

Наконец, я нашел ответ на основе вашего предложения

private def unmarshal[T: Unmarshaller](response: HttpResponse): T = { 
response.entity.as[T] match { 
    case Right(value) => value 
    case Left(error) ⇒ throw new PipelineException(error.toString) 
} 

}

Я изменил мой метод трубопроводного быть

val pipeline: HttpRequest => HttpResponse = addHeader(.......) ~> sendReceive 
val searchResponse = pipeline(Post(urlwithpath, queryString)).map { 
    response => response.status match { 
    case StatusCodes.OK => 
     Some(unmarshal[MyResponse](response)) 
    case StatusCodes.NotFound => print(StatusCodes.NotFound) 
    } 
} 

Теперь, когда я получил это из пути, Я правильно изучу API

1

Если вы жестко запрограммируете немаршаллер в конвейере, вы не сможете получить код состояния. Вы все равно получите код сбоя, поскольку они будут частью исключения, которое приведет к сбою Future.

Если вы действительно хотите сохранить эту информацию и использовать маркированный маршаллер в вашем трубопроводе вам нужно будет написать свой собственный ип-маршаллер, который может предоставить вам ответ такого рода:

case class Wrapper[T](response: T, status: StatusCode) 

val pipeline: HttpRequest => Future[Wrapper[MyResponse]] = addHeader(.......) ~> sendReceive ~> myUnmarshall[MyResponse] 

Этих может стать довольно сложной задачей, если вы не знаете внутренних органов. Другой вариант - не жестко закодировать бит unmarshall в вашем конвейере и вручную обработать JSON.

+0

Хорошо, круто. Спасибо за указатель, сделав запрос на получение тела, а затем сделав еще один запрос, чтобы получить код, это No No, я предполагал. Забавно, что я не знал, что у меня есть жесткие коды внутри unmarshaller. Я только следил за примерами, которые я нашел в Интернете. – Sheggetin

+0

Я имел в виду, что вы жестко кодируете unmarshaller как часть вашего конвейера. Вы можете посмотреть, как он реализован и реализовать его, если вы хотите иметь другое поведение. –

+0

Все еще не на 100 процентов яснее предлагаемого решения. К сожалению, к сожалению, в Интернете нет примеров. Одним из решений, которые я видел в Интернете, был метод, который мог бы захватить httpresonse и поставить в конвейер перед тем, как развязать, например 'code'def mapStatus: HttpResponse => HttpResponse = { case r @ HttpResponse (status, entity, _, _) => r.withEntity (entity.map ((ct, buf) => ContentType.'application/json' -> buf)) case x => x} val pipe: HttpRequest => Future [Wrapper [MyResponse] ] = addHeader (..) ~> sendReceive ~> mapStatus ~> myUnmarshall [MyResponse] – Sheggetin