مختبر تحقق طلب HTTP
HTTP Request Validation Lab
مختبر تحقق طلب HTTP — HTTP Request Validation Lab
قبل أن تحفظ أي طلب، تحقّق من مدخلاته. في هذا المختبر سنبني منطق handler يقبل JSON لمنتج، ويرفض الطلب إذا كان الاسم فارغاً أو السعر غير صحيح.
في تطبيقات HTTP، الثقة بالطلب كما وصل خطأ مكلف. المستخدم قد يرسل JSON ناقصاً، الواجهة قد تحتوي خللاً، أو عميل خارجي قد يرسل سعراً صفرياً. وظيفة الـ handler ليست فقط أن يقرأ الطلب؛ يجب أن يحمي حدود النظام قبل أن تصل البيانات إلى التخزين أو منطق العمل.
سنحاكي handler داخل playground بدالة تستقبل نص JSON، لأن Go Playground لا يشغل خادماً حقيقياً هنا. لكن نفس التفكير ينتقل مباشرة إلى net/http: تفك JSON من r.Body، تتحقق من struct، ثم تكتب status مناسباً ورسالة واضحة. الدرس الحقيقي هو فصل المسؤوليات لا شكل الخادم.
الفكرة
الـ handler الجيد يفصل بين ثلاث مسؤوليات:
- قراءة JSON.
- التحقق من البيانات.
- كتابة استجابة واضحة.
هذا الفصل يمنع دالة واحدة من التحول إلى كتلة طويلة يصعب اختبارها. دالة validateProduct لا تحتاج معرفة HTTP status، ودالة القراءة لا تحتاج معرفة قواعد السعر، ودالة الاستجابة لا تحتاج إعادة حساب الشروط. كل جزء صغير يمكن مراجعته واختباره وحده.
نموذج عملي
لاحظ أننا نتحقق من خطأ json.Unmarshal أولاً. إذا كان JSON نفسه غير صالح، فلا معنى لفحص الاسم أو السعر. بعد نجاح التحويل، تصبح لدينا قيمة ProductRequest عادية يمكن تمريرها إلى دالة تحقق. هذا النمط يجعل الأخطاء مرتبة من الخارج إلى الداخل: صيغة الطلب، ثم معنى البيانات، ثم تنفيذ العملية.
استخدمنا strings.TrimSpace حتى لا يكون الاسم المكون من مسافات مقبولاً. واستخدمنا Price <= 0 لأن السعر الصفري أو السالب لا يمثل منتجاً قابلاً للبيع في هذا المثال. في نظام حقيقي قد تضيف قيوداً أخرى مثل الحد الأعلى للسعر أو العملة، لكن لا تضفها قبل أن تصبح جزءاً من المتطلبات.
تحدي المختبر
أكمل التحقق حتى يرفض الطلب الثاني ويقبل الأول.
امتداد اختياري
بعد نجاح الحل، تخيّل أن handle هي داخل http.HandlerFunc: نفس منطق التحقق يبقى كما هو، والفرق فقط أن الاستجابة ستكتب عبر http.ResponseWriter.
أخطاء شائعة في handlers
أول خطأ هو تجاهل خطأ JSON والمتابعة بقيم صفرية. إذا فشل التحويل، قد يصبح الاسم فارغاً والسعر صفراً، ثم تظهر رسالة تحقق مضللة بدلاً من “JSON غير صالح”. ثاني خطأ هو خلط رسائل المستخدم مع تفاصيل داخلية حساسة. في هذا المثال الرسائل بسيطة وآمنة، لكن في الإنتاج لا تعرض أسماء جداول أو stack traces. ثالث خطأ هو جعل handler يحفظ البيانات قبل اكتمال التحقق، ثم محاولة التراجع بعد ذلك.
قبل اعتبار الحل صحيحاً، جرّب التفكير في ثلاث طلبات: طلب صالح يجب أن يقبل، طلب بسعر صفر يجب أن يرفض، وطلب JSON مكسور يجب أن يرفض قبل التحقق. هذا الترتيب يعكس بوابة HTTP الجيدة: لا يدخل شيء إلى النظام حتى يثبت أنه مفهوم وصالح.
خلاصة
التحقق من طلب HTTP هو خط الدفاع الأول في الخدمة. عندما تفصل القراءة عن التحقق عن الاستجابة، يصبح الكود أسهل في الاختبار وأقل عرضة للأخطاء. دالة صغيرة مثل validateProduct قد تبدو بسيطة، لكنها تمنع بيانات سيئة من الوصول إلى قاعدة البيانات وتشرح سبب الرفض بوضوح. هذا هو الفرق بين handler يعمل في المثال وhandler يمكن الاعتماد عليه في تطبيق حقيقي.