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 สร้างอินสแตนซ์หนึ่งไว้ใกล้ส่วนบนของสคริปต์และตกแต่งด้วย route handler แล้วเรียก run() หรือรอ start_server() เพื่อเริ่มให้บริการ

การลงทะเบียน Route

route(url_pattern: str, methods: list | None = None) Callable#

Decorator ที่ลงทะเบียน handler สำหรับ url_pattern ภายใต้ HTTP method ที่ระบุ (ค่าเริ่มต้น ['GET']) คืนค่า decorator ซึ่งเมื่อนำไปใช้กับฟังก์ชันจะลงทะเบียนเป็น handler และคืนฟังก์ชันนั้นโดยไม่เปลี่ยนแปลง

url_pattern

รูปแบบ path รองรับส่วนคงที่ (/users) และส่วนไดนามิกที่ล้อมรอบด้วย < / > ส่วนไดนามิกยอมรับคำนำหน้าประเภทที่คั่นด้วย : -- <int:id>, <path:rest>, <re:[0-9a-f]+:hex> ประเภทเริ่มต้นคือ string

methods

รายการชื่อ HTTP method หากละไว้จะจับคู่เฉพาะ GET เท่านั้น

Handler ถูกเรียกด้วย request object เป็นอาร์กิวเมนต์แรก ตามด้วยส่วนไดนามิกที่ดักจับได้เป็น keyword argument ค่าที่ handler คืนกลับมาจะกลายเป็น HTTP response ได้แก่ Response, string, tuple (body, status_code[, headers]), หรือ dict / list (ส่งเป็น JSON)

get(url_pattern: str) Callable#

ชื่อแทนสำหรับ route(url_pattern, methods=['GET']) -- ลงทะเบียนฟังก์ชันที่ตกแต่งเป็น GET handler สำหรับ url_pattern คืนค่า decorator

post(url_pattern: str) Callable#

ชื่อแทนสำหรับ route(url_pattern, methods=['POST']) -- ลงทะเบียนฟังก์ชันที่ตกแต่งเป็น POST handler สำหรับ url_pattern คืนค่า decorator

put(url_pattern: str) Callable#

ชื่อแทนสำหรับ route(url_pattern, methods=['PUT']) -- ลงทะเบียนฟังก์ชันที่ตกแต่งเป็น PUT handler สำหรับ url_pattern คืนค่า decorator

patch(url_pattern: str) Callable#

ชื่อแทนสำหรับ route(url_pattern, methods=['PATCH']) -- ลงทะเบียนฟังก์ชันที่ตกแต่งเป็น PATCH handler สำหรับ url_pattern คืนค่า decorator

delete(url_pattern: str) Callable#

ชื่อแทนสำหรับ route(url_pattern, methods=['DELETE']) -- ลงทะเบียนฟังก์ชันที่ตกแต่งเป็น DELETE handler สำหรับ url_pattern คืนค่า decorator

Lifecycle hooks

before_request(f: Callable) Callable#

Decorator ที่ลงทะเบียน f ให้ทำงานก่อนทุก request f รับ request object และค่าที่คืนมักถูกละเว้น หากต้องการหยุดการประมวลผล request ให้คืนค่า Response (หรือค่าที่แปลงเป็นหนึ่งได้) -- pipeline ที่เหลือจะถูกข้ามและส่ง response นั้น คืนค่า f โดยไม่เปลี่ยนแปลง

after_request(f: Callable) Callable#

Decorator ที่ลงทะเบียน f ให้ทำงานหลัง request ที่สำเร็จทุกรายการ f รับ (request, response) และต้องคืน response object (ที่อาจปรับแล้ว) คืนค่า f โดยไม่เปลี่ยนแปลง

after_error_request(f: Callable) Callable#

Decorator ที่ลงทะเบียน f ให้ทำงานหลังจาก Microdot สร้าง error response (404, 500, exception ที่เกิดขึ้น ฯลฯ) f รับ (request, response) และต้องคืน response object (ที่อาจปรับแล้ว) คืนค่า f โดยไม่เปลี่ยนแปลง

errorhandler(status_code_or_exception_class) Callable#

Decorator ที่ลงทะเบียน handler กำหนดเองสำหรับ HTTP status code หรือ Python exception class สำหรับ status code handler รับเฉพาะ request เท่านั้น สำหรับ exception class รับ (request, exception) คืนค่า decorator

การ Mount และการยกเลิก

mount(subapp: Microdot, url_prefix: str = '', local: bool = False) None#

แนบ route ของอินสแตนซ์ Microdot อื่นภายใต้ url_prefix เมื่อ local เป็น False (ค่าเริ่มต้น) before / after / error handler ของ sub-app จะถูกแนบกับ parent ด้วย เมื่อเป็น True handler เหล่านั้นจะทำงานเฉพาะสำหรับ sub-app route เท่านั้น คืนค่า None

static abort(status_code: int, reason: str | None = None) None#

เรียก HTTPException เพื่อยกเลิก request ปัจจุบันด้วย status code ที่กำหนด ไม่มีการคืนค่าปกติ -- เฟรมเวิร์กจะดักจับ exception และแปลงเป็น error response ที่สอดคล้อง ใช้งานได้สะดวกภายใน route body:

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#

บล็อก thread ที่เรียก รัน asyncio.run() บน start_server() คืนค่า None เฉพาะหลังจาก shutdown() ถูกเรียกและ listening loop ออก วิธีที่ง่ายที่สุดในการเปิดแอปแบบ standalone:

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 event loop ที่มีอยู่พร้อมกับ task อื่น coroutine จะไม่คืนค่าจนกว่า shutdown() จะถูกเรียก:

async def main():
    await asyncio.gather(
        app.start_server(port=80),
        capture_loop(),
    )
host

Network interface ที่จะรับฟัง '0.0.0.0' (ค่าเริ่มต้น) หมายถึงทุก interface; '127.0.0.1' หมายถึง loopback เท่านั้น

port

TCP port ที่จะรับฟัง ค่าเริ่มต้น 5000 -- เลือก 80 สำหรับ HTTP ธรรมดา, 443 สำหรับ HTTPS

debug

หากเป็น True จะบันทึกทุก request และแสดง traceback ไปยัง stdout

ssl

ssl.SSLContext สำหรับห่อการเชื่อมต่อขาเข้าใน TLS None (ค่าเริ่มต้น) หมายถึง HTTP ธรรมดา

start_serving

ใช้ได้เฉพาะบน CPython เท่านั้น ถูกละเว้นบน MicroPython

shutdown() None#

ขอปิดเซิร์ฟเวอร์อย่างนุ่มนวล ปลอดภัยที่จะเรียกจาก route handler -- request ปัจจุบันเสร็จสิ้นก่อนที่ loop จะออก คืนค่าทันที การปิดเซิร์ฟเวอร์จริงจะเกิดขึ้นเมื่อ request ที่กำลังดำเนินการเสร็จสิ้น

Attribute

url_map: list#

รายการ route ที่ลงทะเบียนแล้วเป็น tuple (methods, URLPattern, handler, url_prefix, subapp)

before_request_handlers: list#

รายการ callable ที่ลงทะเบียนด้วย before_request() ตามลำดับการลงทะเบียน แต่ละรายการทำงานกับ request object ก่อน route handler การปรับเปลี่ยน list โดยตรงใช้งานได้แต่แทบไม่จำเป็น -- แนะนำให้ใช้ decorator

after_request_handlers: list#

รายการ callable ที่ลงทะเบียนด้วย after_request() ตามลำดับการลงทะเบียน แต่ละรายการทำงานกับ (request, response) หลัง request ที่สำเร็จและต้องคืน response (ที่อาจปรับแล้ว)

after_error_request_handlers: list#

รายการ callable ที่ลงทะเบียนด้วย after_error_request() ตามลำดับการลงทะเบียน แต่ละรายการทำงานกับ (request, response) หลังจาก error response ถูกสร้าง (โดยเฟรมเวิร์กหรือ application error handler) และต้องคืน response

error_handlers: dict#

Mapping ของ error key ไปยัง handler callable ที่เติมข้อมูลโดย errorhandler() key เป็น HTTP status code (int) หรือ Python exception class; value คือ handler ที่ลงทะเบียน Status-code handler รับ (request); exception-class handler รับ (request, exception)

debug: bool#

True ขณะที่เซิร์ฟเวอร์กำลังทำงานด้วย debug=True

class Request#

class microdot.Request#

HTTP request ขาเข้า อินสแตนซ์ถูกส่งไปยัง route handler เป็นอาร์กิวเมนต์ตำแหน่งแรก แอปพลิเคชันไม่สร้าง Request โดยตรง

Class attribute

max_content_length: int#

ปฏิเสธ request ที่มี Content-Length เกินจำนวนไบต์นี้ด้วย response 413 ค่าเริ่มต้น 16 KB

max_body_length: int#

ขนาด body ที่ใหญ่ที่สุดที่บัฟเฟอร์ไว้ในหน่วยความจำและเปิดเผยผ่าน body body ที่ใหญ่กว่า (ไม่เกิน max_content_length) จะอยู่บน socket และต้องอ่านผ่าน stream ค่าเริ่มต้น 16 KB

max_readline: int#

ความยาวสูงสุดของ request line หรือ header line หนึ่งบรรทัดในหน่วยไบต์ ค่าเริ่มต้น 2 KB

Instance attribute

app: Microdot#

อินสแตนซ์ Microdot ที่จัดการ request

client_addr: tuple#

ที่อยู่ของ client เป็น (host, port)

method: str#

HTTP method string ('GET', 'POST', ...)

scheme: str#

'http' หรือ 'https'

url: str#

URL path และ query string ของ request แบบเต็ม (ทุกอย่างหลัง host)

path: str#

เฉพาะส่วน path

query_string: str | None#

ส่วน query string ดิบ หรือ None

args: MultiDict#

Query string ที่แปลงแล้วเป็น MultiDict

headers: NoCaseDict#

Request header เป็น NoCaseDict (การค้นหาแบบไม่คำนึงถึงตัวพิมพ์)

cookies: dict#

Cookie header ที่แปลงแล้วเป็น dict

content_length: int#

ค่า Content-Length แบบ integer หรือ 0 หากไม่มี

content_type: str | None#

ค่า Content-Type header หรือ None

g: object#

คอนเทนเนอร์แบบอิสระต่อ request (object ว่างเปล่า) กำหนด attribute เพื่อส่งค่าระหว่าง hook และ handler (request.g.user = ...)

route: Callable#

ฟังก์ชัน handler ที่จับคู่กับ request นี้

url_prefix: str#

Prefix ที่ route ถูก mount ไว้ หรือ ''

subapp: Microdot | None#

อินสแตนซ์ sub-app ที่ mount ไว้ หรือ None

การเข้าถึง Body

body: bytes#

Request body แบบเต็มเป็น bytes ว่างเปล่าเมื่อ body กำลังถูก stream (ดู stream)

stream: object#

async stream object ที่เปิดเผย read() บน body ใช้สิ่งนี้สำหรับ body ที่ใหญ่กว่า max_body_length

json: dict | list | str | int | float | bool | None#

Body ที่แปลงเป็น JSON (dict, list, str, int, float, หรือ bool -- ตามที่ payload เข้ารหัส) หรือ None หาก Content-Type ไม่ใช่ application/json

form: MultiDict | None#

Form field ที่เข้ารหัส URL เป็น MultiDict หรือ None สำหรับ multipart/form-data ให้ตกแต่ง route ด้วย microdot.multipart.with_form_data()

files: dict | None#

ไฟล์ที่อัปโหลดเป็น {name: FileUpload} ถูกเติมข้อมูลโดย microdot.multipart.with_form_data() None จนกว่า decorator นั้นจะทำงาน

after_request(f: Callable) Callable#

ลงทะเบียน after-request hook เฉพาะ request -- ทำงานหลัง application-level after-request handler เฉพาะเมื่อสำเร็จ f รับ (request, response) และต้องคืน response object (ที่อาจปรับแล้ว) คืนค่า f โดยไม่เปลี่ยนแปลง

class Response#

class microdot.Response(body=b'', status_code: int = 200, headers: dict | None = None, reason: str | None = None)#

HTTP response ส่วนใหญ่ handler คืนค่าที่ Microdot แปลงเป็น Response โดยอัตโนมัติ สร้างโดยตรงเมื่อต้องการ header กำหนดเองหรือ status code เฉพาะ

body

Response body str เข้ารหัสเป็น UTF-8; dict / list เข้ารหัสเป็น JSON และตั้ง Content-Type ตามนั้น; bytes ส่งตรง; file-like object หรือ async generator จะ stream

status_code

HTTP status แบบตัวเลข ค่าเริ่มต้น 200

headers

Dict ของ response header (ไม่คำนึงถึงตัวพิมพ์)

reason

วลีเหตุผลกำหนดเอง ค่าเริ่มต้นคือ "OK" สำหรับ 200 และ "N/A" สำหรับอื่น ๆ

Class attribute

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 header

send_file_buffer_size: int#

ขนาด chunk สำหรับ streaming ของ send_file() ค่าเริ่มต้น 1024

already_handled: None#

Sentinel ที่คืนจาก handler ที่เขียน response โดยตรงแล้ว (ใช้โดย WebSocket upgrade) เสมอ None; สิ่งสำคัญคือ identity

types_map: dict#

Map ของ extension ไปยัง mime-type ที่ใช้โดย send_file() สำหรับการอนุมาน content-type จับคู่ css, gif, html, jpg, js, json, png, txt, svg

Method

เพิ่ม Set-Cookie header expires อาจเป็น string ที่จัดรูปแบบล่วงหน้าหรือ object คล้าย datetime ที่มี timetuple() คืนค่า None; header ถูกต่อท้าย response นี้ในที่เดิม

ตั้ง Set-Cookie ที่ทำให้ cookie ที่กำหนดหมดอายุทันที kwargs ยอมรับตัวเลือกเดียวกับ set_cookie() (path, domain, secure, http_only, partitioned); expires และ max_age ถูกละเว้น คืนค่า None; header ถูกต่อท้าย response นี้ในที่เดิม

classmethod redirect(location: str, status_code: int = 302) Response#

คืน redirect 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#

Stream ไฟล์จาก filesystem เป็น response body content_type อนุมานจาก extension ผ่าน types_map หากไม่ระบุ compressed=True ตั้ง Content-Encoding: gzip (ไฟล์ต้องถูกบีบอัดไว้แล้ว)

Warning

filename ถูกเปิดโดยตรง ห้ามส่ง path ที่ผู้ใช้กำหนดโดยไม่ผ่านการตรวจสอบ -- การทำเช่นนั้นทำให้เปิดเผยไฟล์ตามอำเภอใจได้

Exception#

exception microdot.HTTPException#

เรียกโดย abort() เพื่อหยุด request ด้วย status code เฉพาะ Microdot ดักจับสิ่งนี้และแปลงเป็น error response ที่สอดคล้อง

status_code: int#

HTTP status code แบบตัวเลขที่จะคืนกลับ -- ค่าที่ส่งไปยัง abort()

reason: str#

วลีเหตุผลที่จะรวมใน error response หากไม่ได้กำหนดให้ abort() ค่าเริ่มต้นคือ "<status_code> error" (เช่น "404 error")

class URLPattern#

class microdot.URLPattern(url_pattern: str)#

รูปแบบที่คอมไพล์แล้วของ URL pattern ของ route สร้างโดยอัตโนมัติโดย Microdot.route(); แอปพลิเคชันแทบไม่สร้างอินสแตนซ์โดยตรง

classmethod register_type(type_name: str, pattern: str = '[^/]+', parser: Callable | None = None) None#

ลงทะเบียนประเภทส่วนไดนามิกใหม่สำหรับใช้ใน route pattern คืนค่า None; ประเภทถูกเพิ่มในรีจิสทรีระดับ class ตัวอย่างเช่น การเพิ่มประเภท <uuid:...>

URLPattern.register_type('uuid', '[0-9a-f-]{36}')

parser คือ callable ที่ไม่บังคับซึ่งแปลง string ที่ดักจับได้ก่อนที่จะถึง handler

match(path: str) dict | None#

จับคู่ path กับ pattern และคืน dict ของกลุ่มที่ดักจับได้ หรือ None หากไม่มีการจับคู่

Helper class#

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

dict subclass ที่เก็บค่าหลายค่าต่อ key ใช้สำหรับ query string และ URL-encoded form body ที่ key เดียวกันอาจปรากฏมากกว่าหนึ่งครั้ง (?tag=a&tag=b)

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

คืนค่าแรกสำหรับ key พร้อมแปลงด้วย type (callable) หากต้องการ คืน default หาก key ไม่มีหรือการแปลงล้มเหลว มิฉะนั้นคืนค่า (ที่แปลงแล้วหากมี)

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

คืนค่าทั้งหมดสำหรับ key เป็น list พร้อมแปลงค่าแต่ละค่าด้วย type หากต้องการ คืน list ว่างหาก key ไม่มีอยู่

class microdot.NoCaseDict#

dict subclass ที่มี key string แบบไม่คำนึงถึงตัวพิมพ์ ใช้สำหรับ Request.headers และ Response.headers

ฟังก์ชันระดับ module#

microdot.abort(status_code: int, reason: str | None = None) None#

ชื่อแทนสำหรับ Microdot.abort() ไม่มีการคืนค่าปกติ -- เรียก HTTPException สามารถ import ได้เป็น from microdot import abort

microdot.redirect(location: str, status_code: int = 302) Response#

ชื่อแทนสำหรับ Response.redirect() สามารถ import ได้เป็น from microdot import redirect

microdot.send_file(filename: str, **kwargs) Response#

ชื่อแทนสำหรับ Response.send_file()

microdot.urlencode(s: str) str#

เข้ารหัส URL component แบบ percent สลับตัวอักษรที่มีความหมายพิเศษใน URL (/, ?, &, =, #, space, ...) ด้วย hex escape %xx เพื่อให้ผลลัพธ์วางภายใน path segment หรือ query value ได้อย่างปลอดภัย คืนค่า str ที่เข้ารหัสแล้ว

microdot.urldecode(s: str) str#

ถอดรหัส URL component แบบ percent -- ตรงข้ามกับ urlencode() %xx escape ถูกแทนที่ด้วยไบต์ที่เข้ารหัส และ + แปลงเป็น space (ธรรมเนียม query-string ในอดีต) คืนค่า str ที่ถอดรหัสแล้ว

Submodule#