Skip to content

Commit

Permalink
Merge pull request #223 from hmrc/PODS-9855
Browse files Browse the repository at this point in the history
PODS-9855 Migrate from HttpClientV1 to HttpClientV2 for all Connectors.
  • Loading branch information
rambabu-posa authored Oct 18, 2024
2 parents 22cba53 + 12624a0 commit af424c9
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 297 deletions.
40 changes: 22 additions & 18 deletions app/connectors/AddressLookupConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,37 @@ import config.FrontendAppConfig
import models.TolerantAddress
import play.api.Logger
import play.api.http.Status._
import play.api.libs.json.{JsObject, Json, Reads}
import play.api.libs.json.{Json, Reads}
import uk.gov.hmrc.http.HttpReads.Implicits._
import uk.gov.hmrc.http.{HeaderCarrier, HttpClient, HttpException, HttpResponse}
import uk.gov.hmrc.http.client.HttpClientV2
import uk.gov.hmrc.http.{HeaderCarrier, HttpException, HttpResponse, StringContextOps}

import scala.concurrent.{ExecutionContext, Future}

class AddressLookupConnector @Inject()(http: HttpClient, config: FrontendAppConfig) {
def addressLookupByPostCode(postCode: String)
(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Seq[TolerantAddress]] = {
class AddressLookupConnector @Inject()(httpClientV2: HttpClientV2, config: FrontendAppConfig) {

val schemeHc = hc.withExtraHeaders("X-Hmrc-Origin" -> "PODS")

val addressLookupUrl = s"${config.addressLookUp}/lookup"
def addressLookupByPostCode(postCode: String
)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Seq[TolerantAddress]] = {

val headers = Seq("X-Hmrc-Origin" -> "PODS")
val addressLookupUrl = url"${config.addressLookUp}/lookup"
implicit val reads: Reads[Seq[TolerantAddress]] = TolerantAddress.postCodeLookupReads

val lookupAddressByPostcode =Json.obj("postcode"->postCode)
http.POST[JsObject , HttpResponse](addressLookupUrl , lookupAddressByPostcode)(implicitly , implicitly, schemeHc, implicitly) flatMap {
case response if response.status equals OK =>
Future.successful {
response.json.as[Seq[TolerantAddress]]
.filterNot(a => a.addressLine1.isEmpty && a.addressLine2.isEmpty && a.addressLine3.isEmpty && a.addressLine4.isEmpty)
}
case response =>
val message = s"Address Lookup failed with status ${response.status} Response body :${response.body}"
Future.failed(new HttpException(message, response.status))
} recoverWith logExceptions

httpClientV2.post(addressLookupUrl)
.withBody(lookupAddressByPostcode)
.setHeader(headers: _*)
.execute[HttpResponse].map { response =>
response.status match {
case OK =>
response.json.as[Seq[TolerantAddress]]
.filterNot(a => a.addressLine1.isEmpty && a.addressLine2.isEmpty && a.addressLine3.isEmpty && a.addressLine4.isEmpty)
case _ =>
val message = s"Address Lookup failed with status ${response.status} Response body :${response.body}"
throw new HttpException(message, response.status)
}
} recoverWith logExceptions
}

private val logger = Logger(classOf[AddressLookupConnector])
Expand Down
40 changes: 22 additions & 18 deletions app/connectors/DeregistrationConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import play.api.Logger
import play.api.http.Status._
import play.api.libs.json._
import uk.gov.hmrc.http.HttpReads.Implicits._
import uk.gov.hmrc.http.{HeaderCarrier, HttpClient, HttpResponse}
import uk.gov.hmrc.http.client.HttpClientV2
import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse, StringContextOps}
import utils.HttpResponseHelper

import java.time.LocalDate
Expand All @@ -31,43 +32,47 @@ import scala.util.Failure

@ImplementedBy(classOf[DeregistrationConnectorImpl])
trait DeregistrationConnector {
def deregister(pspId: String, date: LocalDate)
(implicit hc: HeaderCarrier, ec: ExecutionContext) : Future[HttpResponse]
def deregister(pspId: String, date: LocalDate
)(implicit hc: HeaderCarrier, ec: ExecutionContext) : Future[HttpResponse]

def canDeRegister(psaId: String)
(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Boolean]
def canDeRegister(psaId: String
)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Boolean]
}

class DeregistrationConnectorImpl @Inject()(http: HttpClient, config: FrontendAppConfig)
class DeregistrationConnectorImpl @Inject()(httpClientV2: HttpClientV2, config: FrontendAppConfig)
extends DeregistrationConnector
with HttpResponseHelper {

private val logger = Logger(classOf[DeregistrationConnectorImpl])

override def deregister(pspId: String, date: LocalDate)
(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[HttpResponse] = {
val deregisterUrl = config.pspDeregistrationUrl.format(pspId)
val deregisterUrl = url"${config.pspDeregistrationUrl.format(pspId)}"
val data: JsObject = Json.obj(
"deregistrationDate"-> date.toString,
"reason" -> "1"
)

http.POST[JsObject, HttpResponse](deregisterUrl, data).map { response =>
httpClientV2.post(deregisterUrl)
.withBody(data)
.execute[HttpResponse] map { response =>
response.status match {
case OK => response
case _ => handleErrorResponse("POST", deregisterUrl)(response)
case _ => handleErrorResponse("POST", deregisterUrl.toString)(response)
}
} andThen {
case Failure(t: Throwable) => logger.warn("Unable to deregister PSP", t)
}
}
case Failure(t: Throwable) => logger.warn("Unable to deregister PSP", t)
}

}

override def canDeRegister(pspId: String)
(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Boolean] = {

val url = config.canDeregisterUrl.format(pspId)
val url = url"${config.canDeregisterUrl.format(pspId)}"

http.GET[HttpResponse](url).map { response =>
httpClientV2.get(url)
.execute[HttpResponse] map { response =>
response.status match {
case OK => response.json.validate[Boolean] match {
case JsSuccess(value, _) => value
Expand All @@ -76,12 +81,11 @@ class DeregistrationConnectorImpl @Inject()(http: HttpClient, config: FrontendAp
case NOT_FOUND =>
logger.debug(s"CanDeregister call returned a NOT_FOUND response with body ${response.body}")
true
case _ => handleErrorResponse("GET", url)(response)
case _ => handleErrorResponse("GET", url.toString)(response)
}


} andThen {
} andThen {
case Failure(t: Throwable) => logger.warn("Unable to get the response from can de register api", t)
}
}

}
32 changes: 18 additions & 14 deletions app/connectors/EmailConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import config.FrontendAppConfig
import models.{JourneyType, SendEmailRequest}
import play.api.Logger
import play.api.http.Status._
import play.api.libs.json.{JsValue, Json}
import play.api.libs.json.Json
import uk.gov.hmrc.crypto.{ApplicationCrypto, PlainText}
import uk.gov.hmrc.http.HttpReads.Implicits._
import uk.gov.hmrc.http.{HeaderCarrier, HttpClient, HttpResponse}
import uk.gov.hmrc.http.client.HttpClientV2
import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse, StringContextOps}

import java.net.URLEncoder
import java.nio.charset.StandardCharsets
Expand All @@ -38,7 +39,7 @@ case object EmailNotSent extends EmailStatus

class EmailConnector @Inject()(
appConfig: FrontendAppConfig,
http: HttpClient,
httpClientV2: HttpClientV2,
crypto: ApplicationCrypto
) {
private val logger = Logger(classOf[EmailConnector])
Expand All @@ -60,22 +61,25 @@ class EmailConnector @Inject()(
templateName: String,
templateParams: Map[String, String]
)(implicit hc: HeaderCarrier, executionContext: ExecutionContext): Future[EmailStatus] = {
val emailServiceUrl = s"${appConfig.emailApiUrl}/hmrc/email"
val emailServiceUrl = url"${appConfig.emailApiUrl}/hmrc/email"

val sendEmailReq = SendEmailRequest(List(emailAddress), templateName, templateParams, appConfig.emailSendForce,
callBackUrl(requestId, journeyType, pspId, emailAddress))
val jsonData = Json.toJson(sendEmailReq)

http.POST[JsValue, HttpResponse](emailServiceUrl, jsonData).map { response =>
response.status match {
case ACCEPTED =>
logger.debug(s"Email sent successfully for $journeyType")
EmailSent
case status =>
logger.warn(s"Sending Email failed for $journeyType with response status $status")
EmailNotSent
}
} recoverWith logExceptions
httpClientV2.post(emailServiceUrl)
.withBody(jsonData)
.execute[HttpResponse].map { response =>
response.status match {
case ACCEPTED =>
logger.debug(s"Email sent successfully for $journeyType")
EmailSent
case status =>
logger.warn(s"Sending Email failed for $journeyType with response status $status")
EmailNotSent
}
} recoverWith logExceptions

}

private def logExceptions: PartialFunction[Throwable, Future[EmailStatus]] = {
Expand Down
72 changes: 39 additions & 33 deletions app/connectors/EnrolmentConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import play.api.http.Status._
import play.api.libs.json.{Json, Writes}
import play.api.mvc.{AnyContent, RequestHeader}
import uk.gov.hmrc.http.HttpReads.Implicits._
import uk.gov.hmrc.http.{HttpClient, _}
import uk.gov.hmrc.http.client.HttpClientV2
import uk.gov.hmrc.http._
import utils.{HttpResponseHelper, RetryHelper}

import javax.inject.Inject
Expand All @@ -44,38 +45,41 @@ trait EnrolmentConnector {
}

@Singleton
class EnrolmentConnectorImpl @Inject()(val http: HttpClient,
config: FrontendAppConfig,
auditService: AuditService)
extends EnrolmentConnector
with RetryHelper
with HttpResponseHelper {
class EnrolmentConnectorImpl @Inject()(
val httpClientV2: HttpClientV2,
config: FrontendAppConfig,
auditService: AuditService
) extends EnrolmentConnector with RetryHelper with HttpResponseHelper {

private val logger = Logger(classOf[EnrolmentConnectorImpl])

override def enrol(enrolmentKey: String, knownFacts: KnownFacts)
(implicit w: Writes[KnownFacts],
hc: HeaderCarrier,
executionContext: ExecutionContext,
request: DataRequest[AnyContent]): Future[HttpResponse] =
override def enrol(enrolmentKey: String, knownFacts: KnownFacts
)(implicit w: Writes[KnownFacts],
hc: HeaderCarrier,
executionContext: ExecutionContext,
request: DataRequest[AnyContent]): Future[HttpResponse] =
retryOnFailure(() => enrolmentRequest(enrolmentKey, knownFacts), config) andThen
logExceptions(knownFacts)

private def enrolmentRequest(enrolmentKey: String, knownFacts: KnownFacts)
(implicit w: Writes[KnownFacts], hc: HeaderCarrier, executionContext: ExecutionContext,
request: DataRequest[AnyContent]): Future[HttpResponse] = {
val url: String = config.taxEnrolmentsUrl.format("HMRC-PODSPP-ORG")
http.PUT[KnownFacts, HttpResponse](url, knownFacts) flatMap {
response =>
response.status match {
case NO_CONTENT =>
auditService.sendEvent(PSPEnrolmentSuccess(request.externalId, enrolmentKey))
Future.successful(response)
case statusCode =>
auditService.sendEvent(PSPEnrolmentFailure(request.externalId, enrolmentKey, statusCode))
if (response.body.contains("INVALID_JSON")) logger.warn(s"INVALID_JSON returned from call to $url")
handleErrorResponse("PUT", url)(response)
}
private def enrolmentRequest(enrolmentKey: String, knownFacts: KnownFacts
)(implicit w: Writes[KnownFacts],
hc: HeaderCarrier,
executionContext: ExecutionContext,
request: DataRequest[AnyContent]): Future[HttpResponse] = {
val url = url"""${config.taxEnrolmentsUrl.format("HMRC-PODSPP-ORG")}"""

httpClientV2.put(url)
.withBody(knownFacts)
.execute[HttpResponse] flatMap { response =>
response.status match {
case NO_CONTENT =>
auditService.sendEvent(PSPEnrolmentSuccess(request.externalId, enrolmentKey))
Future.successful(response)
case statusCode =>
auditService.sendEvent(PSPEnrolmentFailure(request.externalId, enrolmentKey, statusCode))
if (response.body.contains("INVALID_JSON")) logger.warn(s"INVALID_JSON returned from call to $url")
handleErrorResponse("PUT", url.toString)(response)
}
}
}

Expand All @@ -85,8 +89,8 @@ class EnrolmentConnectorImpl @Inject()(val http: HttpClient,
logger.debug(s"Known Facts: ${Json.toJson(knownFacts)}")
}

override def deEnrol(groupId: String, pspId: String, userId: String)
(implicit hc: HeaderCarrier, ec: ExecutionContext, rh: RequestHeader): Future[HttpResponse] = {
override def deEnrol(groupId: String, pspId: String, userId: String
)(implicit hc: HeaderCarrier, ec: ExecutionContext, rh: RequestHeader): Future[HttpResponse] = {
retryOnFailure(
f = () => deEnrolmentRequest(groupId, pspId, userId),
config = config
Expand All @@ -95,12 +99,14 @@ class EnrolmentConnectorImpl @Inject()(val http: HttpClient,
logDeEnrolmentExceptions
}

private def deEnrolmentRequest(groupId: String, pspId: String, userId: String)
(implicit hc: HeaderCarrier, ec: ExecutionContext, rh: RequestHeader): Future[HttpResponse] = {
private def deEnrolmentRequest(groupId: String, pspId: String, userId: String
)(implicit hc: HeaderCarrier, ec: ExecutionContext, rh: RequestHeader): Future[HttpResponse] = {

val enrolmentKey = s"HMRC-PODSPP-ORG~PSPID~$pspId"
val deEnrolmentUrl = config.taxDeEnrolmentUrl.format(groupId, enrolmentKey)
http.DELETE[HttpResponse](deEnrolmentUrl) flatMap {
val deEnrolmentUrl = url"${config.taxDeEnrolmentUrl.format(groupId, enrolmentKey)}"

httpClientV2.delete(deEnrolmentUrl)
.execute[HttpResponse] flatMap {
case response if response.status equals NO_CONTENT =>
auditService.sendEvent(PSPDeenrolment(userId, pspId))
Future.successful(response)
Expand Down
40 changes: 22 additions & 18 deletions app/connectors/MinimalConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,21 @@ import play.api.Logger
import play.api.http.Status._
import play.api.libs.json.{JsError, JsResultException, JsSuccess, Json}
import uk.gov.hmrc.http.HttpReads.Implicits._
import uk.gov.hmrc.http.{HttpClient, _}
import uk.gov.hmrc.http.client.HttpClientV2
import uk.gov.hmrc.http._
import utils.HttpResponseHelper

import scala.concurrent.{ExecutionContext, Future}
import scala.util.Failure

@ImplementedBy(classOf[MinimalConnectorImpl])
trait MinimalConnector {
def getMinimalPspDetails(pspId: String)
(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[MinimalPSP]

def getMinimalPspDetails(pspId: String)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[MinimalPSP]

}

class MinimalConnectorImpl @Inject()(http: HttpClient, config: FrontendAppConfig)
class MinimalConnectorImpl @Inject()(httpClientV2: HttpClientV2, config: FrontendAppConfig)
extends MinimalConnector
with HttpResponseHelper {

Expand All @@ -44,22 +46,24 @@ class MinimalConnectorImpl @Inject()(http: HttpClient, config: FrontendAppConfig
override def getMinimalPspDetails(pspId: String)
(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[MinimalPSP] = {

val psaHc = hc.withExtraHeaders("pspId" -> pspId)

http.GET[HttpResponse](config.minimalDetailsUrl)(implicitly, psaHc, implicitly) map { response =>
val url = url"${config.minimalDetailsUrl}"
val headers = Seq("pspId" -> pspId)

response.status match {
case OK =>
Json.parse(response.body).validate[MinimalPSP] match {
case JsSuccess(value, _) => value
case JsError(errors) => throw JsResultException(errors)
}
httpClientV2.get(url)
.setHeader(headers: _*)
.execute[HttpResponse].map { response =>
response.status match {
case OK =>
Json.parse(response.body).validate[MinimalPSP] match {
case JsSuccess(value, _) => value
case JsError(errors) => throw JsResultException(errors)
}

case _ => handleErrorResponse("GET", config.minimalDetailsUrl)(response)
}
} andThen {
case Failure(t: Throwable) => logger.warn("Unable get minimal details", t)
}
case _ => handleErrorResponse("GET", config.minimalDetailsUrl)(response)
}
} andThen {
case Failure(t: Throwable) => logger.warn("Unable get minimal details", t)
}
}

}
Loading

0 comments on commit af424c9

Please sign in to comment.