[Ar] Problem Details: An error format for HTTP APIs
(0) الفهرس
مقدمة.
Problem Details.
Fields.
Implementation.
الملخص.
(1) مقدمة
كتير مننا احتاج إنه يدزاين فورمات للـresponse body في حالة الـerror.
ساعتها بيقابلنا أسئلة زي:
هل أحط الـhttp status code في الـresponse body ولا لأ؟
هل أخلي الـerror code يبقى string ولا number؟
لو عايز أبعت structured data مع الـerror message، أعمل كده إزاي؟ .. ولا الـfrontend المفروض يـparse الـerror message ويطلع منها الداتا؟
عشان الأسئلة دي وأسئلة تانية، فيه standard اسمه “Problem Details” بيحاول يجاوب على الأسئلة دي.
(2) Problem Details
ده standard لفورمات الـresponse body في حالة الـerror الـHTTP APIs.
دي الـJSON schema أو الـtype بتاعه:
وده مثال ليه:
(أ) الـstandard ده مابيجبركش إنك تخلي شكل الإيرور كده. بيقولك لو عندك فورمات تاني استخدمه عادي. هو بيقولك بس لو لسه ماعندكش شكل للإيرور، ممكن الشكل ده يعجبك.
بل كمان بيقولك إنك ممكن تاخد أفكار من الـstandard وانت بتدزاين شكل الإيرور. يعني مش لازم تمشي عليه كله.
(ب) الـstandard موجود في RFC 7807 وبعد كده تم تعديله في RFC 9457.
(3) Fields
(أ) status: هو مش موجود في المثال، بس بيقولك إنه يفضل تحط الـhttp status code في field اسمه status (بجانب ما هو already موجود في الـhttp response) لإنك وانت بتـdebug ممكن تبقى باصص على أو تبعت لحد الـresponse body من غير ماتبعت الـhttp response كلها.
وطبعاً لو استخدمته لازم يبقى بيـmatch الـhttp status code اللي في الـresponse.
(ب) type: ده عامل زي الـerror code. ده machine-readable unique string بيعبر عن إيه المشكلة بالظبط.
يعني حتى لو الـstatus 400 فممكن تبقى المشكلة إن الـage is less than 18، أو إن مثلاً الـemail is not valid. فده زي الـerror code كده بيقولك إيه المشكلة بالظبط.
الـstandard بيقولك خليه URI بس أنا بستسهل وبخليه enum وبـserializeـه. يعني مثلاً: “AgeIsLessThan18” أو “EmailIsNotValid”.
(ج) title: ده human-readable summary للمشكلة.
ده مش لازم يبقى موجه للـusers، ده للـdevelopers (وعامةً كل حاجة في الـerror format ده للـdevelopers). والمفروض يبقى ثابت لكل “type”، يعني ماتخليهوش مثلاً “Input age is 15 while the minimum is 18”.
(د) detail: ده زي الـtitle بس ممكن تحط فيه تفاصيل زيادة خاصة بالـinstance دي للمشكلة. يعني مثلاً ممكن يبقى “Input age is 15 while the minimum is 18” عشان تعرف الراجل هو دخل إيه أو انت حسبت الـage بكام (من الـbirthdate مثلاً).
الـtitle والـdetail هما زي فكرة الـ”message”، بس عشان لو كنت بتسأل نفسك هل أخلي الـmessage عامةً ولا فيها تفاصيل للـinstance دي من المشكلة، المفروض الـstandard كده جاوب على سؤالك.
(هـ) instance: أنا ماستعملتوش، بس ده ممكن لينك يوديك للـlogs بتاعة المشكلة أو الركوست ده مثلاً.
(و) extension members: لو عايز تبعت structured data، بيقولك ممكن تحط fields كمان براحتك بس اتأكد إنها مش بتـconflict مع الـstandard fields.
أنا شخصياً بحب أحط أي structured data تحت field اسمه “extensions” عشان أقلل احتمالية إني بالغلط أ-override الـtitle مثلاً، أو بسبب implementation detail معينة كده.
(4) Implementation
في C# مثلاً، أنا بـimplementـه كده:
طبعاً ده pseudocode، ممكن يبقى فيه أخطاء && ممكن مايكونش best practice.
(وفيه تفصيلة صغيرة كده عن هل أعمل exception class منفصل لكل problem type، بس مش هناقشها دلوقتي، وكده كده مش متأكد من الإجابة).
(5) الملخص
فالملخص يعني إنك لو بتدزاين شكل الإيرور للـHTTP API بتاعك، ابقى بص على الـstandard بتاع Problem Details ممكن تلاقي فيه أفكار كويسة.
وممكن الكود اللي في نقطة (4) يساعدك في الـimplementation.
شكراً لقرايتكم.



