microdot --- إطار عمل HTTP بسيط¶
Microdot هو إطار عمل HTTP صغير مستوحى من Flask لأجل MicroPython. يعمل فوق asyncio، ويتعامل مع عملاء متزامنين متعددين دون استخدام خيوط، ويوفر واجهة مألوفة قائمة على مزينات المسارات. يبدو التطبيق البسيط هكذا:
from microdot import Microdot
app = Microdot()
@app.route('/')
async def index(request):
return 'Hello, world!'
app.run(host='0.0.0.0', port=80)
class Microdot¶
- class microdot.Microdot¶
مثيل تطبيق HTTP. يُنشأ مثيل واحد قرب أعلى البرنامج النصي ويُزيَّن بمعالجات المسارات؛ ويبدأ التقديم باستدعاء
run()أو انتظارstart_server().تسجيل المسارات
- route(url_pattern: str, methods: list | None = None) Callable¶
مزيِّن يسجل معالجًا لأجل url_pattern ضمن طرق HTTP المذكورة (الافتراضي
['GET']). يُرجع المزيِّن الذي يسجل الدالة كمعالج عند تطبيقه عليها ويُرجع الدالة دون تغيير.- url_pattern
نمط مسار. يدعم المقاطع الثابتة (
/users) والمقاطع الديناميكية المحاطة بـ</>. تقبل المقاطع الديناميكية بادئة نوع اختيارية مفصولة بـ:--<int:id>و<path:rest>و<re:[0-9a-f]+:hex>. والنوع الافتراضي هوstring.- methods
قائمة بأسماء طرق HTTP. إذا حُذفت، فلن يُطابق سوى
GET.
يُستدعى المعالج بكائن الطلب أولًا، ثم بأي مقاطع ديناميكية ملتقطة كوسائط بأسماء مفاتيح. تصبح القيمة المُرجعة من المعالج استجابة HTTP: إما
Response، أو سلسلة نصية، أو صف(body, status_code[, headers])، أو قاموس / قائمة (تُرسل بصيغة JSON).
- get(url_pattern: str) Callable¶
اسم بديل مريح لـ
route(url_pattern, methods=['GET'])-- يسجل الدالة المزيَّنة كمعالجGETلأجل url_pattern. يُرجع المزيِّن.
- post(url_pattern: str) Callable¶
اسم بديل مريح لـ
route(url_pattern, methods=['POST'])-- يسجل الدالة المزيَّنة كمعالجPOSTلأجل url_pattern. يُرجع المزيِّن.
- put(url_pattern: str) Callable¶
اسم بديل مريح لـ
route(url_pattern, methods=['PUT'])-- يسجل الدالة المزيَّنة كمعالجPUTلأجل url_pattern. يُرجع المزيِّن.
- patch(url_pattern: str) Callable¶
اسم بديل مريح لـ
route(url_pattern, methods=['PATCH'])-- يسجل الدالة المزيَّنة كمعالجPATCHلأجل url_pattern. يُرجع المزيِّن.
- delete(url_pattern: str) Callable¶
اسم بديل مريح لـ
route(url_pattern, methods=['DELETE'])-- يسجل الدالة المزيَّنة كمعالجDELETEلأجل url_pattern. يُرجع المزيِّن.
خطافات دورة الحياة
- before_request(f: Callable) Callable¶
مزيِّن يسجل f لتُنفَّذ قبل كل طلب. تأخذ f كائن الطلب؛ وتُتجاهَل قيمتها المُرجعة عادةً. ولاختصار مسار الطلب، أرجع
Response(أو قيمة تتحول إليها) -- عندئذ يُتخطى باقي خط المعالجة وتُرسل تلك الاستجابة. تُرجع f دون تغيير.
- after_request(f: Callable) Callable¶
مزيِّن يسجل f لتُنفَّذ بعد كل طلب ناجح. تأخذ f الوسيطين
(request, response)ويجب أن تُرجع كائن الاستجابة (ربما بعد تعديله). تُرجع f دون تغيير.
- after_error_request(f: Callable) Callable¶
مزيِّن يسجل f لتُنفَّذ بعد توليد Microdot لاستجابة خطأ (404، 500، استثناء مرفوع، إلخ.). تأخذ f الوسيطين
(request, response)ويجب أن تُرجع كائن الاستجابة (ربما بعد تعديله). تُرجع f دون تغيير.
- errorhandler(status_code_or_exception_class) Callable¶
مزيِّن يسجل معالجًا مخصصًا لرمز حالة HTTP أو لصنف استثناء Python. بالنسبة لرموز الحالة، يأخذ المعالج الطلب فقط؛ وبالنسبة لأصناف الاستثناءات، يأخذ
(request, exception). يُرجع المزيِّن.
التركيب والإجهاض
- mount(subapp: Microdot, url_prefix: str = '', local: bool = False) None¶
يربط مسارات مثيل
Microdotآخر تحت url_prefix. عندما تكون local قيمتهاFalse(الافتراضي)، تُربط أيضًا معالجات before / after / error الخاصة بالتطبيق الفرعي بالتطبيق الأصل. وعندما تكونTrue، تُنفَّذ تلك المعالجات لمسارات التطبيق الفرعي فقط. يُرجعNone.
- static abort(status_code: int, reason: str | None = None) None¶
ارفع
HTTPExceptionلإجهاض الطلب الحالي برمز الحالة المعطى. لا يعود أبدًا بصورة طبيعية -- يلتقط الإطار الاستثناء ويحوله إلى استجابة الخطأ المقابلة. مريح داخل أجسام المسارات:from microdot import abort @app.get('/users/<int:id>') def get_user(request, id): user = lookup(id) if user is None: abort(404) return user.to_dict()
تشغيل الخادم
- run(host: str = '0.0.0.0', port: int = 5000, debug: bool = False, ssl=None) None¶
يحجب الخيط المستدعي، ويُشغِّل
asyncio.run()علىstart_server(). لا يُرجعNoneإلا بعد استدعاءshutdown()وخروج حلقة الإصغاء. أبسط طريقة لتشغيل تطبيق مستقل:app.run(host='0.0.0.0', port=80)
- async start_server(host: str = '0.0.0.0', port: int = 5000, debug: bool = False, ssl=None, start_serving: bool = True) None¶
يبدأ الخادم كروتين متزامن (coroutine). استخدم هذا عند الدمج مع حلقة أحداث
asyncioقائمة إلى جانب مهام أخرى. لا يعود الروتين المتزامن حتى يُستدعىshutdown()async def main(): await asyncio.gather( app.start_server(port=80), capture_loop(), )
- host
واجهة الشبكة التي يُصغى عليها.
'0.0.0.0'(الافتراضي) تعني جميع الواجهات؛ و'127.0.0.1'تعني الاسترجاع المحلي (loopback) فقط.- port
منفذ TCP الذي يُصغى عليه. الافتراضي
5000-- اختر80لأجل HTTP العادي، و443لأجل HTTPS.- debug
إذا كانت
True، فسجِّل كل طلب وأخرِج تتبعات المكدس إلى stdout.- ssl
كائن
ssl.SSLContextلتغليف الاتصالات الواردة بـ TLS. القيمةNone(الافتراضي) تعني HTTP عاديًا.- start_serving
ذو صلة على CPython فقط؛ ويُتجاهَل على MicroPython.
- shutdown() None¶
يطلب إيقاف تشغيل الخادم بسلاسة. يمكن استدعاؤه بأمان من معالج مسار -- يكتمل الطلب الحالي قبل خروج الحلقة. يعود فورًا؛ ويحدث الإيقاف الفعلي بمجرد انتهاء الطلب الجاري تنفيذه.
السمات
- url_map: list¶
قائمة بالمسارات المسجلة على هيئة صفوف
(methods, URLPattern, handler, url_prefix, subapp).
- before_request_handlers: list¶
قائمة بالكائنات القابلة للاستدعاء المسجلة بـ
before_request()، بترتيب التسجيل. يُنفَّذ كل منها مع كائن الطلب قبل معالج المسار. يعمل تعديل القائمة مباشرةً لكنه نادرًا ما يُحتاج إليه -- يُفضَّل استخدام المزيِّن.
- after_request_handlers: list¶
قائمة بالكائنات القابلة للاستدعاء المسجلة بـ
after_request()، بترتيب التسجيل. يُنفَّذ كل منها مع(request, response)بعد طلب ناجح ويجب أن يُرجع الاستجابة (ربما بعد تعديلها).
- after_error_request_handlers: list¶
قائمة بالكائنات القابلة للاستدعاء المسجلة بـ
after_error_request()، بترتيب التسجيل. يُنفَّذ كل منها مع(request, response)بعد توليد استجابة خطأ (بواسطة الإطار أو بواسطة معالج خطأ في التطبيق) ويجب أن يُرجع الاستجابة.
- error_handlers: dict¶
تعيين (mapping) لمفاتيح الأخطاء إلى كائنات معالجة قابلة للاستدعاء، تُملأ بواسطة
errorhandler(). المفاتيح إما رموز حالة HTTP (int) أو أصناف استثناءات Python؛ والقيم هي المعالجات المسجلة. تأخذ معالجات رموز الحالة(request)؛ وتأخذ معالجات أصناف الاستثناءات(request, exception).
class Request¶
- class microdot.Request¶
طلب HTTP وارد. تُمرَّر المثيلات إلى معالجات المسارات كأول وسيط موضعي. لا تنشئ التطبيقات
Requestمباشرةً.سمات الصنف
- max_content_length: int¶
ترفض الطلبات التي يتجاوز
Content-Lengthفيها هذا العدد من البايتات باستجابة 413. الافتراضي 16 كيلوبايت.
- max_body_length: int¶
أكبر جسم يُخزَّن مؤقتًا في الذاكرة ويُعرَض عبر
body. تبقى الأجسام الأكبر (حتىmax_content_length) على المقبس (socket) ويجب قراءتها عبرstream. الافتراضي 16 كيلوبايت.
سمات المثيل
- headers: NoCaseDict¶
ترويسات الطلب على هيئة
NoCaseDict(بحث غير حساس لحالة الأحرف).
- g: object¶
حاوية حرة الشكل خاصة بكل طلب (كائن فارغ). أسنِد إليها سمات لتمرير القيم بين الخطافات والمعالجات (
request.g.user = ...).
- route: Callable¶
دالة المعالج التي طابقت هذا الطلب.
الوصول إلى الجسم
- stream: object¶
كائن دفق غير متزامن يعرض
read()على الجسم. استخدم هذا لأجل الأجسام الأكبر منmax_body_length.
- json: dict | list | str | int | float | bool | None¶
الجسم بعد تحليله بصيغة JSON (إما
dictأوlistأوstrأوintأوfloatأوbool-- أيًا كان ما تشفره الحمولة)، أوNoneإذا لم يكنContent-Typeهوapplication/json.
- form: MultiDict | None¶
حقول النموذج المشفرة بصيغة URL على هيئة
MultiDict، أوNone. لأجلmultipart/form-data، زيِّن المسار بـmicrodot.multipart.with_form_data().
- files: dict | None¶
الملفات المرفوعة على هيئة
{name: FileUpload}، تُملأ بواسطةmicrodot.multipart.with_form_data(). تكونNoneحتى يُنفَّذ ذلك المزيِّن.
- after_request(f: Callable) Callable¶
يسجل خطاف ما بعد الطلب محليًا للطلب -- يُنفَّذ بعد معالجات ما بعد الطلب على مستوى التطبيق، عند النجاح فقط. تأخذ f الوسيطين
(request, response)ويجب أن تُرجع كائن الاستجابة (ربما بعد تعديله). تُرجع f دون تغيير.
class Response¶
- class microdot.Response(body=b'', status_code: int = 200, headers: dict | None = None, reason: str | None = None)¶
استجابة HTTP. تُرجع معظم المعالجات قيمًا يحولها Microdot إلى
Responseتلقائيًا؛ أنشئ واحدة مباشرةً عندما تحتاج إلى ترويسات مخصصة أو رمز حالة محدد.- body
جسم الاستجابة. تُشفَّر
strبترميز UTF-8؛ وتُشفَّرdict/listبصيغة JSON ويُضبَطContent-Typeتبعًا لذلك؛ وتُرسَلbytesكما هي؛ ويُبَث كائن شبيه بالملف أو مولِّد غير متزامن.- status_code
حالة HTTP رقمية. الافتراضي 200.
- headers
قاموس بترويسات الاستجابة (غير حساس لحالة الأحرف).
- reason
عبارة سبب مخصصة. القيمة الافتراضية
"OK"لأجل 200 و"N/A"فيما عدا ذلك.
سمات الصنف
- default_content_type: str¶
نوع المحتوى المستخدم عندما لا يُضبَط أي نوع صراحةً. الافتراضي
'text/plain'.
- default_send_file_max_age: int | None¶
قيمة
Cache-Control: max-ageلأجلsend_file()عندما لا تُعطى قيمةmax_age. القيمةNone(الافتراضي) تعني عدم وجود ترويسة Cache-Control.
- send_file_buffer_size: int¶
حجم القطعة لأجل بث
send_file(). الافتراضي 1024.
- already_handled: None¶
قيمة حارسة (sentinel) تُرجَع من المعالجات التي كتبت الاستجابة مباشرةً بالفعل (تستخدمها ترقيات WebSocket). تكون دائمًا
None؛ والمهم هو هويتها.
- types_map: dict¶
خريطة من الامتداد إلى نوع mime يستخدمها
send_file()لاستنتاج نوع المحتوى. تربطcssوgifوhtmlوjpgوjsوjsonوpngوtxtوsvg.
الطرائق
- set_cookie(cookie: str, value: str, path: str | None = None, domain: str | None = None, expires=None, max_age: int | None = None, secure: bool = False, http_only: bool = False, partitioned: bool = False) None¶
يضيف ترويسة
Set-Cookie. قد تكون expires سلسلة منسقة مسبقًا أو كائنًا شبيهًا بـdatetimeلهtimetuple(). يُرجعNone؛ وتُلحَق الترويسة بهذه الاستجابة في مكانها.
- delete_cookie(cookie: str, **kwargs) None¶
يضبط
Set-Cookieتنتهي صلاحية ملف تعريف الارتباط المعطى فورًا. تقبلkwargsالخيارات نفسها التي تقبلهاset_cookie()(pathوdomainوsecureوhttp_onlyوpartitioned)؛ وتُتجاهَلexpiresوmax_age. يُرجعNone؛ وتُلحَق الترويسة بهذه الاستجابة في مكانها.
- classmethod redirect(location: str, status_code: int = 302) Response¶
يُرجع استجابة إعادة توجيه:
@app.get('/old') def old(request): return Response.redirect('/new')
- classmethod send_file(filename: str, status_code: int = 200, content_type: str | None = None, stream=None, max_age: int | None = None, compressed: bool | str = False, file_extension: str = '') Response¶
يبث ملفًا من نظام الملفات كجسم للاستجابة. يُستنتَج
content_typeمن الامتداد عبرtypes_mapإن لم يُعطَ. ويضبطcompressed=TrueالترويسةContent-Encoding: gzip(يجب أن يكون الملف مضغوطًا بالفعل).تحذير
يُفتح filename مباشرةً. لا تمرر أبدًا مسارًا مزودًا من المستخدم دون تطهير -- فالقيام بذلك يتيح كشف ملفات اعتباطية.
الاستثناءات¶
class URLPattern¶
- class microdot.URLPattern(url_pattern: str)¶
الصيغة المُجمَّعة لنمط عنوان URL الخاص بمسار. يُنشأ تلقائيًا بواسطة
Microdot.route()؛ ونادرًا ما تنشئ التطبيقات واحدًا مباشرةً.- classmethod register_type(type_name: str, pattern: str = '[^/]+', parser: Callable | None = None) None¶
يسجل نوع مقطع ديناميكي جديد للاستخدام في أنماط المسارات. يُرجع
None؛ ويُضاف النوع إلى سجل الأنواع على مستوى الصنف. على سبيل المثال لإضافة نوع<uuid:...>URLPattern.register_type('uuid', '[0-9a-f-]{36}')parser هو كائن قابل للاستدعاء اختياري يحوِّل السلسلة الملتقطة قبل أن تصل إلى المعالج.
أصناف مساعِدة¶
- class microdot.MultiDict(initial_dict: dict | None = None)¶
صنف فرعي من dict يخزن قيمًا متعددة لكل مفتاح. يُستخدم لسلاسل الاستعلام وأجسام النماذج المشفرة بصيغة URL حيث يمكن أن يظهر المفتاح نفسه أكثر من مرة (
?tag=a&tag=b).
- class microdot.NoCaseDict¶
صنف فرعي من dict بمفاتيح نصية غير حساسة لحالة الأحرف. يُستخدم لأجل
Request.headersوResponse.headers.
دوال على مستوى الوحدة¶
- microdot.abort(status_code: int, reason: str | None = None) None¶
اختصار لـ
Microdot.abort(). لا يعود أبدًا بصورة طبيعية -- يرفعHTTPException. قابل للاستيراد بصيغةfrom microdot import abort.
- microdot.redirect(location: str, status_code: int = 302) Response¶
اختصار لـ
Response.redirect(). قابل للاستيراد بصيغةfrom microdot import redirect.
- microdot.send_file(filename: str, **kwargs) Response¶
اختصار لـ
Response.send_file().
- microdot.urlencode(s: str) str¶
يشفِّر مكوِّن عنوان URL بترميز النسبة المئوية (percent-encode). يستبدل الأحرف ذات المعنى المحجوز في عنوان URL (
/و?و&و=و#ومسافة ...) بهرَوبها الست عشري%xxبحيث يمكن أن توضع النتيجة بأمان داخل مقطع مسار أو قيمة استعلام. يُرجعstrالمشفرة.
- microdot.urldecode(s: str) str¶
يفك تشفير مكوِّن عنوان URL من ترميز النسبة المئوية -- معكوس
urlencode(). تُستبدَل هرَوبات%xxبالبايت الذي تشفره، وتُحوَّل+إلى مسافة (وفق العرف التاريخي لسلسلة الاستعلام). يُرجعstrالمفكوكة.
الوحدات الفرعية¶
microdot.auth--- مصادقة HTTPmicrodot.cors--- مشاركة الموارد عبر المصادر (CORS)microdot.csrf--- حماية CSRFmicrodot.login--- تدفق تسجيل دخول المستخدمmicrodot.multipart--- تحليل multipart/form-datamicrodot.session--- جلسات ملفات تعريف الارتباط الموقَّعةmicrodot.sse--- أحداث مُرسَلة من الخادم (Server-Sent Events)microdot.websocket--- دعم WebSocket