O HTTP-verbs é uma biblioteca Scala que fornece uma interface para fazer chamadas HTTP assíncronas.
Ele encapsula algumas preocupações comuns em chamar outros serviços HTTP na plataforma tributária do HMRC, incluindo:
Veja Changelog para alterações e migrações.
Em seu SBT Build 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 " Onde play-xx é a sua versão do play (por exemplo, play-30 ).
Existem dois httpclients disponíveis, mas a API HttpClient e relacionada foram obsoletos. Por favor, use uk.gov.hmrc.http.client.HttpClientV2 .
Esse cliente possui mais recursos que o HttpClient original e é mais simples de usar.
Exige que um HeaderCarrier represente o contexto do chamador e um HttpReads para processar a resposta HTTP.
Também:
play.api.libs.ws.WSRequest subjacente.api.libs.ws.wsRequest com o transform , facilitando a personalização da solicitação.java.net.URL ; Você pode usar o interpolador de URL fornecido.Exemplos podem ser encontrados aqui e aqui
Este cliente foi obsoleto. Você pode migrar o seguinte:
httpClient. GET [ ResponseType ](url)torna -se
httpClientV2.get( url " $url " ).execute[ ResponseType ]e
httpClient. POST [ ResponseType ](url, payload, headers)torna -se
httpClientV2.post( url " $url " ).withBody( Json .toJson(payload)).setHeader(headers).execute[ ResponseType ]Se você estivesse criando anteriormente vários httpclients para configurar proxies ou alterar o agente do usuário, isso não será necessário, pois todos eles podem ser controlados com a API HTTPClientV2 por chamada.
O HeaderCarrier deve ser amplamente tratado como uma representação imutável do chamador. Se você precisar manipular os cabeçalhos que estão sendo enviados em solicitações, poderá fazer isso com a API HttpClientV2 .
Por exemplo, para substituir o agente do usuário padrão ou o cabeçalho de autorização definido no Headercarrier, você pode usar setHeader que substituirá os existentes.
httpClientV2.get( url " $url " )
.setHeader( " User-Agent " - > userAgent)
.setHeader( " Authorization " - > authorization)
.execute[ ResponseType ] Se você deseja anexar aos cabeçalhos padrão, poderá acessar addHttpHeaders no WSClient subjacente com transform . por exemplo
httpClientV2.get( url " $url " )
.transform(_.addHttpHeaders( " User-Agent " - > userAgent))
.execute[ ResponseType ] Esteja ciente de que o "Content-Type" não pode ser alterado uma vez definido com WSRequest ; portanto, se você deseja um diferente para o definido pelo BodyWriter implícito, precisará defini-lo antes de fornecer o corpo. por exemplo
httpClientV2.post( url " $url " )
.setHeader( " Content-Type " - > " application/xml " )
.withBody(< foo >bar</ foo >) Com HttpClient , para usar um proxy necessário, criando uma nova instância de httpclient para misturar no WSProxy e configurar. Com HttpClientV2 isso pode ser feito com o mesmo cliente, ligando withProxy por chamada. por exemplo
httpClientV2.get( url " $url " ).withProxy.execute[ ResponseType ]WSProxyConfiguration.buildWsProxyServer , que é ativado com http-verbs.proxy.enabled na configuração. É desativado por padrão, o que é apropriado para o desenvolvimento e os testes locais, mas precisará ativar quando implantado (se ainda não estiver ativado pela configuração ambiental). O streaming é suportado com HttpClientV2 e será auditado da mesma maneira que as chamadas não transmitidas. Observe que as cargas úteis serão truncadas nos logs de auditoria se excederem o máximo suportado (conforme configurado por http-verbs.auditing.maxBodyLength ).
Solicitações transmitidas podem simplesmente ser transmitidas para withBody :
val reqStream : Source [ ByteString , _] = ???
httpClientV2.post( url " $url " ).withBody(reqStream).execute[ ResponseType ] Para respostas transmitidas, use stream em vez de execute :
httpClientV2.get( url " $url " ).stream[ Source [ ByteString , _]] O HTTPClientV2 trunca cargas úteis para logs de auditoria se eles excederem o máximo suportado (conforme configurado por http-verbs.auditing.maxBodyLength ).
Isso significa que as auditorias que foram rejeitadas por serem muito grandes com o HTTPClient provavelmente serão aceitas com o httpclientv2.
Um interpolador de URL foi fornecido para ajudar a escapar dos parâmetros de consulta e caminho corretamente.
import uk . gov . hmrc . http . StringContextOps
url " http://localhost:8080/users/ ${user.id} ?email= ${user.email} " O HeaderCarrier deve ser criado com HeaderCarrierConverter Quando uma solicitação estiver disponível, isso garantirá que os cabeçalhos apropriados sejam encaminhados para hosts internos.
Por exemplo, para back -end:
HeaderCarrierConverter .fromRequest(request)E para os frontends:
HeaderCarrierConverter .fromRequestAndSession(request, request.session) Se um terminal de front -end estiver atendendo a uma chamada de API, provavelmente deve usar fromRequest , pois fromRequestAndSession procurará apenas um token de autorização na sessão e ignorará qualquer um cabeçalho de solicitação.
Para chamadas assíncronas, onde nenhuma solicitação está disponível, um novo Headercherrier pode ser criado com parâmetros padrão:
HeaderCarrier ()Os cabeçalhos são encaminhados de maneira diferente para os hosts, dependendo se são internos ou externos . Essa distinção é feita pela configuração internal serviceHostPatterns.
Para hosts externos, apenas o cabeçalho do agente do usuário é enviado. Quaisquer outros cabeçalhos devem ser fornecidos explicitamente à função verbal ( get , post etc.).
httpClientV2
.get( url " https://externalhost/api " )(hc)
.setHeader( " Authorization " - > " Bearer token " ) // explicit Authorization header for external request Além do agente do usuário, todos os cabeçalhos modelados explicitamente no HeaderCarrier são encaminhados para hosts internos. Ele também encaminhará outros cabeçalhos no HeaderCarrier se listado na configuração bootstrap.http.headersAllowlist .
Você pode substituir qualquer um desses cabeçalhos implicitamente encaminhados ou adicionar outros, fornecendo -os à função setHeader .
Observe que, para o HttpClient original, os cabeçalhos fornecidos à função verbal são enviados além dos do Headercarrier; portanto, se você quiser substituir um, terá que manipular o HeaderCarrier por exemplo:
client. GET ( " https://internalhost/api " )(hc.copy(authorization = Some ( Authorization ( " Basic 1234 " ))))A resposta é desapealizada por uma instância de htttreads.
Você pode criar suas próprias instâncias ou usar as instâncias fornecidas com
import uk . gov . hmrc . http . HttpReads . Implicits . _Os implícitos padrão (sem importação explícita) foram depreciados. Veja aqui para mais detalhes.
O HttpReads descreve como converter uma HttpResponse em seu modelo usando o código de status e o corpo de resposta.
As instâncias fornecidas, trazidas ao escopo com a importação acima, permitem:
client. GET [ HttpResponse ](url) implicit val reads : Reads [ MyModel ] = ???
client.get[ MyModel ](url)UpstreamErrorResponse para os códigos de status que não são de sucesso. As falhas de análise JSON serão retornadas da mesma forma, pois JsValidationException essas exceções podem ser recuperadas, se necessário.None implict val reads : Reads [ MyModel ] = ???
client.get[ Option [ MyModel ]](url)UpstreamErrorResponse em Either implict val reads : Reads [ MyModel ] = ???
client.get[ Either [ UpstreamErrorResponse , MyModel ]](url)Na sua construção SBT, adicione o seguinte em suas dependências de teste:
libraryDependencies + = " uk.gov.hmrc " %% " http-verbs-test-play-xx " % " x.x.x " % TestRecomendamos que o Wiremock seja usado para testar o código HTTP-Verbs, com extensas afirmações sobre os campos de URL, cabeçalhos e corpos para solicitações e respostas. Isso testará a maioria das coisas, não envolve "zombando do que você não possui" e garante que as mudanças nessa biblioteca sejam capturadas. Ou seja, o resultado do uso desta biblioteca é o que se destinava, não apenas se a biblioteca foi invocada conforme o esperado.
O traço WireMockSupport ajuda a configurar o Wiremock para seus testes. Ele fornece wireMockHost , wireMockPort e wireMockUrl que podem ser usados para configurar seu cliente adequadamente.
por exemplo, com um aplicativo:
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 ]
} O traço HttpClientV2Support pode fornecer uma instância de HttpClientV2 como uma alternativa para instanciando o aplicativo:
class MyConnectorSpec extends WireMockSupport with HttpClientV2Support {
private val connector = new MyConnector (
httpClientV2,
Configuration ( " connector.url " - > wireMockUrl)
)
} O traço ExternalWireMockSupport é uma alternativa ao WireMockSupport , que usa 127.0.0.1 em vez de localhost para o nome do host, que é tratado como um host externo para regras de encaminhamento de cabeçalho. Isso deve ser usado para testes de conectores que chamam pontos de extremidade externos à plataforma. A variável externalWireMockHost (ou externalWireMockUrl ) deve ser usada para fornecer o nome do host na configuração.
WireMockSupport e ExternalWireMockSupport podem ser usados juntos para testes de integração, se necessário.
A característica ResponseMatchers fornece alguns ajudantes úteis para testar respostas.
Este código é um software de código aberto licenciado sob a licença Apache 2.0.