HTTP-Verbs adalah perpustakaan Scala yang menyediakan antarmuka untuk melakukan panggilan HTTP asinkron.
Ini merangkum beberapa kekhawatiran umum untuk memanggil layanan HTTP lainnya pada platform pajak HMRC, termasuk:
Lihat Changelog untuk perubahan dan migrasi.
Di SBT Anda Bangun Tambah:
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 " Di mana play-xx adalah versi permainan Anda (misalnya play-30 ).
Ada dua httpClient yang tersedia, tetapi HttpClient dan API terkait telah ditinggalkan. Silakan gunakan uk.gov.hmrc.http.client.HttpClientV2 sebagai gantinya.
Klien ini memiliki lebih banyak fitur daripada HttpClient asli dan lebih sederhana untuk digunakan.
Dibutuhkan HeaderCarrier untuk mewakili konteks penelepon, dan HttpReads untuk memproses respons HTTP.
Itu juga:
play.api.libs.ws.WSRequest dengan transform , membuatnya lebih mudah untuk menyesuaikan permintaan.java.net.URL ; Anda dapat menggunakan interpolator URL yang disediakan.Contoh dapat ditemukan di sini dan di sini
Klien ini sudah usang. Anda dapat bermigrasi sebagai berikut:
httpClient. GET [ ResponseType ](url)menjadi
httpClientV2.get( url " $url " ).execute[ ResponseType ]Dan
httpClient. POST [ ResponseType ](url, payload, headers)menjadi
httpClientV2.post( url " $url " ).withBody( Json .toJson(payload)).setHeader(headers).execute[ ResponseType ]Jika Anda sebelumnya membuat beberapa httpClients untuk mengonfigurasi proxy atau mengubah agen pengguna, ini tidak akan diperlukan karena ini semua dapat dikontrol dengan HTTPClientV2 API per panggilan.
HeaderCarrier sebagian besar harus diperlakukan sebagai representasi yang tidak berubah dari penelepon. Jika Anda perlu memanipulasi header yang dikirim dalam permintaan, Anda dapat melakukan ini dengan HttpClientV2 API.
Misalnya untuk mengganti agen pengguna default atau header otorisasi yang ditentukan dalam HeaderCarrier, Anda dapat menggunakan setHeader yang akan menggantikan yang sudah ada.
httpClientV2.get( url " $url " )
.setHeader( " User-Agent " - > userAgent)
.setHeader( " Authorization " - > authorization)
.execute[ ResponseType ] Jika Anda ingin menambahkan header default, maka Anda dapat mengakses addHttpHeaders pada WSClient yang mendasarinya dengan transform . misalnya
httpClientV2.get( url " $url " )
.transform(_.addHttpHeaders( " User-Agent " - > userAgent))
.execute[ ResponseType ] Ketahuilah bahwa "Content-Type" tidak dapat diubah setelah diatur dengan WSRequest jadi jika Anda menginginkan yang berbeda dengan yang ditentukan oleh BodyWriter implisit, Anda perlu mengaturnya sebelum menyediakan tubuh. misalnya
httpClientV2.post( url " $url " )
.setHeader( " Content-Type " - > " application/xml " )
.withBody(< foo >bar</ foo >) Dengan HttpClient , untuk menggunakan proxy yang diperlukan membuat instance baru httpClient untuk mencampur dalam WSProxy dan mengkonfigurasi. Dengan HttpClientV2 ini dapat dilakukan dengan klien yang sama, menelepon withProxy per panggilan. misalnya
httpClientV2.get( url " $url " ).withProxy.execute[ ResponseType ]WSProxyConfiguration.buildWsProxyServer yang diaktifkan dengan http-verbs.proxy.enabled dalam konfigurasi. Ini dinonaktifkan secara default, yang sesuai untuk pengembangan dan pengujian lokal, tetapi perlu mengaktifkan saat digunakan (jika belum diaktifkan oleh konfigurasi lingkungan). Streaming didukung dengan HttpClientV2 , dan akan diaudit dengan cara yang sama seperti panggilan non-streamed. Perhatikan bahwa muatan akan dipotong dalam log audit jika melebihi maksimal yang didukung (seperti yang dikonfigurasi oleh http-verbs.auditing.maxBodyLength ).
Permintaan streaming dapat dengan mudah diteruskan ke withBody :
val reqStream : Source [ ByteString , _] = ???
httpClientV2.post( url " $url " ).withBody(reqStream).execute[ ResponseType ] Untuk respons yang stream, gunakan stream daripada execute :
httpClientV2.get( url " $url " ).stream[ Source [ ByteString , _]] HTTPCLIENTV2 memotong muatan untuk log audit jika melebihi maksimal yang didukung (seperti yang dikonfigurasi oleh http-verbs.auditing.maxBodyLength ).
Ini berarti audit yang ditolak karena terlalu besar dengan httpclient mungkin akan diterima dengan httpclientv2.
Interpolator URL telah disediakan untuk membantu melarikan diri dari kueri dan parameter jalur dengan benar.
import uk . gov . hmrc . http . StringContextOps
url " http://localhost:8080/users/ ${user.id} ?email= ${user.email} " HeaderCarrier harus dibuat dengan HeaderCarrierConverter ketika permintaan tersedia, ini akan memastikan bahwa header yang sesuai diteruskan ke host internal.
Misalnya untuk backends:
HeaderCarrierConverter .fromRequest(request)Dan untuk frontend:
HeaderCarrierConverter .fromRequestAndSession(request, request.session) Jika titik akhir frontend melayani panggilan API, itu mungkin harus menggunakan fromRequest karena fromRequestAndSession hanya akan mencari token otorisasi dalam sesi tersebut, dan mengabaikan apa pun yang disediakan sebagai header permintaan.
Untuk panggilan asinkron, di mana tidak ada permintaan yang tersedia, headercarrier baru dapat dibuat dengan params default:
HeaderCarrier ()Header diteruskan secara berbeda ke host tergantung pada apakah mereka internal atau eksternal . Perbedaan ini dibuat oleh konfigurasi internalServiceHostPatterns.
Untuk host eksternal, hanya header agen pengguna yang dikirim. Header lain harus disediakan secara eksplisit ke fungsi kata kerja ( get , post dll).
httpClientV2
.get( url " https://externalhost/api " )(hc)
.setHeader( " Authorization " - > " Bearer token " ) // explicit Authorization header for external request Selain agen pengguna, semua header yang dimodelkan secara eksplisit di HeaderCarrier diteruskan ke host internal. Ini juga akan meneruskan header lain di HeaderCarrier jika terdaftar di bootstrap.http.headersAllowlist Configuration.
Anda dapat mengganti salah satu header yang diteruskan secara implisit ini atau menambahkan yang lain dengan menyediakannya ke fungsi setHeader .
Catatan, untuk HttpClient asli, header yang disediakan untuk fungsi kata kerja dikirim selain yang ada di headercarrier, jadi jika Anda ingin menggantinya, Anda harus memanipulasi HeaderCarrier misalnya:
client. GET ( " https://internalhost/api " )(hc.copy(authorization = Some ( Authorization ( " Basic 1234 " ))))Responsnya diuraikan dengan contoh httpreads.
Anda dapat membuat instance Anda sendiri atau menggunakan instance yang disediakan dengan
import uk . gov . hmrc . http . HttpReads . Implicits . _Implikasi default (tanpa impor eksplisit) telah sudah usang. Lihat di sini untuk detail lebih lanjut.
HttpReads menjelaskan cara mengubah HttpResponse menjadi model Anda menggunakan kode status dan badan respons.
Contoh yang disediakan, dibawa ke dalam lingkup impor di atas, memungkinkan Anda untuk:
client. GET [ HttpResponse ](url) implicit val reads : Reads [ MyModel ] = ???
client.get[ MyModel ](url)UpstreamErrorResponse untuk kode status non-suscess. Kegagalan parsing JSON juga akan dikembalikan sebagai JsValidationException pengecualian ini dapat dipulihkan dari jika diperlukan.None implict val reads : Reads [ MyModel ] = ???
client.get[ Option [ MyModel ]](url)UpstreamErrorResponse di Either implict val reads : Reads [ MyModel ] = ???
client.get[ Either [ UpstreamErrorResponse , MyModel ]](url)Di SBT Anda, Tambahkan yang berikut dalam dependensi tes Anda:
libraryDependencies + = " uk.gov.hmrc " %% " http-verbs-test-play-xx " % " x.x.x " % TestKami merekomendasikan bahwa Wiremock digunakan untuk menguji kode HTTP-Verbs, dengan pernyataan luas pada URL, header, dan bidang tubuh untuk permintaan dan tanggapan. Ini akan menguji sebagian besar hal, tidak melibatkan "mengejek apa yang tidak Anda miliki", dan memastikan bahwa perubahan pada perpustakaan ini akan ditangkap. Yaitu bahwa hasil menggunakan perpustakaan ini adalah apa yang dimaksudkan, bukan hanya jika perpustakaan dipanggil seperti yang diharapkan.
Sifat WireMockSupport membantu mengatur Wiremock untuk tes Anda. Ini menyediakan wireMockHost , wireMockPort dan wireMockUrl yang dapat digunakan untuk mengonfigurasi klien Anda dengan tepat.
misalnya dengan aplikasi:
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 ]
} Sifat HttpClientV2Support dapat memberikan contoh HttpClientV2 sebagai alternatif untuk memancing aplikasi:
class MyConnectorSpec extends WireMockSupport with HttpClientV2Support {
private val connector = new MyConnector (
httpClientV2,
Configuration ( " connector.url " - > wireMockUrl)
)
} Sifat dukungan ExternalWireMockSupport adalah alternatif untuk WireMockSupport yang menggunakan 127.0.0.1 alih -alih localhost untuk nama host yang diperlakukan sebagai host eksternal untuk aturan penerusan header. Ini harus digunakan untuk tes konektor yang memanggil titik akhir eksternal ke platform. Variabel externalWireMockHost (atau externalWireMockUrl ) harus digunakan untuk memberikan nama host dalam konfigurasi.
Baik WireMockSupport dan ExternalWireMockSupport dapat digunakan bersama untuk tes integrasi jika diperlukan.
Sifat ResponseMatchers memberikan beberapa pembantu yang berguna untuk menguji respons.
Kode ini adalah perangkat lunak open source yang dilisensikan di bawah lisensi Apache 2.0.