http-verbs is a Java library bridging to http-verbs.
In your SBT build add:
resolvers += Resolver.bintrayRepo("hmrc", "releases")
libraryDependencies += "uk.gov.hmrc" %% "http-verbs-java" % "x.x.x"
Each verb is available as both an agnostic Http___
interface and a play-specific WS___
interface. They can be used as default interfaces:
import uk.gov.hmrc.play.java.http.*;
import uk.gov.hmrc.play.java.http.ws.*;
class ConnectorWithMixins implements HttpGet, HttpPost {
...
}
Each verb supplies a single matching method, which takes a URL, and a request body if appropriate:
http.doGet("http://gov.uk/hmrc", headerCarrier)
http.doDelete("http://gov.uk/hmrc", headerCarrier)
http.doPost("http://gov.uk/hmrc", body = "hi there")
http.doPut("http://gov.uk/hmrc", body = "hi there")
All calls require a HeaderCarrier
.
Headers from the carrier are added to every request. This allows:
- Common headers to be configured for all requests
- Headers from an inbound call to be propagated to an outbound one (we do this by implicitly converting Play's
Request
into aHeaderCarrier
)
All verbs return Future
s. By default, a HttpResponse
is returned for successful responses, which gives access to the status code, raw body and headers:
val r1 = http.GET("http://gov.uk/hmrc") // Returns an HttpResponse
val r2 = http.GET[HttpResponse]("http://gov.uk/hmrc") // Can specify this explicitly
r1.map { r =>
r.status
r.body
r.allHeaders
}
To make microservice development simple, responses with non-200 status codes will cause a failed Future
to be returned with a typed exception. This allows failures to be propagated back naturally.
Status Code | Exception |
---|---|
400 | BadRequestException |
404 | NotFoundException |
4xx | Upstream4xxResponse |
5xx | Upstream5xxResponse |
For all possible exception types, see the hmrc/http-exceptions project
If some failure status codes are expected in normal flow, recover
can be used:
httpGet.GET("url") recover {
case nf: NotFoundException => ...
case se: Upstream5xxResponse => ...
}
or if you expect responses which indicate no content, you can use an Option[...]
return type.
http-verbs can automatically map responses into richer types.
If you have an implicit play.api.libs.json.Reads[A]
for your type in scope, just specify that type and it will be automatically deserialised.
import play.api.libs.json._
case class MyCaseClass(a: String, b: Int)
implicit val f = Json.reads[MyCaseClass]
http.GET[MyCaseClass]("http://gov.uk/hmrc") // Returns an MyCaseClass de-serialised from JSON
If you wish to use HTML responses, Play's Html
type can be used:
import play.twirl.api.Html
http.GET[Html]("http://gov.uk/hmrc") // Returns a Play Html type
If you expect to receive a 204
or 404
response in some circumstances, then you can add Option[...]
to your return type:
http.GET[Option[MyCaseClass]]("http://gov.uk/hmrc") // Returns None, or Some[MyCaseClass] de-serialised from JSON
http.GET[Option[Html]]("http://gov.uk/hmrc") // Returns a None, or a Play Html type
Response handling is implemented via the HttpReads[A]
typeclass, which is responsible for converting the raw response into either an exception or the specified type. Default implementations of HttpReads[A]
have been provided in its companion object to cover common use cases, but clients may provide their own implementations if required.
You can now set up http-verbs to run a series of callbacks when the future representing an http request completes - these are known as hooks. Hooks are used by play-auditing in order to wire up implicit auditing.
A hook looks like this:
object MyHook extends HttpHook {
override def apply(url: String, verb: String, body: Option[_], responseF: Future[HttpResponse])(implicit hc: HeaderCarrier): Unit = {
responseF.map {
response => // do something on success
}.recover {
case e: Throwable => // do something on exception
}
}
}
And is registered with http-verbs like this:
object WSHttp extends WSGet with WSPut with WSPost with WSDelete with WSPatch {
override val hooks = Seq(MyHook, AnotherHook)
...
...
}
This code is open source software licensed under the Apache 2.0 License.