microdot — מסגרת HTTP מינימלית#

Microdot היא מסגרת HTTP קטנה בהשראת Flask עבור MicroPython. היא פועלת מעל asyncio, מטפלת בלקוחות מקבילים מרובים ללא תהליכונים, וחושפת API מוכר של מעטרי נתיב (route decorator). יישום מינימלי נראה כך:

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]), או dict / list (הנשלחים כ-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 (או ערך המומר לכזה) – שאר הצינור (pipeline) מדולג אז ותגובה זו נשלחת. מחזיר את 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#

מתחיל את השרת כקורוטינה. השתמש בכך בעת שילוב עם לולאת אירועים קיימת של 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, רשום ביומן כל בקשה והדפס traceback ל-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#

רשימת הניתנים-לקריאה (callables) הרשומים עם before_request(), בסדר הרישום. כל אחד פועל עם אובייקט הבקשה לפני מטפל הנתיב. שינוי הרשימה ישירות עובד אך נדרש לעיתים רחוקות – העדף את המעטר.

after_request_handlers: list#

רשימת הניתנים-לקריאה (callables) הרשומים עם after_request(), בסדר הרישום. כל אחד פועל עם (request, response) לאחר בקשה מוצלחת וחייב להחזיר את התגובה (שיתכן ושונתה).

after_error_request_handlers: list#

רשימת הניתנים-לקריאה (callables) הרשומים עם after_error_request(), בסדר הרישום. כל אחד פועל עם (request, response) לאחר שתגובת שגיאה נוצרת (על ידי המסגרת או על ידי מטפל שגיאות של היישום) וחייב להחזיר את התגובה.

error_handlers: dict#

מיפוי של מפתחות שגיאה לניתנים-לקריאה של מטפלים, המאוכלס על ידי errorhandler(). המפתחות הם או קודי מצב HTTP (int) או מחלקות חריגה של Python; הערכים הם המטפלים הרשומים. מטפלי קודי מצב מקבלים (request); מטפלי מחלקות חריגה מקבלים (request, exception).

debug: bool#

True כל עוד השרת פועל עם debug=True.

class Request#

class microdot.Request#

בקשת HTTP נכנסת. מופעים מועברים למטפלי נתיב כארגומנט המיקומי הראשון. יישומים אינם בונים Request ישירות.

תכונות מחלקה

max_content_length: int#

דחה בקשות שה-Content-Length שלהן חורג ממספר בתים זה עם תגובת 413. ברירת מחדל 16 KB.

max_body_length: int#

הגוף הגדול ביותר המאוחסן בחוצץ בזיכרון ונחשף דרך body. גופים גדולים יותר (עד max_content_length) נשארים בשקע (socket) וחייבים להיקרא דרך stream. ברירת מחדל 16 KB.

max_readline: int#

האורך המרבי של שורת בקשה / שורת כותרת בודדת בבתים. ברירת מחדל 2 KB.

תכונות מופע

app: Microdot#

מופע ה-Microdot המטפל בבקשה.

client_addr: tuple#

כתובת הלקוח כ-(host, port).

method: str#

מחרוזת מתודת HTTP ('GET', 'POST', …).

scheme: str#

'http' או 'https'.

url: str#

נתיב כתובת ה-URL המלא של הבקשה ומחרוזת השאילתה (כל מה שאחרי המארח).

path: str#

רק חלק הנתיב.

query_string: str | None#

חלק מחרוזת השאילתה הגולמי, או None.

args: MultiDict#

מחרוזת השאילתה המנותחת כ-MultiDict.

headers: NoCaseDict#

כותרות הבקשה כ-NoCaseDict (חיפוש שאינו תלוי-רישיות).

cookies: dict#

כותרת ה-Cookie המנותחת כ-dict.

content_length: int#

ערך ה-Content-Length כמספר שלם, או 0 אם נעדר.

content_type: str | None#

ערך כותרת ה-Content-Type, או None.

g: object#

מכל חופשי לכל בקשה (אובייקט ריק). הקצה לו תכונות כדי להעביר ערכים בין ווים למטפלים (request.g.user = ...).

route: Callable#

פונקציית המטפל שהתאימה לבקשה זו.

url_prefix: str#

הקידומת שתחתיה הורכב הנתיב, או ''.

subapp: Microdot | None#

מופע תת-היישום המורכב, או None.

גישה לגוף

body: bytes#

גוף הבקשה המלא כ-bytes. ריק כאשר הגוף מוזרם (ראה stream).

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#

רשום וו after-request מקומי לבקשה – פועל לאחר מטפלי ה-after-request ברמת היישום, רק בהצלחה. 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

Dict של כותרות תגובה (שאינו תלוי-רישיות).

reason

ביטוי סיבה מותאם אישית. ברירת מחדל "OK" עבור 200 ו-"N/A" אחרת.

תכונות מחלקה

default_content_type: str#

Content-Type המשמש כאשר אף אחד לא נקבע במפורש. ברירת מחדל '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#

גודל מקטע (chunk) עבור הזרמת 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. expires יכול להיות מחרוזת מעוצבת מראש או אובייקט דמוי-datetime עם timetuple(). מחזיר 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#

מחזיר תגובת הפניה (redirect):

@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 נפתח ישירות. לעולם אל תעביר נתיב שסיפק המשתמש שלא עבר חיטוי – הדבר מאפשר חשיפת קבצים שרירותיים.

חריגות#

exception microdot.HTTPException#

מורם על ידי abort() כדי לקצר בקשה עם קוד מצב מסוים. Microdot לוכדת זאת והופכת זאת לתגובת השגיאה המתאימה.

status_code: int#

קוד מצב HTTP מספרי להחזרה – הערך שהועבר ל-abort().

reason: str#

ביטוי סיבה לכלילה בתגובת השגיאה. אם אינו ניתן ל-abort(), ברירת המחדל היא "<status_code> error" (למשל "404 error").

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 הוא ניתן-לקריאה (callable) אופציונלי הממיר את המחרוזת שנלכדה לפני שהיא מגיעה למטפל.

match(path: str) dict | None#

התאם את path לתבנית והחזר dict של הקבוצות שנלכדו, או None בהיעדר התאמה.

מחלקות עזר#

class microdot.MultiDict(initial_dict: dict | None = None)#

תת-מחלקה של dict המאחסנת מספר ערכים לכל מפתח. משמשת עבור מחרוזות שאילתה וגופי טופס מקודדי-URL שבהם אותו מפתח יכול להופיע יותר מפעם אחת (?tag=a&tag=b).

get(key, default=None, type: Callable | None = None)#

מחזיר את הערך הראשון עבור key, אופציונלית מומר עם type (ניתן-לקריאה). מחזיר את default אם המפתח חסר או שההמרה נכשלת; אחרת מחזיר את הערך (המומר אופציונלית).

getlist(key, type: Callable | None = None) list#

מחזיר את כל הערכים עבור key כרשימה, אופציונלית כשכל ערך מומר על ידי type. מחזיר רשימה ריקה אם key אינו קיים.

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#

מקודד באחוזים (percent-encode) רכיב URL. מחליף תווים בעלי משמעות שמורה ב-URL (/, ?, &, =, #, רווח, …) בבריחות (escapes) ההקסדצימליות שלהם %xx כך שהתוצאה יכולה לשבת בבטחה בתוך מקטע נתיב או ערך שאילתה. מחזיר את ה-str המקודד.

microdot.urldecode(s: str) str#

מפענח באחוזים (percent-decode) רכיב URL – ההפך מ-urlencode(). בריחות %xx מוחלפות בבית שהן מקודדות, ו-+ מומר לרווח (מוסכמת מחרוזת השאילתה ההיסטורית). מחזיר את ה-str המפוענח.

תת-מודולים#