HTTP-Verbs هي مكتبة Scala توفر واجهة لإجراء مكالمات HTTP غير متزامنة.
يلف بعض المخاوف المشتركة لاستدعاء خدمات HTTP الأخرى على منصة ضريبة HMRC ، بما في ذلك:
انظر changelog للحصول على التغييرات والهجرة.
في بناء SBT الخاص بك إضافة:
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 " حيث play-xx هو إصدار Play الخاص بك (على سبيل المثال play-30 ).
هناك نوعان من httpclients المتاحة ، ولكن تم إهمال HttpClient و API ذات الصلة. يرجى استخدام uk.gov.hmrc.http.client.HttpClientV2 بدلاً من ذلك.
يحتوي هذا العميل على ميزات أكثر من HttpClient الأصلي وأبسط الاستخدام.
يتطلب الأمر HeaderCarrier لتمثيل سياق المتصل ، و HttpReads لمعالجة استجابة HTTP.
أيضا:
play.api.libs.ws.WSRequest الأساسي ، مما يسهل transform الطلب.java.net.URL ؛ يمكنك الاستفادة من interpolator URL المقدم.يمكن العثور على أمثلة هنا وهنا
تم إهمال هذا العميل. يمكنك الترحيل على النحو التالي:
httpClient. GET [ ResponseType ](url)يصبح
httpClientV2.get( url " $url " ).execute[ ResponseType ]و
httpClient. POST [ ResponseType ](url, payload, headers)يصبح
httpClientV2.post( url " $url " ).withBody( Json .toJson(payload)).setHeader(headers).execute[ ResponseType ]إذا كنت تقوم سابقًا بإنشاء HTTPClients متعددة لتكوين الوكلاء أو تغيير وكيل المستخدم ، فلن يكون ذلك ضروريًا لأن هذا يمكن التحكم فيه مع API HTTPCLIENTV2 لكل مكالمة.
يجب أن يعامل HeaderCarrier إلى حد كبير على أنه تمثيل ثابت للمتصل. إذا كنت بحاجة إلى معالجة الرؤوس التي يتم إرسالها في الطلبات ، فيمكنك القيام بذلك باستخدام API HttpClientV2 .
على سبيل المثال ، لتجاوز عامل المستخدم الافتراضي أو رأس التفويض المحدد في HeaderCarrier ، يمكنك استخدام setHeader الذي سيحل محل أي منها.
httpClientV2.get( url " $url " )
.setHeader( " User-Agent " - > userAgent)
.setHeader( " Authorization " - > authorization)
.execute[ ResponseType ] إذا كنت ترغب في إلحاق الرؤوس الافتراضية ، فيمكنك الوصول إلى addHttpHeaders على WSClient الأساسي مع transform . على سبيل المثال
httpClientV2.get( url " $url " )
.transform(_.addHttpHeaders( " User-Agent " - > userAgent))
.execute[ ResponseType ] كن على دراية بأن "Content-Type" لا يمكن تغييره بمجرد تعيينه مع WSRequest ، لذا إذا كنت تريد واحدة مختلفة عن ذلك المحدد بواسطة BodyWriter الضمني ، فستحتاج إلى ضبطه قبل توفير الجسم. على سبيل المثال
httpClientV2.post( url " $url " )
.setHeader( " Content-Type " - > " application/xml " )
.withBody(< foo >bar</ foo >) مع HttpClient ، لاستخدام وكيل يتطلب إنشاء مثيل جديد من httpclient لخلط في WSProxy والتكوين. مع HttpClientV2 يمكن القيام بذلك مع نفس العميل ، والاتصال withProxy لكل مكالمة. على سبيل المثال
httpClientV2.get( url " $url " ).withProxy.execute[ ResponseType ]WSProxyConfiguration.buildWsProxyServer الذي تم تمكينه باستخدام http-verbs.proxy.enabled في التكوين. يتم تعطيله افتراضيًا ، وهو مناسب للتطوير والاختبارات المحلية ، ولكنه سيحتاج إلى تمكين عند نشره (إن لم يكن ممكّنًا بالفعل عن طريق التكوين البيئي). يتم دعم التدفق مع HttpClientV2 ، وسيتم مراجعته بنفس طريقة المكالمات غير المجردة. لاحظ أنه سيتم اقتطاع الحمولة في سجلات التدقيق إذا تجاوزت الحد الأقصى المدعوم (كما تم تكوينه بواسطة http-verbs.auditing.maxBodyLength ).
يمكن ببساطة تمرير طلبات البث المترتبة على withBody :
val reqStream : Source [ ByteString , _] = ???
httpClientV2.post( url " $url " ).withBody(reqStream).execute[ ResponseType ] للاستجابات التي تم بثها ، استخدم stream بدلاً من execute :
httpClientV2.get( url " $url " ).stream[ Source [ ByteString , _]] HTTPCLIENTV2 ياقت حمولة حمولة لسجلات التدقيق إذا تجاوزت الحد الأقصى المدعوم (كما تم تكوينه بواسطة http-verbs.auditing.maxBodyLength ).
هذا يعني أن عمليات التدقيق التي تم رفضها لكونها كبيرة جدًا مع HTTPClient من المحتمل أن يتم قبولها مع HTTPCLIENTV2.
تم توفير interpolator URL للمساعدة في الهروب من معلمات الاستعلام والمسار بشكل صحيح.
import uk . gov . hmrc . http . StringContextOps
url " http://localhost:8080/users/ ${user.id} ?email= ${user.email} " يجب إنشاء HeaderCarrier باستخدام HeaderCarrierConverter عند توفر الطلب ، وهذا سيضمن إعادة توجيه الرؤوس المناسبة إلى المضيفين الداخليين.
على سبيل المثال للخلفية:
HeaderCarrierConverter .fromRequest(request)وللأمام:
HeaderCarrierConverter .fromRequestAndSession(request, request.session) إذا كانت نقطة نهاية الواجهة الأمامية تخدم مكالمة API ، فيجب على الأرجح استخدام fromRequest لأن fromRequestAndSession ستبحث فقط عن رمز تفويض في الجلسة ، وتجاهل أي رأس طلب.
بالنسبة للمكالمات غير المتزامنة ، حيث لا يتوفر أي طلب ، يمكن إنشاء جولة جديدة مع المعلمات الافتراضية:
HeaderCarrier ()يتم إعادة توجيه الرؤوس بشكل مختلف إلى المضيفين اعتمادًا على ما إذا كانت داخلية أو خارجية . يتم إجراء هذا التمييز من خلال تكوين internalservicehostpatterns.
بالنسبة للمضيفين الخارجيين ، يتم إرسال رأس وكيل المستخدم فقط. يجب توفير أي رؤوس أخرى بشكل صريح لوظيفة الفعل ( get ، post الخ).
httpClientV2
.get( url " https://externalhost/api " )(hc)
.setHeader( " Authorization " - > " Bearer token " ) // explicit Authorization header for external request بالإضافة إلى وكيل المستخدم ، يتم إعادة توجيه جميع الرؤوس التي تم تصميمها بشكل صريح في HeaderCarrier إلى المضيفين الداخليين. كما ستعمل على إعادة توجيه أي رؤوس أخرى في HeaderCarrier إذا تم إدراجها في تكوين bootstrap.http.headersAllowlist .
يمكنك استبدال أي من هذه الرؤوس التي يتم إعادة توجيهها ضمنيًا أو إضافة أي آخرين من خلال تزويدها بوظيفة setHeader .
ملاحظة ، بالنسبة إلى HttpClient الأصلي ، يتم إرسال الرؤوس المقدمة إلى وظيفة الفعل بالإضافة إلى تلك الموجودة في HeaderCarrier ، لذلك إذا كنت ترغب في استبدال واحدة ، فسيتعين عليك معالجة HeaderCarrier على سبيل المثال:
client. GET ( " https://internalhost/api " )(hc.copy(authorization = Some ( Authorization ( " Basic 1234 " ))))يتم استجابة الاستجابة من قبل مثيل httpreads.
يمكنك إما إنشاء مثيلاتك الخاصة أو استخدام الحالات المقدمة مع
import uk . gov . hmrc . http . HttpReads . Implicits . _تم إهمال الضمني الافتراضي (بدون استيراد صريح). انظر هنا لمزيد من التفاصيل.
يصف HttpReads كيفية تحويل HttpResponse إلى النموذج الخاص بك باستخدام رمز الحالة وجسم الاستجابة.
الحالات المقدمة ، التي تم إحضارها إلى نطاق الاستيراد أعلاه ، تسمح لك بال:
client. GET [ HttpResponse ](url) implicit val reads : Reads [ MyModel ] = ???
client.get[ MyModel ](url)UpstreamErrorResponse لرموز الحالة غير الناجحة. وبالمثل ، سيتم إرجاع إخفاقات تحليل JSON حيث يمكن استرداد JsValidationException هذه الاستثناءات من إذا لزم الأمر.None implict val reads : Reads [ MyModel ] = ???
client.get[ Option [ MyModel ]](url)UpstreamErrorResponse في Either implict val reads : Reads [ MyModel ] = ???
client.get[ Either [ UpstreamErrorResponse , MyModel ]](url)في بناء SBT الخاص بك ، أضف ما يلي في تبعيات الاختبار:
libraryDependencies + = " uk.gov.hmrc " %% " http-verbs-test-play-xx " % " x.x.x " % Testنوصي باستخدام Wiremock لاختبار رمز HTTP-Verbs ، مع تأكيدات واسعة على عنوان URL والرؤوس وحقول الجسم لكل من الطلبات والاستجابات. سيختبر هذا معظم الأشياء ، ولا يتضمن "سخرًا مما لا تملكه" ، ويضمن أن يتم اكتشاف التغييرات في هذه المكتبة. أي أن نتيجة استخدام هذه المكتبة هي ما كان مقصودًا ، وليس فقط إذا تم استدعاء المكتبة كما هو متوقع.
تساعد سمة WireMockSupport في إعداد Wiremock لاختباراتك. إنه يوفر wireMockHost و wireMockPort و wireMockUrl والذي يمكن استخدامه لتكوين عميلك بشكل مناسب.
على سبيل المثال مع التطبيق:
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 ]
} يمكن أن توفر سمة HttpClientV2Support مثيلًا لـ HttpClientV2 كبديل لتأسيس التطبيق:
class MyConnectorSpec extends WireMockSupport with HttpClientV2Support {
private val connector = new MyConnector (
httpClientV2,
Configuration ( " connector.url " - > wireMockUrl)
)
} سمة ExternalWireMockSupport هي بديل لـ WireMockSupport الذي يستخدم 127.0.0.1 بدلاً من localhost الذي يتم التعامل معه كمضيف خارجي لقواعد إعادة توجيه الرأس. يجب استخدام هذا لاختبارات الموصلات التي تستدعي نقاط النهاية الخارجية إلى النظام الأساسي. يجب استخدام المتغير externalWireMockHost (أو externalWireMockUrl ) لتوفير اسم المضيف بالتكوين.
يمكن استخدام كل من WireMockSupport و ExternalWireMockSupport معًا لاختبارات التكامل إذا لزم الأمر.
توفر سمة ResponseMatchers بعض المساعدين المفيدين لاختبار الاستجابات.
هذا الرمز مفتوح المصدر للبرامج المرخصة بموجب ترخيص Apache 2.0.