يقرأ الوكيل الأمامي سطر الطلب والترويسات، ثم يمررها، ثم ينتظر في select جسم POST. العميل أرسله بالفعل. يبدو أن كلا الطرفين ينتظر الآخر.

مع BaseHTTPRequestHandler في Python، تمر قراءة الترويسات عبر rfile، وهو تدفق إدخال مُخزَّن مؤقتًا. يمكن لهذا التدفق أن يقرأ مسبقًا ويحتفظ ببايتات تنتمي إلى الجسم. الانتظار على المقبس الأساسي يسأل فقط هل واصف الملف جاهز؛ ولا يسأل هل يحتوي تدفق Python على بيانات صالحة بالفعل.

اتبع المخزن الذي قرأ الترويسات

اقرأ الجسم عبر self.rfile أيضًا. لا تنتقل إلى self.connection.recv بعد تحليل الترويسات بالتدفق المُخزَّن. وإلا فقد تتجاوز الشيفرة بايتات يحتفظ بها ذلك التدفق وتنتظر بيانات لن تُرسل مرة أخرى.

تمرير rfile نفسه إلى select لا يجعل select يفحص مخزنه في Python. تعمل واجهة الجاهزية عبر واصف ملف الكائن.

بالنسبة لطلب له Content-Length صالح واحد ولا Transfer-Encoding، استهلك بالضبط عدد البايتات المعلن، مع التعامل مع نهاية الإدخال المبكرة وحدود الحجم والوقت لديك. لا تقرأ حتى EOF: قد يُبقي العميل الذي يستخدم اتصالًا دائمًا الاتصال مفتوحًا بعد إنهاء الطلب.

اجعل التأطير جزءًا صريحًا من الوكيل

تحتاج أجسام الطلبات المُجزَّأة إلى دعم تأطير مُجزَّأ. لا يمكن قراءتها بالبحث عن Content-Length غائب. تحتاج بيانات الطول الغامضة إلى مسار رفض محدد، بدل اختيار الترويسة التي تبدو ملائمة.

يمكن للمعالج الحاجب أن يواصل استخدام واجهة تدفقه بقراءات محدودة. يحتاج الوكيل المدفوع بالأحداث إلى نموذج مخزن يدمج القراءة المسبقة للمحلل مع معالجة الجاهزية. تغيير المهلة لن يوفق بين مستهلكين مستقلين للمقبس نفسه.

هذا التشخيص خاص بمكان احتفاظ البايتات الواردة. بعد أن يستهلك الوكيل الجسم الصحيح، ما زال يحتاج إلى تمرير ذلك الجسم بتأطير HTTP متسق. معالج http.server القياسي مكان مفيد لفهم الآلية، لكنه ليس تنفيذًا إنتاجيًا لوكيل أمامي.

مقالات ذات صلة