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 המפוענח.

תת-מודולים