How to get response headers and body in dispatch request?

2.1k Views Asked by At

I want to get both body and headers from dispatch request. How to do this?

val response = Http(request OK as.String)
for (r <- response) yield {
  println(r.toString) //prints body
  // println(r.getHeaders) // ???? how to print headers here ???? 
}
2

There are 2 best solutions below

0
On BEST ANSWER

From the Dispatch docs:

import dispatch._, Defaults._
val svc = url("http://api.hostip.info/country.php")
val country = Http(svc OK as.String)

The above defines and initiates a request to the given host where 2xx responses are handled as a string. Since Dispatch is fully asynchronous, country represents a future of the string rather than the string itself. (source)

In your example, the type of response is Future[String], because 'OK as.String' converts 2xx responses into strings and non-2xx responses into failed futures. If you remove 'OK as.String', you'll get a Future[com.ning.http.client.Response]. You can then use getResponseBody, getHeaders, etc. to inspect the Request object.

0
On

We needed the response body of failed requests to an API, so we came up with this solution:

Define your own ApiHttpError class with code and body (for the body text):

case class ApiHttpError(code: Int, body: String)
  extends Exception("Unexpected response status: %d".format(code))

Define OkWithBodyHandler similar to what is used in the source of displatch:

class OkWithBodyHandler[T](f: Response => T) extends AsyncCompletionHandler[T] {
  def onCompleted(response: Response) = {
    if (response.getStatusCode / 100 == 2) {
      f(response)
    } else {
      throw ApiHttpError(response.getStatusCode, response.getResponseBody)
    }
  }
}

Now, near your call to the code that might throw and exception (calling API), add implicit override to the ToupleBuilder (again similar to the source code) and call OkWithBody on request:

class MyApiService {
  implicit class MyRequestHandlerTupleBuilder(req: Req) {
    def OKWithBody[T](f: Response => T) =
      (req.toRequest, new OkWithBodyHandler(f))
  }

  def callApi(request: Req) = {
    Http(request OKWithBody as.String).either
  }
}

From now on, fetching either will give you the [Throwable, String] (using as.String), and the Throwable is our ApiHttpError with code and body.

Hope it helped.