الأصل في بروتوكول HTTP أنه ناقل عديم الحالة (Stateless)؛ بمعنى أن كل طلب فيه مستقلٌّ عما قبله. فلا يجوز أن يعتمد الطلب الثاني على نفوذ الطلب الأول. بل يجب أن يتضمَّن كل طلبٍ جميع المعلومات اللازمة، إضافة إلى تحديد ما يريد.
مثلاً: معلومات تسجيل الدخول: اسم المستخدم وكلمة المرور. يجب أن تكون في الطلب الأول، وكذلك يجب أن تكون في الطلب الثاني. لذلك تمَّ إيجاد مفهوم الجلسة (Session) بحيث تجمع طلبات العميل في سياق واحد.
وكذلك أمور أخرى تتعلق بحالة التطبيق نفسه بالنسبة لكل عميل، حتى قبل عملية تسجيل الدخول:
إعدادات العرض: حجم الخط، الوضع الداكن، ترتيب القوائم، اللغة، العملة، …إلخ.
عربة التسوق: قائمة المنتجات التي أضفتها قبل الشراء (حتى وإن لم يكن المستخدم قد أنشأ حسابًا بعد)
ومن منافع تصميم البروتوكول بهذه الآلية أمران:
الأول: ذاكرة أوسع: لا حاجة للخادم أن يحتفظ بمعلومات كل العملاء في وقت واحد؛ بل إن كل عميلٍ معه ما يلزم لخدمته. فهذا يوسِّع على الخادم ذاكرته لخدمة عدد لا محدود من العملاء.
الثاني: توزيع الجهد: يمكن لأكثر من خادم أن يخدم نفس العميل بين طلب وآخر؛ وبالتالي فإنه ثمة خادم وسيط عكسي (Reverse Proxy) يلعب دوْر موزِّع الجهد (Load Balancer) يعيِّن الخادم المناسب بحسب فراغهم وشغلهم (وغالبًا ما يكون التوزيع العشوائي كافيًا).
وتم الاصطلاح على: ملفات تعريف الارتباط (Cookies) وهي كلمة أصلها (Magic Cookies) وهي تشير لدوْرة يحصُلُ فيها الاستفادة من الشيء، بتمريره من الطرف الأول للثاني ثم رده كما هو من غير تعديل عليه؛ وذلك كالوثائق الحكوميَّة؛ حيث لا يجوز للمواطنين العبث فيها، وإنما يحتفظون فيها ويبرزونها عند حاجة موظفي الدولة إليها؛ ثم هم يعدلون عليها ويسلموها إلى المواطن مرة أخرى ليحتفظ فيها، وهكذا دواليك.
وهذا يعني أن الخادم يأمر المتصفِّح بحفظ معلومات معيَّنة يتم إرسالُها في كل طلب. ولا يجوز للعميل التعديل عليها. ويُمكن إلزامه بذلك عن طريق توقيع (Signature) مخصوص لضمان السلامة (Integrity). وهذا ما سنعرفه في درس الحماية -إن شاء الله-.
القطعة الأولى: فتعمل عند الزيارة. فهي تأخذ البيانات المخزَّنة في الـCookies فإن لم تجد شيئًا فإنها تفترض القيمة المقابلة: request.cookes.get(value, default). بعد ذلك تملأ القالب بالبيانات وتجيب به:
أما القطعة الثانية: فتعمل عند إرسال الاستمارة بمدخلاتها التي فيها عند الضغط على زر Save كما في القالب. والمعالجة تقضي بقراءة الاستمارة في form = await request.form().
فأما await وكذلك async def المذكورة قبل ذلك في التعريف، فسيأتي الكلام عنها في حينه إن شاء الله. لكن هي أمور زائدة لا تؤثر في النتيجة.
بعد ذلك يتم قراءة البيانات: form.get، ثم ننشئ الجواب الذي هو تحويل المستخدم لصفحة العرض (demo)، ونعدل فيه الـCookies، ثم نرجع به في نهاية الدالة: return response:
elif request.method =="POST": form =await request.form() dark_mode = form.get("dark_mode", "off") language_code = form.get("language", "en")# Prepare the response as a redirect to the demo page response = RedirectResponse(url="/settings/demo", status_code=303) response.set_cookie(key="dark_mode", value=dark_mode) response.set_cookie(key="language", value=language_code)return response