Skip to content

Commit

Permalink
Merge pull request #126 from hmrc/BDOG-1338
Browse files Browse the repository at this point in the history
BDOG-1338
  • Loading branch information
chotai authored Mar 31, 2021
2 parents f14b09f + 22d5670 commit 12f5c5b
Show file tree
Hide file tree
Showing 28 changed files with 271 additions and 247 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
| HeaderNames package change | Minor | [Scalafix available](https://github.com/hmrc/scalafix-rules/blob/master/http-verbs-13/rules/src/main/scala/fix/HttpVerbs13RenamePackages.scala) |
| URLs can now be supplied as `java.net.URL` | Minor | Optional change |
| Removed deprecated values from `SessionKeys` | Minor | Use auth client retrievals |
| All sent request headers explicitly passed to HttpHook | Minor | Distinction between sent headers and HeaderCarrier is useful|
| Transport layer explicitly passed all headers (e.g doPost) | Minor | All headers can be obtained from HeaderCarrier.headersForUrl |

To run a scalafix rule on your project, please refer to [the usage docs](https://github.com/hmrc/scalafix-rules#usage).

Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def sharedSources = Seq(
Compile / unmanagedSourceDirectories += baseDirectory.value / "../http-verbs-common/src/main/scala",
Compile / unmanagedResourceDirectories += baseDirectory.value / "../http-verbs-common/src/main/resources",
Test / unmanagedSourceDirectories += baseDirectory.value / "../http-verbs-common/src/test/scala",
Test / unmanagedResourceDirectories += baseDirectory.value / "../http-verbs-common/src/test/resources",
Test / unmanagedResourceDirectories += baseDirectory.value / "../http-verbs-common/src/test/resources"
)

def copySources(module: Project) = Seq(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ case class HeaderCarrier(
}

object HeaderCarrier {

def headersForUrl(
config: Config,
url: String,
extraHeaders: Seq[(String, String)] = Seq()
)(
implicit hc: HeaderCarrier
): Seq[(String, String)] =
hc.withExtraHeaders(extraHeaders: _*).headersForUrl(config)(url)

case class Config(
internalHostPatterns : Seq[Regex] = Seq.empty,
headersAllowlist : Seq[String] = Seq.empty,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ trait HttpDelete
with HttpHooks
with Retries {

private lazy val hcConfig = HeaderCarrier.Config.fromConfig(configuration)

override def DELETE[O](url: String, headers: Seq[(String, String)] = Seq.empty)(implicit rds: HttpReads[O], hc: HeaderCarrier, ec: ExecutionContext): Future[O] =
withTracing(DELETE_VERB, url) {
val httpResponse = retry(DELETE_VERB, url)(doDelete(url, headers))
executeHooks(url, DELETE_VERB, None, httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(DELETE_VERB, url)(doDelete(url, allHeaders))
executeHooks(DELETE_VERB, url"$url", allHeaders, None, httpResponse)
mapErrors(DELETE_VERB, url, httpResponse).map(rds.read(DELETE_VERB, url, _))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import scala.concurrent.{ExecutionContext, Future}

trait HttpGet extends CoreGet with GetHttpTransport with HttpVerb with ConnectionTracing with HttpHooks with Retries {

private lazy val hcConfig = HeaderCarrier.Config.fromConfig(configuration)

override def GET[A](
url: String,
queryParams: Seq[(String, String)],
Expand All @@ -43,8 +45,9 @@ trait HttpGet extends CoreGet with GetHttpTransport with HttpVerb with Connectio
val urlWithQuery = url + makeQueryString(queryParams)

withTracing(GET_VERB, urlWithQuery) {
val httpResponse = retry(GET_VERB, urlWithQuery)(doGet(urlWithQuery, headers = headers))
executeHooks(url, GET_VERB, None, httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(GET_VERB, urlWithQuery)(doGet(urlWithQuery, headers = allHeaders))
executeHooks(GET_VERB, url"$url", allHeaders, None, httpResponse)
mapErrors(GET_VERB, urlWithQuery, httpResponse).map(response => rds.read(GET_VERB, urlWithQuery, response))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ trait HttpPatch
with HttpHooks
with Retries {

private lazy val hcConfig = HeaderCarrier.Config.fromConfig(configuration)

override def PATCH[I, O](
url: String,
body: I,
Expand All @@ -40,8 +42,9 @@ trait HttpPatch
hc: HeaderCarrier,
ec: ExecutionContext): Future[O] =
withTracing(PATCH_VERB, url) {
val httpResponse = retry(PATCH_VERB, url)(doPatch(url, body, headers))
executeHooks(url, PATCH_VERB, Option(HookData.FromString(Json.stringify(wts.writes(body)))), httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(PATCH_VERB, url)(doPatch(url, body, allHeaders))
executeHooks(PATCH_VERB, url"$url", allHeaders, Option(HookData.FromString(Json.stringify(wts.writes(body)))), httpResponse)
mapErrors(PATCH_VERB, url, httpResponse).map(response => rds.read(PATCH_VERB, url, response))
}
}
22 changes: 14 additions & 8 deletions http-verbs-common/src/main/scala/uk/gov/hmrc/http/HttpPost.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ trait HttpPost
with HttpHooks
with Retries {

private lazy val hcConfig = HeaderCarrier.Config.fromConfig(configuration)

override def POST[I, O](
url: String,
body: I,
Expand All @@ -40,8 +42,9 @@ trait HttpPost
hc: HeaderCarrier,
ec: ExecutionContext): Future[O] =
withTracing(POST_VERB, url) {
val httpResponse = retry(POST_VERB, url)(doPost(url, body, headers))
executeHooks(url, POST_VERB, Option(HookData.FromString(Json.stringify(wts.writes(body)))), httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(POST_VERB, url)(doPost(url, body, allHeaders))
executeHooks(POST_VERB, url"$url", allHeaders, Option(HookData.FromString(Json.stringify(wts.writes(body)))), httpResponse)
mapErrors(POST_VERB, url, httpResponse).map(rds.read(POST_VERB, url, _))
}

Expand All @@ -53,8 +56,9 @@ trait HttpPost
hc: HeaderCarrier,
ec: ExecutionContext): Future[O] =
withTracing(POST_VERB, url) {
val httpResponse = retry(POST_VERB, url)(doPostString(url, body, headers))
executeHooks(url, POST_VERB, Option(HookData.FromString(body)), httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(POST_VERB, url)(doPostString(url, body, allHeaders))
executeHooks(POST_VERB, url"$url", allHeaders, Option(HookData.FromString(body)), httpResponse)
mapErrors(POST_VERB, url, httpResponse).map(rds.read(POST_VERB, url, _))
}

Expand All @@ -66,8 +70,9 @@ trait HttpPost
hc: HeaderCarrier,
ec: ExecutionContext): Future[O] =
withTracing(POST_VERB, url) {
val httpResponse = retry(POST_VERB, url)(doFormPost(url, body, headers))
executeHooks(url, POST_VERB, Option(HookData.FromMap(body)), httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(POST_VERB, url)(doFormPost(url, body, allHeaders))
executeHooks(POST_VERB, url"$url", allHeaders, Option(HookData.FromMap(body)), httpResponse)
mapErrors(POST_VERB, url, httpResponse).map(rds.read(POST_VERB, url, _))
}

Expand All @@ -78,8 +83,9 @@ trait HttpPost
hc: HeaderCarrier,
ec: ExecutionContext): Future[O] =
withTracing(POST_VERB, url) {
val httpResponse = retry(POST_VERB, url)(doEmptyPost(url, headers))
executeHooks(url, POST_VERB, None, httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(POST_VERB, url)(doEmptyPost(url, allHeaders))
executeHooks(POST_VERB, url"$url", allHeaders, None, httpResponse)
mapErrors(POST_VERB, url, httpResponse).map(rds.read(POST_VERB, url, _))
}
}
12 changes: 8 additions & 4 deletions http-verbs-common/src/main/scala/uk/gov/hmrc/http/HttpPut.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import scala.concurrent.{ExecutionContext, Future}

trait HttpPut extends CorePut with PutHttpTransport with HttpVerb with ConnectionTracing with HttpHooks with Retries {

private lazy val hcConfig = HeaderCarrier.Config.fromConfig(configuration)

override def PUT[I, O](
url: String,
body: I,
Expand All @@ -34,8 +36,9 @@ trait HttpPut extends CorePut with PutHttpTransport with HttpVerb with Connectio
hc: HeaderCarrier,
ec: ExecutionContext): Future[O] =
withTracing(PUT_VERB, url) {
val httpResponse = retry(PUT_VERB, url)(doPut(url, body, headers))
executeHooks(url, PUT_VERB, Option(HookData.FromString(Json.stringify(wts.writes(body)))), httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(PUT_VERB, url)(doPut(url, body, allHeaders))
executeHooks(PUT_VERB, url"$url", allHeaders, Option(HookData.FromString(Json.stringify(wts.writes(body)))), httpResponse)
mapErrors(PUT_VERB, url, httpResponse).map(response => rds.read(PUT_VERB, url, response))
}

Expand All @@ -47,8 +50,9 @@ trait HttpPut extends CorePut with PutHttpTransport with HttpVerb with Connectio
hc: HeaderCarrier,
ec: ExecutionContext): Future[O] =
withTracing(PUT_VERB, url) {
val httpResponse = retry(PUT_VERB, url)(doPutString(url, body, headers))
executeHooks(url, PUT_VERB, Option(HookData.FromString(body)), httpResponse)
val allHeaders = HeaderCarrier.headersForUrl(hcConfig, url, headers)
val httpResponse = retry(PUT_VERB, url)(doPutString(url, body, allHeaders))
executeHooks(PUT_VERB, url"$url", allHeaders, Option(HookData.FromString(body)), httpResponse)
mapErrors(PUT_VERB, url, httpResponse).map(rds.read(PUT_VERB, url, _))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,14 @@ trait GetHttpTransport {
def doGet(
url: String,
headers: Seq[(String, String)] = Seq.empty)(
implicit hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]
implicit ec: ExecutionContext): Future[HttpResponse]
}

trait DeleteHttpTransport {
def doDelete(
url: String,
headers: Seq[(String, String)] = Seq.empty)(
implicit hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]
implicit ec: ExecutionContext): Future[HttpResponse]
}

trait PatchHttpTransport {
Expand All @@ -44,7 +42,6 @@ trait PatchHttpTransport {
body: A,
headers: Seq[(String, String)] = Seq.empty)(
implicit rds: Writes[A],
hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]
}

Expand All @@ -54,15 +51,13 @@ trait PutHttpTransport {
body: A,
headers: Seq[(String, String)] = Seq.empty)(
implicit rds: Writes[A],
hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]

def doPutString(
url: String,
body: String,
headers: Seq[(String, String)] = Seq.empty)(
implicit hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]
implicit ec: ExecutionContext): Future[HttpResponse]
}

trait PostHttpTransport {
Expand All @@ -71,28 +66,24 @@ trait PostHttpTransport {
body: A,
headers: Seq[(String, String)] = Seq.empty)(
implicit wts: Writes[A],
hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]

def doPostString(
url: String,
body: String,
headers: Seq[(String, String)] = Seq.empty)(
implicit hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]
implicit ec: ExecutionContext): Future[HttpResponse]

def doEmptyPost[A](
url: String,
headers: Seq[(String, String)] = Seq.empty)(
implicit hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]
implicit ec: ExecutionContext): Future[HttpResponse]

def doFormPost(
url: String,
body: Map[String, Seq[String]],
headers: Seq[(String, String)] = Seq.empty)(
implicit hc: HeaderCarrier,
ec: ExecutionContext): Future[HttpResponse]
implicit ec: ExecutionContext): Future[HttpResponse]
}

trait HttpTransport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,23 @@

package uk.gov.hmrc.http.hooks

import java.net.URL

import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse}

import scala.concurrent.{ExecutionContext, Future}

trait HttpHook {
def apply(url: String, verb: String, body: Option[HookData], responseF: Future[HttpResponse])(
def apply(
verb: String,
url: URL,
headers : Seq[(String, String)],
body: Option[HookData],
responseF: Future[HttpResponse]
)(
implicit hc: HeaderCarrier,
ec: ExecutionContext)
ec: ExecutionContext
)
}

sealed trait HookData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package uk.gov.hmrc.http.hooks

import java.net.URL

import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse}

import scala.concurrent.{ExecutionContext, Future}
Expand All @@ -26,25 +28,27 @@ trait HttpHooks {
val NoneRequired = Seq(
new HttpHook {
def apply(
url : String,
verb : String,
url : URL,
headers : Seq[(String, String)],
body : Option[HookData],
responseF: Future[HttpResponse]
)(implicit
hc: HeaderCarrier,
ec: ExecutionContext
) = {}
)(
implicit hc: HeaderCarrier,
ec: ExecutionContext
): Unit = {}
}
)

protected def executeHooks(
url : String,
verb : String,
body : Option[HookData],
verb : String,
url : URL,
headers: Seq[(String, String)],
body : Option[HookData],
responseF: Future[HttpResponse]
)(implicit
hc: HeaderCarrier,
)(
implicit hc: HeaderCarrier,
ec: ExecutionContext
): Unit =
hooks.foreach(_.apply(url, verb, body, responseF))
hooks.foreach(_.apply(verb, url, headers, body, responseF))
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

package uk.gov.hmrc.http.logging

import org.slf4j.LoggerFactory
import uk.gov.hmrc.http.{HttpException, Upstream4xxResponse}
import org.slf4j.{Logger, LoggerFactory}
import uk.gov.hmrc.http.{HttpException, UpstreamErrorResponse}

import scala.concurrent._
import scala.util.{Failure, Success, Try}

trait ConnectionTracing {

lazy val connectionLogger = LoggerFactory.getLogger("connector")
lazy val connectionLogger: Logger = LoggerFactory.getLogger("connector")

def withTracing[T](method: String, uri: String)(
body: => Future[T])(implicit ld: LoggingDetails, ec: ExecutionContext): Future[T] = {
Expand All @@ -34,18 +34,18 @@ trait ConnectionTracing {
f
}

def logResult[A](ld: LoggingDetails, method: String, uri: String, startAge: Long)(result: Try[A]) = result match {
case Success(ground) => connectionLogger.debug(formatMessage(ld, method, uri, startAge, "ok"))
def logResult[A](ld: LoggingDetails, method: String, uri: String, startAge: Long)(result: Try[A]): Unit = result match {
case Success(_) => connectionLogger.debug(formatMessage(ld, method, uri, startAge, "ok"))
case Failure(ex: HttpException) if ex.responseCode == 404 =>
connectionLogger.info(formatMessage(ld, method, uri, startAge, s"failed ${ex.getMessage}"))
case Failure(ex: Upstream4xxResponse) if ex.upstreamResponseCode == 404 =>
connectionLogger.info(formatMessage(ld, method, uri, startAge, s"failed ${ex.getMessage}"))
case Failure(ex: UpstreamErrorResponse) if ex.statusCode == 404 =>
connectionLogger.info(formatMessage(ld, method, uri, startAge, s"failed ${ex.message}"))
case Failure(ex) => connectionLogger.warn(formatMessage(ld, method, uri, startAge, s"failed ${ex.getMessage}"))
}

import uk.gov.hmrc.http.logging.ConnectionTracing.formatNs

def formatMessage(ld: LoggingDetails, method: String, uri: String, startAge: Long, message: String) = {
def formatMessage(ld: LoggingDetails, method: String, uri: String, startAge: Long, message: String): String = {
val requestId = ld.requestId.getOrElse("")
val requestChain = ld.requestChain
val durationNs = ld.age - startAge
Expand Down
Loading

0 comments on commit 12f5c5b

Please sign in to comment.