HTTP-Verbos es una biblioteca Scala que proporciona una interfaz para realizar llamadas HTTP asíncronas.
Encapsula algunas preocupaciones comunes por llamar a otros servicios HTTP en la plataforma fiscal HMRC, que incluyen:
Ver ChangeLog para cambios y migraciones.
En su compilación SBT ADD:
resolvers + = MavenRepository ( " HMRC-open-artefacts-maven2 " , " https://open.artefacts.tax.service.gov.uk/maven2 " )
libraryDependencies + = " uk.gov.hmrc " %% " http-verbs-play-xx " % " x.x.x " Donde play-xx es tu versión de Play (por ejemplo, play-30 ).
Hay dos httpclients disponibles, pero HttpClient y la API relacionada se han desactivado. Utilice uk.gov.hmrc.http.client.HttpClientV2 en su lugar.
Este cliente tiene más características que el HttpClient original y es más simple de usar.
Requiere un HeaderCarrier para representar el contexto de la persona que llama, y un HttpReads para procesar la respuesta HTTP.
También:
play.api.libs.ws.WSRequest subyacente transformjava.net.URL ; Puede hacer uso del interpolador URL proporcionado.Se pueden encontrar ejemplos aquí y aquí
Este cliente ha estado en desuso. Puedes migrar de la siguiente manera:
httpClient. GET [ ResponseType ](url)se convierte en
httpClientV2.get( url " $url " ).execute[ ResponseType ]y
httpClient. POST [ ResponseType ](url, payload, headers)se convierte en
httpClientV2.post( url " $url " ).withBody( Json .toJson(payload)).setHeader(headers).execute[ ResponseType ]Si previamente estaba creando múltiples httpclients para configurar proxies o cambiar el agente de usuario, esto no será necesario, ya que todos se pueden controlar con la API HTTPClientv2 por llamada.
El HeaderCarrier debe tratarse en gran medida como una representación inmutable de la persona que llama. Si necesita manipular los encabezados que se envían en solicitudes, puede hacerlo con la API HttpClientV2 .
Por ejemplo, para anular el agente de usuario predeterminado o el encabezado de autorización definido en el avance de la cabeza, puede usar setHeader que reemplazará a los existentes.
httpClientV2.get( url " $url " )
.setHeader( " User-Agent " - > userAgent)
.setHeader( " Authorization " - > authorization)
.execute[ ResponseType ] Si desea agregar a los encabezados predeterminados, puede acceder addHttpHeaders en el WSClient subyacente con transform . p.ej
httpClientV2.get( url " $url " )
.transform(_.addHttpHeaders( " User-Agent " - > userAgent))
.execute[ ResponseType ] Tenga en cuenta que el "Content-Type" no se puede cambiar una vez establecido con WSRequest , por lo que si desea uno diferente al definido por el BodyWriter implícito, deberá configurarlo antes de proporcionar el cuerpo. p.ej
httpClientV2.post( url " $url " )
.setHeader( " Content-Type " - > " application/xml " )
.withBody(< foo >bar</ foo >) Con HttpClient , para usar un proxy requerido para crear una nueva instancia de httpclient para mezclar WSProxy y configurar. Con HttpClientV2 esto se puede hacer con el mismo cliente, llamando withProxy por llamada. p.ej
httpClientV2.get( url " $url " ).withProxy.execute[ ResponseType ]WSProxyConfiguration.buildWsProxyServer que está habilitado con http-verbs.proxy.enabled en configuración. Está deshabilitado de forma predeterminada, lo que es apropiado para el desarrollo y las pruebas locales, pero necesitará habilitar cuando se implementa (si ya no está habilitado por la configuración ambiental). La transmisión es compatible con HttpClientV2 , y se auditará de la misma manera que las llamadas no correctas. Tenga en cuenta que las cargas útiles se truncarán en los registros de auditoría si exceden el máximo compatible (según lo configurado por http-verbs.auditing.maxBodyLength ).
Las solicitudes transmitidas simplemente se pueden pasar a withBody :
val reqStream : Source [ ByteString , _] = ???
httpClientV2.post( url " $url " ).withBody(reqStream).execute[ ResponseType ] Para las respuestas transmitidas, use stream en lugar de execute :
httpClientV2.get( url " $url " ).stream[ Source [ ByteString , _]] HttpClientv2 trunca las cargas útiles para los registros de auditoría si exceden el máximo compatible (según lo configurado por http-verbs.auditing.maxBodyLength ).
Esto significa que las auditorías que fueron rechazadas por ser demasiado grandes con httpclient probablemente serán aceptadas con httpclientv2.
Se ha proporcionado un interpolador de URL para ayudar a escapar de la consulta y los parámetros de ruta correctamente.
import uk . gov . hmrc . http . StringContextOps
url " http://localhost:8080/users/ ${user.id} ?email= ${user.email} " El HeaderCarrier debe crearse con HeaderCarrierConverter cuando hay una solicitud disponible, esto asegurará que los encabezados apropiados se envíen a los hosts internos.
Por ejemplo, para backends:
HeaderCarrierConverter .fromRequest(request)Y para los frontends:
HeaderCarrierConverter .fromRequestAndSession(request, request.session) Si un punto final frontend está atendiendo una llamada API, probablemente debería usar fromRequest ya que fromRequestAndSession solo buscará un token de autorización en la sesión e ignora cualquier encabezado provisto como encabezado de solicitud.
Para llamadas asíncronas, donde no hay solicitud disponible, se puede crear un nuevo WorCarrier con parámetros predeterminados:
HeaderCarrier ()Los encabezados se envían de manera diferente a los hosts dependiendo de si son internos o externos . Esta distinción es realizada por la configuración de los puntos internas de servicio interno.
Para hosts externos, solo se envía el encabezado de agente de usuario. Cualquier otro encabezado debe proporcionarse explícitamente a la función verbal ( get , post etc.).
httpClientV2
.get( url " https://externalhost/api " )(hc)
.setHeader( " Authorization " - > " Bearer token " ) // explicit Authorization header for external request Además del agente de usuarios, todos los encabezados que se modelan explícitamente en el HeaderCarrier se envían a los hosts internos. También reenviará cualquier otro encabezado en el HeaderCarrier si se enumera en la configuración bootstrap.http.headersAllowlist .
Puede reemplazar cualquiera de estos encabezados reenviados implícitamente o agregar otros proporcionándolos a la función setHeader .
Nota, para el HttpClient original, los encabezados proporcionados a la función verbal se envían además de los que están en el portador de cabecera, por lo que si desea reemplazar uno, tendrá que manipular el HeaderCarrier , por ejemplo:
client. GET ( " https://internalhost/api " )(hc.copy(authorization = Some ( Authorization ( " Basic 1234 " ))))La respuesta está deserializada por una instancia de httpreads.
Puede crear sus propias instancias o usar las instancias proporcionadas con
import uk . gov . hmrc . http . HttpReads . Implicits . _Los implicados predeterminados (sin importación explícita) se han desactivado. Vea aquí para más detalles.
El HttpReads describe cómo convertir un HttpResponse en su modelo utilizando el código de estado y el cuerpo de respuesta.
Las instancias proporcionadas, incorporadas con la importación anterior, le permiten:
client. GET [ HttpResponse ](url) implicit val reads : Reads [ MyModel ] = ???
client.get[ MyModel ](url)UpstreamErrorResponse para códigos de estado no exitosos. Las fallas de análisis de JSON se devolverán de manera similar como JsValidationException estas excepciones pueden recuperarse si es necesario.None implict val reads : Reads [ MyModel ] = ???
client.get[ Option [ MyModel ]](url)UpstreamErrorResponse en Either implict val reads : Reads [ MyModel ] = ???
client.get[ Either [ UpstreamErrorResponse , MyModel ]](url)En su compilación SBT, agregue lo siguiente en sus dependencias de prueba:
libraryDependencies + = " uk.gov.hmrc " %% " http-verbs-test-play-xx " % " x.x.x " % TestRecomendamos que Wiremock se use para probar el código HTTP-Verbos, con afirmaciones extensas sobre la URL, los encabezados y los campos corporales para las solicitudes y las respuestas. Esto probará la mayoría de las cosas, no implica "burlarse de lo que no posee" y asegura que se atrapen cambios en esta biblioteca. Es decir, el resultado de usar esta biblioteca es lo que se pretendía, no solo si la biblioteca se invocaba como se esperaba.
El rasgo de WireMockSupport ayuda a configurar Wiremock para sus pruebas. Proporciona wireMockHost , wireMockPort y wireMockUrl que se pueden usar para configurar su cliente adecuadamente.
por ejemplo, con una aplicación:
class MyConnectorSpec extends WireMockSupport with GuiceOneAppPerSuite {
override def fakeApplication () : Application =
new GuiceApplicationBuilder ()
.configure(
" connector.host " - > wireMockHost,
" connector.port " - > wireMockPort
).build()
private val connector = app.injector.instanceOf[ MyConnector ]
} El rasgo HttpClientV2Support puede proporcionar una instancia de HttpClientV2 como alternativa para instanciar la aplicación:
class MyConnectorSpec extends WireMockSupport with HttpClientV2Support {
private val connector = new MyConnector (
httpClientV2,
Configuration ( " connector.url " - > wireMockUrl)
)
} El rasgo ExternalWireMockSupport es una alternativa a WireMockSupport que usa 127.0.0.1 en lugar de localhost para el nombre de host que se trata como un host externo para las reglas de reenvío de encabezado. Esto debe usarse para pruebas de conectores que llaman puntos finales externos a la plataforma. El Variable externalWireMockHost (o externalWireMockUrl ) debe usarse para proporcionar el nombre de host en la configuración.
Tanto WireMockSupport como ExternalWireMockSupport se pueden usar juntos para las pruebas de integración si es necesario.
El rasgo ResponseMatchers proporciona algunos ayudantes útiles para probar las respuestas.
Este código es software de código abierto con licencia bajo la licencia Apache 2.0.