Just Handlers

Just Handlers

If you issue a request and receive a response, you need to create a handler. dispatch provides some handy handlers to convert the response body to a string, XML or using whatever function you have that converts a request to an output value.

Some of the as.* that you have out of the box include:

  • as.Response: Returns the raw response object.

  • as.String.utf8: Returns utf8 string.

  • as.Bytes: Returns bytes.

  • as.File(yourfile): Redirects the body to a file.

  • as.XML: Creates XML a scala scala.xml.Elem.

You can also pass in your own function that handles a full async-http-client Response and returns some value derived from it. For example, the response body is available as Reseponse.getResponseBody so you could do:

@ Http(host("localhost:9000") > { _.getResponseBody} ) onComplete println 
Success(<h1>you have reached the example server</h1>)

which does the same thing as as.String but illustrates the syntax somewhat. You could also define your function elsewhere and use it instead of {_.getResponseBody}. You should notice that this function only runs after the entire response has been received so you lose as-you-get-it processing capabilities using this approach. You can also provide your own AsyncHandler directly and use >.

Generally, you will wan to use OK and your handler, a function Response => T so that your function only runs if the call was successful:

@ Http(host("localhost:9000") OK { _.getResponseBody} ) onComplete println 
Success(<h1>you have reached the example server</h1>)
@ Http(host("localhost:9000") OK { _.getStatusCode} ) onComplete println 
Success(200)

The > function and AsyncHandler

The > function to create a handler is overloaded. You can provide a function, like we did in the last section, or an AsyncHandler.

There is also a handler at at.stream.Lines that takes a String => T function parameter that processes each line of response using the function parameter. If we alter our example-server program to return a well known set of lines:

then we can use it like:

Using the handler this way is clearly being used for its side-effects. We also used the > method which directly takes an async-http-client AsyncHandler directly. When you want explicit control over response processing you would write your own AsyncHandler. You would use this, for example, to interface to a processing library like monix.

json response handling

XML is a bit deprecated today and the new hotness, for the past decade actually, has really been json.

dispatch has json support for a few libarries but does not restrict you to only using them. Everyone uses a different json library it seems.

First, we need to alter our example server to return some json, the route will add is:

There are a few add-ons for json support provided by dispatch. We will show the one based on lift json, which has not been updated in a long time, but still works of course:

You call the handle just like the other handlers, as.lift.Json and get back a json object:

The code for the handler suggests how simple it is to create your own json handler:

You can see that using a combinator of andThen you can piece together the handlers and build on previous handlers. First as.String reads the response body and converts it to a String then JsonParser.parse parses that result. You can do this because a handler is defined as a function and you can compose functions.

The circe library is the new hotness for json parsing, based on argonaut but faster (here on github). We just need a "handler" that takes a response to a circe json object, which is based on a cats library object since circe uses cats underneath:

Which prints out:

the result we expect.

Last updated

Was this helpful?