HTTP-Verbs ist eine Scala-Bibliothek, die eine Schnittstelle zur Verfügung stellt, um asynchrone HTTP-Anrufe zu tätigen.
Es fasst einige gemeinsame Bedenken, andere HTTP -Dienste auf der HMRC -Steuerplattform aufzurufen, darunter:
Sehen Sie ChangeLog für Änderungen und Migrationen.
In Ihrem SBT -Build hinzufügen:
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 " Wo play-xx Ihre Version von Play ist (z. B. play-30 ).
Es sind zwei HTTPClients verfügbar, aber HttpClient und verwandte API wurden veraltet. Bitte verwenden Sie stattdessen uk.gov.hmrc.http.client.HttpClientV2 .
Dieser Client hat mehr Funktionen als das ursprüngliche HttpClient und ist einfacher zu verwenden.
Es erfordert einen HeaderCarrier , den Kontext des Anrufers darzustellen, und ein HttpReads , um die HTTP -Antwort zu verarbeiten.
Es auch:
play.api.libs.ws.WSRequest mit transform und erleichtert das Anpassen der Anfrage.java.net.URL ; Sie können den bereitgestellten URL -Interpolator verwenden.Beispiele finden Sie hier und hier
Dieser Kunde wurde veraltet. Sie können wie folgt migrieren:
httpClient. GET [ ResponseType ](url)wird
httpClientV2.get( url " $url " ).execute[ ResponseType ]Und
httpClient. POST [ ResponseType ](url, payload, headers)wird
httpClientV2.post( url " $url " ).withBody( Json .toJson(payload)).setHeader(headers).execute[ ResponseType ]Wenn Sie zuvor mehrere HTTPClients erstellt haben, um Proxys zu konfigurieren oder den Benutzeragenten zu ändern, ist dies nicht erforderlich, da diese alle mit der HTTPCLIENTV2-API pro Anruf gesteuert werden können.
Der HeaderCarrier sollte größtenteils als unveränderliche Darstellung des Anrufers behandelt werden. Wenn Sie die Header in Anfragen manipulieren müssen, können Sie dies mit der HttpClientV2 -API tun.
Zum Beispiel, um den Standardbenutzer-Agent oder den im Headercarrier definierten Autorisierungsheader zu überschreiben, können Sie setHeader verwenden, die vorhandene ersetzen.
httpClientV2.get( url " $url " )
.setHeader( " User-Agent " - > userAgent)
.setHeader( " Authorization " - > authorization)
.execute[ ResponseType ] Wenn Sie sich an Standard -Header anhängen möchten, können Sie mit transform auf addHttpHeaders auf dem zugrunde liegenden WSClient zugreifen. z.B
httpClientV2.get( url " $url " )
.transform(_.addHttpHeaders( " User-Agent " - > userAgent))
.execute[ ResponseType ] Beachten Sie, dass "Content-Type" nicht einmal mit WSRequest geändert werden kann. Wenn Sie also einen anderen als der durch den implizite BodyWriter definierte, müssen Sie ihn festlegen, bevor Sie den Körper zur Verfügung stellen. z.B
httpClientV2.post( url " $url " )
.setHeader( " Content-Type " - > " application/xml " )
.withBody(< foo >bar</ foo >) Um einen HttpClient zu verwenden, musste eine neue Instanz von httpclient zum Mischen von WSProxy und konfiguriert werden, um einen Proxy zu verwenden. Mit HttpClientV2 kann dies mit demselben Client erfolgen, withProxy pro Anruf ruft. z.B
httpClientV2.get( url " $url " ).withProxy.execute[ ResponseType ]WSProxyConfiguration.buildWsProxyServer , der mit http-verbs.proxy.enabled in der Konfiguration aktiviert ist. Es ist standardmäßig deaktiviert, was für die lokale Entwicklung und Tests geeignet ist, muss jedoch bei der Bereitstellung aktiviert werden (falls dies nicht bereits durch Umgebungskonfiguration aktiviert ist). Das Streaming wird mit HttpClientV2 unterstützt und auf die gleiche Weise wie nicht überströmen Anrufe geprüft. Beachten Sie, dass die Nutzlasten in Prüfprotokollen abgeschnitten werden, wenn sie den unterstützten MAX überschreiten (wie von http-verbs.auditing.maxBodyLength konfiguriert).
Streamierte Anfragen können einfach withBody übergeben werden:
val reqStream : Source [ ByteString , _] = ???
httpClientV2.post( url " $url " ).withBody(reqStream).execute[ ResponseType ] Verwenden Sie für Streamed -Antworten stream anstatt execute :
httpClientV2.get( url " $url " ).stream[ Source [ ByteString , _]] HTTPCLIENTV2 schneidet die Nutzlasten für Prüfprotokolle ab, wenn sie den unterstützten Maximal überschreiten (wie von http-verbs.auditing.maxBodyLength konfiguriert).
Dies bedeutet, dass Audits, die als zu groß mit HTTPClient abgelehnt wurden, wahrscheinlich mit httpclientv2 akzeptiert werden.
Es wurde ein URL -Interpolator bereitgestellt, um die entscheidenden Abfrage- und Pfadparameter korrekt zu entkommen.
import uk . gov . hmrc . http . StringContextOps
url " http://localhost:8080/users/ ${user.id} ?email= ${user.email} " Der HeaderCarrier sollte mit HeaderCarrierConverter erstellt werden, wenn eine Anfrage verfügbar ist. Dadurch wird sichergestellt, dass die entsprechenden Header an interne Hosts weitergeleitet werden.
ZB für Backends:
HeaderCarrierConverter .fromRequest(request)und für Frontenden:
HeaderCarrierConverter .fromRequestAndSession(request, request.session) Wenn ein Frontend -Endpunkt einen API -Aufruf bedient, sollte er wahrscheinlich fromRequest verwendet werden, da aus fromRequestAndSession nur nach einem Autorisierungs -Token in der Sitzung suchen und alle als Anfrage -Header bereitgestellten Anforderungen ignoriert werden.
Für asynchrone Anrufe, bei denen keine Anfrage verfügbar ist, kann ein neuer Header -Barrier mit Standardparamien erstellt werden:
HeaderCarrier ()Header werden unterschiedlich an Wirte weitergeleitet, je nachdem, ob sie intern oder extern sind. Diese Unterscheidung wird von der Konfiguration von InternalServiceHostPatterns getroffen.
Für externe Hosts wird nur der Benutzer-Agent-Header gesendet. Alle anderen Header sollten ausdrücklich mit der Verb -Funktion ( get , post usw.) zur Verfügung gestellt werden.
httpClientV2
.get( url " https://externalhost/api " )(hc)
.setHeader( " Authorization " - > " Bearer token " ) // explicit Authorization header for external request Zusätzlich zum Benutzeragenten werden alle Header, die explizit im HeaderCarrier modelliert werden, an interne Hosts weitergeleitet. Es wird auch alle anderen Header im HeaderCarrier weiterleiten, wenn sie in der Konfiguration bootstrap.http.headersAllowlist aufgeführt sind.
Sie können jede dieser implizit weitergeleiteten Header ersetzen oder andere hinzufügen, indem Sie sie der setHeader -Funktion zur Verfügung stellen.
Beachten Sie, dass für das ursprüngliche HttpClient die Header für die Verb -Funktion zusätzlich zu denen im Headerbarrier gesendet werden. Wenn Sie also einen ersetzen möchten, müssen Sie den HeaderCarrier -EG manipulieren:
client. GET ( " https://internalhost/api " )(hc.copy(authorization = Some ( Authorization ( " Basic 1234 " ))))Die Antwort wird durch eine Instanz von Httpreads deserialisiert.
Sie können entweder Ihre eigenen Instanzen erstellen oder die bereitgestellten Instanzen mit verwenden
import uk . gov . hmrc . http . HttpReads . Implicits . _Die Standard -Implikationen (ohne explizite Import) wurden veraltet. Weitere Informationen finden Sie hier.
Die HttpReads beschreibt, wie ein HttpResponse mit dem Statuscode und dem Antwortkörper in Ihr Modell konvertiert wird.
Die bereitgestellten Fälle, die mit dem obigen Import in den Geltungsbereich gebracht wurden, ermöglichen es Ihnen:
client. GET [ HttpResponse ](url) implicit val reads : Reads [ MyModel ] = ???
client.get[ MyModel ](url)UpstreamErrorResponse für Nicht-SUCCESS-Statuscodes zurückgibt. JSON -Parsing -Misserfolge werden in ähnlicher Weise als JsValidationException zurückgegeben. Diese Ausnahmen können bei Bedarf wiederhergestellt werden.None handeln implict val reads : Reads [ MyModel ] = ???
client.get[ Option [ MyModel ]](url)UpstreamErrorResponse in Either implict val reads : Reads [ MyModel ] = ???
client.get[ Either [ UpstreamErrorResponse , MyModel ]](url)In Ihrem SBT Build Fügen Sie in Ihren Testabhängigkeiten Folgendes hinzu:
libraryDependencies + = " uk.gov.hmrc " %% " http-verbs-test-play-xx " % " x.x.x " % TestWir empfehlen, dass Wiremock zum Testen von HTTP-Verbs-Code verwendet wird, mit umfangreichen Behauptungen auf URL, Header und Körperfeldern für Anfragen und Antworten. Dies wird die meisten Dinge testen, nicht "verspotten, was Sie nicht besitzen", und stellt sicher, dass Änderungen an dieser Bibliothek gefangen werden. Dh das Ergebnis der Verwendung dieser Bibliothek war das, was beabsichtigt war, nicht nur, wenn die Bibliothek wie erwartet aufgerufen wurde.
Das WireMockSupport -Merkmal hilft Wiremock für Ihre Tests. Es bietet wireMockHost , wireMockPort und wireMockUrl , mit denen Ihr Client angemessen konfiguriert werden kann.
zB mit einer Anwendung:
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 ]
} Das HttpClientV2Support -Merkmal kann eine Instanz von HttpClientV2 als Alternative zur Instanzierung der Anwendung liefern:
class MyConnectorSpec extends WireMockSupport with HttpClientV2Support {
private val connector = new MyConnector (
httpClientV2,
Configuration ( " connector.url " - > wireMockUrl)
)
} Das ExternalWireMockSupport -Merkmal ist eine Alternative zu WireMockSupport , die 127.0.0.1 anstelle von localhost für den Hostnamen verwendet, der als externer Wirt für Header -Weiterleitungsregeln behandelt wird. Dies sollte für Tests von Anschlüssen verwendet werden, die Endpunkte extern auf der Plattform aufrufen. Die variable externalWireMockHost (oder externalWireMockUrl ) sollte verwendet werden, um den Hostnamen in der Konfiguration bereitzustellen.
Sowohl WireMockSupport als auch ExternalWireMockSupport können bei Bedarf zusammen für Integrationstests verwendet werden.
Das ResponseMatchers -Merkmal bietet einige nützliche Helfer zum Testen von Antworten.
Dieser Code ist Open -Source -Software, die unter der Apache 2.0 -Lizenz lizenziert ist.