scalascala-dispatch

Databinder dispatch: Get uncompressed content of a 403 response


I am using databinder dispatch for making HTTP requests which works nicely, as long as the web server returns a 404.

If the request fails, the web server returns a 403 status code and provides a detailed error message in the response body as XML.

How to read the xml body (regardless of the 403), e.g. how can I make dispatch ignore all 403 errors?

My code looks like this:

class HttpApiService(val apiAccount:ApiAccount) extends ApiService {
  val http = new Http

  override def baseUrl() = "http://ws.audioscrobbler.com/2.0"

  def service(call:Call) : Response = {
    val http = new Http
    var req = url(baseUrl())
    var params = call.getParameterMap(apiAccount)

    var response: NodeSeq = Text("")

    var request: Request = constructRequest(call, req, params)
    // Here a StatusCode exception is thrown. 
    // Cannot use StatusCode case matching because of GZIP compression
    http(request <> {response = _})
    //returns the parsed xml response as NodeSeq
    Response(response)
  }

  private def constructRequest(call: Call, req: Request, params: Map[String, String]): Request = {
    val request: Request = call match {
      case authCall: AuthenticatedCall =>
        if (authCall.isWriteRequest) req <<< params else req <<? params
      case _ => req <<? params
    }
    //Enable gzip compression
    request.gzip
  }
}

Solution

  • I believe something like this works:

    val response: Either[String, xml.Elem] = 
      try { 
        Right(http(request <> { r => r })) 
      } catch { 
        case dispatch.StatusCode(403, contents) => 
          Left(contents)
      }
    

    The error will be in Left. The success will be in Right. The error is a String that should contain the XML response you desire.

    If you need more, I believe you can look at HttpExecutor.x, which should give you full control. It's been a while since I've used dispatch, though.

    Also, I'd suggest using more val's and less var's.