wsgiref --- ابزارهای WSGI و پیادهسازی مرجع¶
کد منبع: Lib/wsgiref
هشدار
wsgiref یک پیادهسازی مرجع است و برای استفاده در محیط عملیاتی توصیه نمیشود. این ماژول تنها بررسیهای امنیتی پایه را انجام میدهد.
رابط دروازهی سرور وب (WSGI) یک رابط استاندارد میان نرمافزار سرور وب و برنامههای وب نوشتهشده با پایتون است. داشتن یک رابط استاندارد، استفاده از برنامهای را که از WSGI پشتیبانی میکند با تعدادی از سرورهای وب مختلف آسان میسازد.
تنها نویسندگان وبسرورها و چارچوبهای برنامهنویسی نیاز دارند که تمام جزئیات و حالتهای خاص طراحی WSGI را بدانند. شما صرفاً برای نصب یک برنامه WSGI یا نوشتن یک برنامه وب با استفاده از یک چارچوب موجود، نیازی به درک تمام جزئیات WSGI ندارید.
wsgiref یک پیادهسازی مرجع از مشخصات WSGI است که میتوان از آن برای افزودن پشتیبانی از WSGI به یک وبسرور یا چارچوب استفاده کرد. این ماژول ابزارهایی برای دستکاری متغیرهای محیطی WSGI و سرآیندهای پاسخ، کلاسهای پایه برای پیادهسازی سرورهای WSGI، یک سرور HTTP نمایشی که به برنامههای WSGI سرویس میدهد، انواعی برای بررسی ایستای نوع، و یک ابزار اعتبارسنجی را فراهم میکند که سرورها و برنامههای WSGI را از نظر انطباق با مشخصات WSGI (PEP 3333) بررسی میکند.
برای اطلاعات بیشتر درباره WSGI و پیوندهایی به آموزشها و سایر منابع، به wsgi.readthedocs.io مراجعه کنید.
wsgiref.util -- ابزارهای سودمند محیط WSGI¶
این ماژول توابع کاربردی متنوعی برای کار با محیطهای WSGI فراهم میکند. محیط WSGI دیکشنری حاوی متغیرهای درخواست HTTP است که در PEP 3333 توصیف شده است. تمام توابعی که پارامتر environ میپذیرند، انتظار دارند یک دیکشنری مطابق با WSGI ارائه شود؛ لطفاً برای مشخصات دقیق، PEP 3333 و برای نام مستعار نوعی که میتواند در حاشیهنویسیهای نوع استفاده شود، WSGIEnvironment را ببینید.
- wsgiref.util.guess_scheme(environ)¶
با بررسی متغیر محیطی
HTTPSدر دیکشنری environ، حدسی دربارهی اینکهwsgi.url_schemeباید "http" باشد یا "https" برمیگرداند. مقدار بازگشتی یک رشته است.این تابع هنگام ایجاد درگاهی که CGI یا پروتکلی مشابه CGI مانند FastCGI را پوشش میدهد، مفید است. معمولاً سرورهایی که چنین پروتکلهایی را ارائه میدهند، هنگامی که درخواستی از طریق SSL دریافت میشود، شامل یک متغیر
HTTPSبا مقدار "1"، "yes" یا "on" هستند. بنابراین، این تابع در صورت یافتن چنین مقداری، "https" و در غیر این صورت "http" را برمیگرداند.
- wsgiref.util.request_uri(environ, include_query=True)¶
URI کامل درخواست را، بهصورت اختیاری شامل رشتهی کوئری، با استفاده از الگوریتم موجود در بخش «URL Reconstruction» در PEP 3333 برمیگرداند. اگر include_query نادرست باشد، رشتهی کوئری در URI حاصل گنجانده نمیشود.
- wsgiref.util.application_uri(environ)¶
مشابه
request_uri()، با این تفاوت که متغیرهایPATH_INFOوQUERY_STRINGنادیده گرفته میشوند. نتیجه، URI پایهی شیء برنامهی مورد اشارهی درخواست است.
- wsgiref.util.shift_path_info(environ)¶
یک نام را از
PATH_INFOبهSCRIPT_NAMEجابهجا میکند و نام را برمیگرداند. دیکشنری environ بهصورت درجا تغییر مییابد؛ اگر نیاز داریدPATH_INFOیاSCRIPT_NAMEاصلی را دستنخورده نگه دارید، از یک کپی استفاده کنید.اگر هیچ بخش مسیر باقیماندهای در
PATH_INFOوجود نداشته باشد،Noneبرگردانده میشود.معمولاً از این تابع برای پردازش هر بخش از مسیر URI درخواست استفاده میشود، برای مثال برای اینکه با مسیر بهعنوان دنبالهای از کلیدهای دیکشنری رفتار شود. این تابع محیط دادهشده را تغییر میدهد تا برای فراخوانی یک برنامه WSGI دیگر که در URI هدف قرار دارد مناسب شود. برای مثال، اگر یک برنامه WSGI در
/fooوجود داشته باشد، و مسیر URI درخواست/foo/bar/bazباشد، و برنامه WSGI در/fooتابعshift_path_info()را فراخوانی کند، رشته "bar" را دریافت خواهد کرد، و محیط بهگونهای بهروزرسانی میشود که برای ارسال به یک برنامه WSGI در/foo/barمناسب باشد. یعنیSCRIPT_NAMEاز/fooبه/foo/barتغییر میکند، وPATH_INFOاز/bar/bazبه/bazتغییر میکند.هنگامی که
PATH_INFOفقط یک "/" باشد، این رویه یک رشته خالی برمیگرداند و یک اسلش پایانی بهSCRIPT_NAMEمیافزاید، هرچند بخشهای خالی مسیر معمولاً نادیده گرفته میشوند وSCRIPT_NAMEمعمولاً به اسلش ختم نمیشود. این رفتار عمدی است تا اطمینان حاصل شود که یک برنامه کاربردی میتواند هنگام استفاده از این رویه برای پیمایش شیء، تفاوت میان URIهایی که به/xختم میشوند و آنهایی که به/x/ختم میشوند را تشخیص دهد.
- wsgiref.util.setup_testing_defaults(environ)¶
environ را با پیشفرضهای ساده برای اهداف آزمایش بهروزرسانی کنید.
این روال، پارامترهای مختلفی را که برای WSGI مورد نیاز هستند اضافه میکند، از جمله
HTTP_HOST،SERVER_NAME،SERVER_PORT،REQUEST_METHOD،SCRIPT_NAME،PATH_INFOو همهی متغیرهایwsgi.*تعریفشده در PEP 3333. این روال تنها مقادیر پیشفرض را فراهم میکند و هیچیک از تنظیمات موجود برای این متغیرها را جایگزین نمیکند.این روتین در نظر گرفته شده است تا راهاندازی محیطهای ساختگی را برای آزمونهای واحد سرورها و برنامههای WSGI آسانتر کند. سرورها یا برنامههای WSGI واقعی نباید از آن استفاده کنند، زیرا دادهها جعلی هستند!
نمونه استفاده (همچنین برای نمونهای دیگر
demo_app()را ببینید):from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server # A relatively simple WSGI application. It's going to print out the # environment dictionary after being updated by setup_testing_defaults def simple_app(environ, start_response): setup_testing_defaults(environ) status = '200 OK' headers = [('Content-type', 'text/plain; charset=utf-8')] start_response(status, headers) ret = [("%s: %s\n" % (key, value)).encode("utf-8") for key, value in environ.items()] return ret with make_server('', 8000, simple_app) as httpd: print("Serving on port 8000...") httpd.serve_forever()
علاوه بر توابع محیطی بالا، ماژول wsgiref.util این ابزارهای متفرقه را نیز فراهم میکند:
- wsgiref.util.is_hop_by_hop(header_name)¶
اگر 'header_name' یک سرآیند HTTP/1.1 از نوع «Hop-by-Hop» باشد، همانطور که در RFC 2616 تعریف شده است،
Trueبرمیگرداند.
- class wsgiref.util.FileWrapper(filelike, blksize=8192)¶
یک پیادهسازی عینی از پروتکل
wsgiref.types.FileWrapperکه برای تبدیل یک شیء شبهپرونده به یک پیمایشگر به کار میرود. اشیای حاصل، پیمایشپذیر هستند. هنگامی که شیء مورد تکرار قرار میگیرد، پارامتر اختیاری blksize بهطور مکرر به متدread()شیء filelike پاس داده خواهد شد تا رشتههای بایتی برای yield به دست آیند. هنگامی کهread()یک رشته بایتی خالی برگرداند، تکرار پایان مییابد و قابل از سرگیری نیست.اگر filelike دارای متد
close()باشد، شیء برگرداندهشده نیز دارای متدclose()خواهد بود و هنگام فراخوانی، متدclose()شیء filelike را فراخوانی میکند.نمونه استفاده:
from io import StringIO from wsgiref.util import FileWrapper # We're using a StringIO-buffer for as the file-like object filelike = StringIO("This is an example file-like object"*10) wrapper = FileWrapper(filelike, blksize=5) for chunk in wrapper: print(chunk)
تغییر یافته در نسخهی 3.11: پشتیبانی از متد
__getitem__()حذف شده است.
wsgiref.headers -- ابزارهای سرآیند پاسخ WSGI¶
این ماژول یک کلاس واحد، Headers، را برای دستکاری آسان سرآیندهای پاسخ WSGI با استفاده از یک رابط نگاشتمانند ارائه میدهد.
- class wsgiref.headers.Headers([headers])¶
یک شیء نگاشتمانند ایجاد کنید که پوششی برای headers است؛ headers باید فهرستی از تاپلهای نام/مقدار سرآیند باشد، همانطور که در PEP 3333 توضیح داده شده است. مقدار پیشفرض headers یک فهرست خالی است.
اشیای
Headersاز عملیات معمول نگاشت پشتیبانی میکنند، از جمله__getitem__()،get()،__setitem__()،setdefault()،__delitem__()و__contains__(). برای هر یک از این متدها، کلید نام سرآیند است (بدون حساسیت به بزرگی و کوچکی حروف در نظر گرفته میشود)، و مقدار نخستین مقدار مرتبط با آن نام سرآیند است. تنظیم یک سرآیند تمام مقدارهای موجود برای آن سرآیند را حذف میکند، سپس یک مقدار جدید را در انتهای فهرست سرآیندهای تحت پوشش اضافه میکند. ترتیب موجود سرآیندها بهطور کلی حفظ میشود، و سرآیندهای جدید به انتهای فهرست تحت پوشش اضافه میشوند.برخلاف دیکشنری، اشیای
Headersهنگامی که سعی میکنید کلیدی را که در فهرست سرآیندهای دربرگرفتهشده نیست دریافت یا حذف کنید، خطایی پرتاب نمیکنند. دریافت یک سرآیند ناموجود فقطNoneرا برمیگرداند و حذف یک سرآیند ناموجود هیچ کاری انجام نمیدهد.اشیای
Headersهمچنین از متدهایkeys()،values()وitems()پشتیبانی میکنند. فهرستهای برگرداندهشده توسطkeys()وitems()میتوانند در صورت وجود سرآیند چندمقداری، یک کلید یکسان را بیش از یک بار شامل شوند.len()یک شیءHeadersبرابر با طولitems()آن است، که خود برابر با طول فهرست سرآیند دربرگرفتهشده است. در واقع، متدitems()فقط یک کپی از فهرست سرآیند دربرگرفتهشده را برمیگرداند.فراخوانی
bytes()روی یک شیءHeadersیک رشتهبایت (bytestring) قالببندیشده مناسب برای انتقال بهعنوان سرآیندهای پاسخ HTTP را برمیگرداند. هر سرآیند همراه با مقدارش در یک خط قرار میگیرد؛ سرآیند و مقدار با یک دونقطه و یک فاصله از هم جدا میشوند. هر خط با یک بازگشت به ابتدای سطر (carriage return) و یک تغذیهی سطر (line feed) پایان مییابد و رشتهبایت با یک خط خالی پایان مییابد.علاوه بر رابط نگاشت و قابلیتهای قالببندی آنها، اشیاء
Headersهمچنین دارای متدهای زیر برای پرسوجو و افزودن سرآیندهای چندمقداری، و برای افزودن سرآیندها با پارامترهای MIME هستند:- get_all(name)¶
فهرستی از تمام مقدارهای سرآیند نامبردهشده را برمیگرداند.
فهرست برگرداندهشده به همان ترتیبی که در فهرست سرآیند اصلی ظاهر شدهاند یا به این نمونه افزوده شدهاند، مرتب خواهد شد و ممکن است شامل موارد تکراری باشد. هر فیلدی که حذف و دوباره درج شود، همیشه به فهرست سرآیند افزوده میشود. اگر هیچ فیلدی با نام دادهشده وجود نداشته باشد، یک فهرست خالی برمیگرداند.
- add_header(name, value, **_params)¶
یک سرآیند (احتمالاً چندمقداری) اضافه کنید، با پارامترهای MIME اختیاری که از طریق آرگومانهای کلیدواژهای مشخص میشوند.
name فیلد سرآیندی است که اضافه میشود. میتوان از آرگومانهای کلیدواژهای برای تنظیم پارامترهای MIME برای فیلد سرآیند استفاده کرد. هر پارامتر باید یک رشته یا
Noneباشد. زیرسطرها در نامهای پارامتر به خطتیره تبدیل میشوند، زیرا خطتیره در شناسههای پایتون غیرمجاز است، اما بسیاری از نامهای پارامتر MIME شامل خطتیره هستند. اگر مقدار پارامتر یک رشته باشد، به پارامترهای مقدار سرآیند در قالبname="value"اضافه میشود. اگرNoneباشد، فقط نام پارامتر اضافه میشود. (این برای پارامترهای MIME بدون مقدار استفاده میشود.) نمونه استفاده:h.add_header('content-disposition', 'attachment', filename='bud.gif')
مورد بالا سرآیندی اضافه میکند که به شکل زیر است:
Content-Disposition: attachment; filename="bud.gif"
تغییر یافته در نسخهی 3.5: پارامتر headers اختیاری است.
wsgiref.simple_server -- یک سرور HTTP ساده WSGI¶
این ماژول یک سرور HTTP ساده (بر پایهی http.server) پیادهسازی میکند که اپلیکیشنهای WSGI را سرویس میدهد. هر نمونه از سرور، یک اپلیکیشن WSGI واحد را روی یک میزبان و پورت مشخص سرویس میدهد. اگر میخواهید چندین اپلیکیشن را روی یک میزبان و پورت واحد سرویس دهید، باید یک اپلیکیشن WSGI بسازید که PATH_INFO را تجزیه کند تا انتخاب کند برای هر درخواست کدام اپلیکیشن فراخوانی شود. (برای مثال، با استفاده از تابع shift_path_info() از wsgiref.util.)
- wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)¶
یک سرور WSGI جدید ایجاد کنید که روی host و port گوش میدهد و اتصالات را برای app میپذیرد. مقدار بازگشتی، نمونهای از server_class ارائهشده است و درخواستها را با استفاده از handler_class مشخصشده پردازش میکند. app باید یک شیء برنامه WSGI باشد، همانطور که در PEP 3333 تعریف شده است.
نمونه استفاده:
from wsgiref.simple_server import make_server, demo_app with make_server('', 8000, demo_app) as httpd: print("Serving HTTP on port 8000...") # Respond to requests until process is killed httpd.serve_forever() # Alternative: serve one request, then exit httpd.handle_request()
- wsgiref.simple_server.demo_app(environ, start_response)¶
این تابع یک برنامهی WSGI کوچک اما کامل است که یک صفحهی متنی شامل پیام «Hello world!» و فهرستی از جفتهای کلید/مقدار ارائهشده در پارامتر environ را برمیگرداند. این تابع برای تأیید اینکه یک سرور WSGI (مانند
wsgiref.simple_server) میتواند یک برنامهی WSGI ساده را بهدرستی اجرا کند، مفید است.شیء فراخوانیپذیر start_response باید از پروتکل
StartResponseپیروی کند.
- class wsgiref.simple_server.WSGIServer(server_address, RequestHandlerClass)¶
یک نمونه از
WSGIServerایجاد کنید. server_address باید یک تاپل(host,port)باشد، و RequestHandlerClass باید زیرکلاسhttp.server.BaseHTTPRequestHandlerباشد که برای پردازش درخواستها استفاده خواهد شد.معمولاً نیازی نیست این سازنده را فراخوانی کنید، زیرا تابع
make_server()میتواند تمام جزئیات را برای شما مدیریت کند.WSGIServerیک زیرکلاس ازhttp.server.HTTPServerاست، بنابراین همهی متدهای آن (مانندserve_forever()وhandle_request()) در دسترس هستند.WSGIServerهمچنین این متدهای ویژهی WSGI را نیز ارائه میکند:- set_app(application)¶
فراخوانیپذیر application را بهعنوان برنامه WSGI که درخواستها را دریافت خواهد کرد، تنظیم میکند.
- get_app()¶
برنامهی فراخوانیپذیر تنظیمشدهی کنونی را برمیگرداند.
با این حال، معمولاً نیازی به استفاده از این متدهای اضافی ندارید، زیرا
set_app()معمولاً توسطmake_server()فراخوانی میشود وget_app()عمدتاً برای استفادهی نمونههای هندلر درخواست وجود دارد.
- class wsgiref.simple_server.WSGIRequestHandler(request, client_address, server)¶
یک مدیر HTTP (HTTP handler) برای request دادهشده (یعنی یک سوکت)، client_address (یک تاپل
(host,port)) و server (نمونهای ازWSGIServer) ایجاد کنید.شما نیازی به ایجاد مستقیم نمونههای این کلاس ندارید؛ آنها بهصورت خودکار در صورت نیاز توسط اشیای
WSGIServerایجاد میشوند. با این حال، میتوانید یک زیرکلاس از این کلاس بسازید و آن را بهعنوان handler_class به تابعmake_server()ارائه دهید. برخی متدهای احتمالاً مرتبط برای بازنویسی در زیرکلاسها:- get_environ()¶
یک دیکشنری
WSGIEnvironmentبرای یک درخواست برمیگرداند. پیادهسازی پیشفرض، محتوای ویژگی دیکشنریbase_environشیءWSGIServerرا کپی میکند و سپس سرآیندهای مختلفی را که از درخواست HTTP بهدست میآیند، اضافه میکند. هر فراخوانی این متد باید یک دیکشنری جدید حاوی تمام متغیرهای محیطی CGI مرتبط، همانطور که در PEP 3333 مشخص شده است، برگرداند.
- get_stderr()¶
شیءای را که باید بهعنوان جریان
wsgi.errorsاستفاده شود، برمیگرداند. پیادهسازی پیشفرض فقطsys.stderrرا برمیگرداند.
- handle()¶
درخواست HTTP را پردازش میکند. پیادهسازی پیشفرض، با استفاده از کلاسی از
wsgiref.handlers، نمونهای از هندلر ایجاد میکند تا رابط واقعی برنامهی WSGI را پیادهسازی کند.
wsgiref.validate --- بررسیکنندهی انطباق WSGI¶
هنگام ایجاد اشیاء برنامه WSGI، چارچوبها، سرورها یا میانافزارهای جدید، میتوانید انطباق کد جدید را با استفاده از wsgiref.validate اعتبارسنجی کنید. این ماژول تابعی فراهم میکند که اشیاء برنامه WSGI را ایجاد میکند؛ این اشیاء ارتباطات بین یک سرور یا درگاه WSGI و یک شیء برنامه WSGI را اعتبارسنجی میکنند تا انطباق هر دو طرف با پروتکل بررسی شود.
توجه داشته باشید که این ابزار انطباق کامل با PEP 3333 را تضمین نمیکند؛ نبود خطا از سوی این ماژول لزوماً به این معنا نیست که هیچ خطایی وجود ندارد. با این حال، اگر این ماژول خطایی تولید کند، عملاً قطعی است که یا سرور یا برنامه ۱۰۰٪ منطبق نیست.
این ماژول بر پایهی ماژول paste.lint از کتابخانهی «Python Paste» متعلق به Ian Bicking است.
- wsgiref.validate.validator(application)¶
application را در بر میگیرد و یک شیء برنامه WSGI جدید برمیگرداند. برنامه برگرداندهشده تمام درخواستها را به application اصلی هدایت میکند و بررسی میکند که هم application و هم سروری که آن را فراخوانی میکند، با مشخصات WSGI و RFC 2616 مطابقت دارند.
هرگونه عدم انطباق شناساییشده منجر به پرتاب
AssertionErrorمیشود؛ با این حال توجه داشته باشید که چگونگی مدیریت این خطاها وابسته به سرور است. برای مثال،wsgiref.simple_serverو سایر سرورهای مبتنی برwsgiref.handlers(که متدهای مدیریت خطا را برای انجام کار دیگری بازنویسی نمیکنند) صرفاً پیامی مبنی بر وقوع یک خطا را خروجی میدهند و ردگیری پشته را درsys.stderrیا جریان خطای دیگری مینویسند.این دربرگیرنده ممکن است همچنین با استفاده از ماژول
warningsخروجی تولید کند تا رفتارهایی را که پرسشبرانگیز هستند اما ممکن است در واقع در PEP 3333 ممنوع نشده باشند، نشان دهد. مگر اینکه این هشدارها با استفاده از گزینههای خط فرمان پایتون یا API ماژولwarningsمهار شوند، هر یک از این هشدارها درsys.stderrنوشته خواهند شد (نهwsgi.errors، مگر اینکه این دو اتفاقاً یک شیء باشند).نمونه استفاده:
from wsgiref.validate import validator from wsgiref.simple_server import make_server # Our callable object which is intentionally not compliant to the # standard, so the validator is going to break def simple_app(environ, start_response): status = '200 OK' # HTTP Status headers = [('Content-type', 'text/plain')] # HTTP Headers start_response(status, headers) # This is going to break because we need to return a list, and # the validator is going to inform us return b"Hello World" # This is the application wrapped in a validator validator_app = validator(simple_app) with make_server('', 8000, validator_app) as httpd: print("Listening on port 8000....") httpd.serve_forever()
wsgiref.handlers -- کلاسهای پایهی سرور/درگاه¶
این ماژول، کلاسهای پایهی هندلر را برای پیادهسازی سرورها و دروازههای WSGI فراهم میکند. این کلاسهای پایه، بیشتر کار ارتباط با یک برنامهی WSGI را انجام میدهند، مشروط بر اینکه محیطی شبهCGI به همراه جریانهای ورودی، خروجی و خطا به آنها داده شود.
- class wsgiref.handlers.CGIHandler¶
فراخوانی مبتنی بر CGI از طریق
sys.stdin،sys.stdout،sys.stderrوos.environ. این زمانی مفید است که یک برنامه WSGI دارید و میخواهید آن را بهعنوان یک اسکریپت CGI اجرا کنید. کافی استCGIHandler().run(app)را فراخوانی کنید، که در آنappشیء برنامه WSGI است که میخواهید فراخوانی شود.این کلاس، زیرکلاسی از
BaseCGIHandlerاست کهwsgi.run_onceرا روی درست،wsgi.multithreadرا روی نادرست وwsgi.multiprocessرا روی درست تنظیم میکند و همیشه برای به دست آوردن جریانها و محیط CGI مورد نیاز، ازsysوosاستفاده میکند.
- class wsgiref.handlers.IISCGIHandler¶
یک جایگزین تخصصی برای
CGIHandler، برای استفاده هنگام استقرار روی وبسرور IIS مایکروسافت، بدون اینکه گزینهی پیکربندی allowPathInfo (IIS>=7) یا metabase allowPathInfoForScriptMappings (IIS<7) تنظیم شده باشد.بهطور پیشفرض، IIS یک
PATH_INFOمیدهد که در ابتدای آنSCRIPT_NAMEرا تکرار میکند و برای برنامههای WSGI که مایل به پیادهسازی مسیریابی هستند، مشکل ایجاد میکند. این هندلر هرگونه مسیر تکراری از این دست را حذف میکند.میتوان IIS را بهگونهای پیکربندی کرد که
PATH_INFOدرست را ارسال کند، اما این کار سبب اشکال دیگری میشود که در آنPATH_TRANSLATEDنادرست است. خوشبختانه این متغیر بهندرت استفاده میشود و در WSGI تضمین نشده است. با این حال، در IIS<7، این تنظیم فقط میتواند در سطح میزبان مجازی (vhost) اعمال شود و بر تمام نگاشتهای اسکریپتی دیگر تأثیر میگذارد؛ بسیاری از آنها در صورت مواجهه با اشکالPATH_TRANSLATEDاز کار میافتند. به همین دلیل، IIS<7 تقریباً هرگز همراه با این اصلاحیه مستقر نمیشود (حتی IIS7 نیز بهندرت از آن استفاده میکند، زیرا هنوز هیچ رابط کاربری برای آن وجود ندارد.)هیچ راهی برای کد CGI وجود ندارد که تشخیص دهد گزینه تنظیم شده است یا نه، بنابراین یک کلاس هندلر جداگانه ارائه شده است. این کلاس به همان روش
CGIHandlerاستفاده میشود، یعنی با فراخوانیIISCGIHandler().run(app)، که در آنappشیء برنامه WSGI است که میخواهید فراخوانی کنید.اضافه شده در نسخهی 3.2.
- class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)¶
مشابه
CGIHandler، اما بهجای استفاده از ماژولهایsysوos، محیط CGI و جریانهای I/O بهصورت صریح مشخص میشوند. مقادیر multithread و multiprocess برای تنظیم پرچمهایwsgi.multithreadوwsgi.multiprocessبرای هر برنامهای که توسط نمونهی هندلر اجرا میشود، استفاده میشوند.این کلاس، زیرکلاسی از
SimpleHandlerاست که برای استفاده با نرمافزارهایی غیر از «سرورهای مبدأ HTTP» (origin servers) در نظر گرفته شده است. اگر در حال نوشتن پیادهسازی پروتکل دروازه (gateway protocol) هستید (مانند CGI، FastCGI، SCGI و غیره) که از سرآیندStatus:برای ارسال وضعیت HTTP استفاده میکند، احتمالاً میخواهید بهجایSimpleHandler، زیرکلاسی از این کلاس بسازید.
- class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)¶
مشابه
BaseCGIHandler، اما برای استفاده با سرورهای مبدأ HTTP طراحی شده است. اگر در حال نوشتن پیادهسازی یک سرور HTTP هستید، احتمالاً میخواهید بهجایBaseCGIHandler، از این کلاس یک زیرکلاس بسازید.این کلاس زیرکلاسی از
BaseHandlerاست. این کلاس متدهای__init__()،get_stdin()،get_stderr()،add_cgi_vars()،_write()و_flush()را بازنویسی میکند تا از تنظیم صریح محیط و جریانها از طریق سازنده پشتیبانی کند. محیط و جریانهای ارائهشده در ویژگیهایstdin،stdout،stderrوenvironذخیره میشوند.متد
write()مربوط به stdout باید هر تکه (chunk) را بهطور کامل بنویسد، مانندio.BufferedIOBase.
- class wsgiref.handlers.BaseHandler¶
این یک کلاس پایه انتزاعی برای اجرای برنامههای WSGI است. هر نمونه یک درخواست HTTP واحد را مدیریت خواهد کرد، هرچند در اصل میتوانید زیرکلاسی ایجاد کنید که برای چندین درخواست قابل استفاده مجدد باشد.
نمونههای
BaseHandlerتنها یک متد برای استفاده بیرونی دارند:- run(app)¶
برنامه WSGI مشخصشده، app را اجرا کنید.
تمامی متدهای دیگر
BaseHandlerتوسط این متد در فرایند اجرای برنامه فراخوانی میشوند، و بنابراین عمدتاً وجود دارند تا امکان سفارشیسازی این فرایند را فراهم کنند.متدهای زیر باید در یک زیرکلاس بازنویسی شوند:
- _write(data)¶
بایتهای data را برای ارسال به کلاینت در بافر قرار دهید. اگر این متد واقعاً دادهها را ارسال کند، اشکالی ندارد؛
BaseHandlerفقط عملیات نوشتن و تخلیه را برای کارایی بیشتر هنگامی که سیستم زیربنایی واقعاً چنین تمایزی دارد، از هم جدا میکند.
- _flush()¶
دادههای بافرشده را بهاجبار به کلاینت ارسال میکند. اشکالی ندارد اگر این متد عملیات بیاثر (no-op) باشد (یعنی اگر
_write()در واقع دادهها را ارسال میکند).
- get_stdin()¶
یک شیء سازگار با
InputStreamبرمیگرداند که برای استفاده بهعنوانwsgi.inputدرخواستی که هماکنون در حال پردازش است، مناسب است.
- get_stderr()¶
یک شیء سازگار با
ErrorStreamرا برمیگرداند که برای استفاده بهعنوانwsgi.errorsدرخواستی که در حال پردازش است مناسب است.
- add_cgi_vars()¶
متغیرهای CGI برای درخواست جاری را در ویژگی
environدرج میکند.
در اینجا چند متد و ویژگی دیگر آمده است که ممکن است بخواهید آنها را بازنویسی کنید. البته این فهرست تنها یک خلاصه است و شامل همهی متدهایی که میتوان آنها را بازنویسی کرد نمیشود. پیش از اقدام برای ایجاد یک زیرکلاس سفارشیشده از
BaseHandler، برای اطلاعات بیشتر به رشتههای مستند و کد منبع مراجعه کنید.ویژگیها و متدها برای سفارشیسازی محیط WSGI:
- wsgi_multithread¶
مقداری که برای متغیر محیطی
wsgi.multithreadاستفاده میشود. مقدار پیشفرض آن درBaseHandlerبرابر true است، اما ممکن است در سایر زیرکلاسها پیشفرض متفاوتی داشته باشد (یا توسط سازنده تنظیم شود).
- wsgi_multiprocess¶
مقدار مورد استفاده برای متغیر محیطی
wsgi.multiprocess. مقدار پیشفرض آن درBaseHandlerبرابر true است، اما ممکن است در زیرکلاسهای دیگر پیشفرض متفاوتی داشته باشد (یا توسط سازنده تنظیم شود).
- wsgi_run_once¶
مقداری که برای متغیر محیطی
wsgi.run_onceاستفاده میشود. مقدار پیشفرض آن درBaseHandlerبرابر false است، اماCGIHandlerآن را بهطور پیشفرض روی true تنظیم میکند.
- os_environ¶
متغیرهای محیطی پیشفرض که باید در محیط WSGI هر درخواست گنجانده شوند. بهطور پیشفرض، این یک نسخه از
os.environدر زمانی است کهwsgiref.handlersایمپورت شد، اما زیرکلاسها میتوانند نسخهی خود را در سطح کلاس یا نمونه ایجاد کنند. توجه داشته باشید که دیکشنری باید فقطخواندنی در نظر گرفته شود، زیرا مقدار پیشفرض بین چندین کلاس و نمونه مشترک است.
- server_software¶
اگر ویژگی
origin_serverتنظیم شده باشد، از مقدار این ویژگی برای تنظیم مقدار پیشفرض متغیر محیطیSERVER_SOFTWAREدر WSGI و نیز تنظیم یک سرآیند پیشفرضServer:در پاسخهای HTTP استفاده میشود. این مقدار برای هندلرهایی (مانندBaseCGIHandlerوCGIHandler) که سرورهای مبدأ HTTP نیستند، نادیده گرفته میشود.تغییر یافته در نسخهی 3.3: اصطلاح «Python» با اصطلاح خاص پیادهسازی مانند «CPython»، «Jython» و غیره جایگزین میشود.
- get_scheme()¶
طرحواره URL مورد استفاده برای درخواست جاری را برمیگرداند. پیادهسازی پیشفرض از تابع
guess_scheme()درwsgiref.utilاستفاده میکند تا بر اساس متغیرهایenvironدرخواست جاری حدس بزند که طرحواره باید "http" یا "https" باشد.
- setup_environ()¶
ویژگی
environرا روی یک محیط WSGI کاملاً مقداردهیشده تنظیم کنید. پیادهسازی پیشفرض از تمام متدها و ویژگیهای بالا، بههمراه متدهایget_stdin()،get_stderr()وadd_cgi_vars()و ویژگیwsgi_file_wrapperاستفاده میکند. همچنین اگر کلیدSERVER_SOFTWAREوجود نداشته باشد، مشروط بر اینکه ویژگیorigin_serverمقدار درست داشته باشد و ویژگیserver_softwareتنظیمشده باشد، آن را درج میکند.
متدها و ویژگیها برای سفارشیسازی مدیریت استثنا:
- log_exception(exc_info)¶
تاپل exc_info را در گزارش سرور ثبت کنید. exc_info یک تاپل
(type, value, traceback)است. پیادهسازی پیشفرض بهسادگی ردگیری پشته را در جریانwsgi.errorsدرخواست مینویسد و آن را تخلیه میکند. زیرکلاسها میتوانند این متد را بازنویسی کنند تا قالب را تغییر دهند، خروجی را به مقصد دیگری هدایت کنند، ردگیری پشته را با ایمیل برای مدیر ارسال کنند، یا هر اقدام دیگری که مناسب تشخیص داده شود انجام دهند.
- traceback_limit¶
حداکثر تعداد فریمها برای درج در ردگیریهای پشتهی خروجیدادهشده توسط متد پیشفرض
log_exception(). اگرNoneباشد، تمام فریمها درج میشوند.
- error_output(environ, start_response)¶
این متد یک برنامهی WSGI برای تولید صفحهی خطا برای کاربر است. این متد تنها در صورتی فراخوانی میشود که خطایی پیش از ارسال سرآیندها به کلاینت رخ دهد.
این متد میتواند با استفاده از
sys.exception()به خطای جاری دسترسی پیدا کند و باید هنگام فراخوانی آن، آن اطلاعات را به start_response منتقل کند (همانطور که در بخش «Error Handling» از PEP 3333 توضیح داده شده است). بهویژه، فراخوانیپذیر start_response باید از پروتکلStartResponseپیروی کند.پیادهسازی پیشفرض فقط از ویژگیهای
error_status،error_headersوerror_bodyبرای تولید یک صفحه خروجی استفاده میکند. زیرکلاسها میتوانند این را بازنویسی کنند تا خروجی خطای پویاتری تولید کنند.با این حال، توجه داشته باشید که از دیدگاه امنیتی توصیه نمیشود پیامهای تشخیصی را در اختیار هر کاربری قرار دهید؛ در حالت ایدهآل، باید برای فعال کردن خروجی تشخیصی کار خاصی انجام دهید، به همین دلیل پیادهسازی پیشفرض شامل هیچ خروجی تشخیصی نیست.
- error_status¶
وضعیت HTTP مورد استفاده برای پاسخهای خطا. این باید یک رشته وضعیت، مطابق تعریف PEP 3333 باشد؛ مقدار پیشفرض آن یک کد و پیام ۵۰۰ است.
- error_headers¶
سرآیندهای HTTP مورد استفاده برای پاسخهای خطا. این باید فهرستی از سرآیندهای پاسخ WSGI (تاپلهای
(name, value)) باشد، همانطور که در PEP 3333 توضیح داده شده است. فهرست پیشفرض فقط نوع محتوا را رویtext/plainتنظیم میکند.
- error_body¶
بدنهی پاسخ خطا. این باید یک رشتهبایت (bytestring) برای بدنهی پاسخ HTTP باشد. مقدار پیشفرض آن متن سادهی «خطای سرور رخ داد. لطفاً با مدیر تماس بگیرید.» است.
متدها و ویژگیهای مربوط به قابلیت «مدیریت اختیاری پرونده وابسته به سکو» در PEP 3333:
- wsgi_file_wrapper¶
یک کارخانه
wsgi.file_wrapper، سازگار باwsgiref.types.FileWrapper، یاNone. مقدار پیشفرض این ویژگی، کلاسwsgiref.util.FileWrapperاست.
- sendfile()¶
برای پیادهسازی انتقال پرونده مختص پلتفرم، این متد را بازنویسی کنید. این متد تنها زمانی فراخوانی میشود که مقدار بازگشتی برنامه، نمونهای از کلاسی باشد که توسط ویژگی
wsgi_file_wrapperمشخص شده است. این متد باید در صورتی که بتواند پرونده را با موفقیت منتقل کند، مقداری درست برگرداند تا کد انتقال پیشفرض اجرا نشود. پیادهسازی پیشفرض این متد فقط مقداری نادرست برمیگرداند.
متدها و ویژگیهای متفرقه:
- origin_server¶
این ویژگی باید به یک مقدار درست تنظیم شود اگر از
_write()و_flush()هندلر برای برقراری ارتباط مستقیم با کلاینت استفاده میشود، نه از طریق یک پروتکل دروازهای مشابه CGI که وضعیت HTTP را در یک سرآیندStatus:خاص میخواهد.مقدار پیشفرض این ویژگی در
BaseHandlerبرابر با درست است، اما درBaseCGIHandlerوCGIHandlerبرابر با نادرست است.
- http_version¶
اگر
origin_serverدرست باشد، این ویژگی رشتهای برای تنظیم نسخه HTTP پاسخ ارسالشده به کلاینت استفاده میشود. مقدار پیشفرض آن"1.0"است.
- wsgiref.handlers.read_environ()¶
متغیرهای CGI را از
os.environبه رشتههای «bytes in unicode» مطابق PEP 3333 بازکدگذاری (transcode) میکند و یک دیکشنری جدید برمیگرداند. این تابع توسطCGIHandlerوIISCGIHandlerبهجای استفادهی مستقیم ازos.environاستفاده میشود، که لزوماً در همهی پلتفرمها و وبسرورهایی که از Python 3 استفاده میکنند با WSGI سازگار نیست؛ بهویژه آنهایی که محیط واقعی سیستمعامل آنها یونیکد است (یعنی Windows)، یا آنهایی که محیط بهصورت بایت است، اما کدگذاری سیستمی که پایتون برای کدگشایی آن استفاده میکند چیزی غیر از ISO-8859-1 است (مثلاً سیستمهای Unix که از UTF-8 استفاده میکنند).اگر در حال پیادهسازی یک هندلر مبتنی بر CGI خودتان هستید، احتمالاً میخواهید بهجای کپی کردن مستقیم مقادیر از
os.environ، از این روال استفاده کنید.اضافه شده در نسخهی 3.2.
wsgiref.types -- انواع WSGI برای بررسی ایستای نوع¶
این ماژول انواع مختلفی را برای بررسی ایستای نوع فراهم میکند، همانطور که در PEP 3333 توضیح داده شده است.
اضافه شده در نسخهی 3.11.
- class wsgiref.types.StartResponse¶
یک
typing.Protocolکه فراخوانیپذیرهای start_response() را توصیف میکند (PEP 3333).
- wsgiref.types.WSGIEnvironment¶
یک نام مستعار نوع که دیکشنری محیط WSGI را توصیف میکند.
- wsgiref.types.WSGIApplication¶
یک ناممستعار نوع که یک شیء فراخوانیپذیر برنامه WSGI را توصیف میکند.
- class wsgiref.types.InputStream¶
یک
typing.Protocolکه یک WSGI Input Stream را توصیف میکند.
- class wsgiref.types.ErrorStream¶
یک
typing.Protocolکه WSGI Error Stream را توصیف میکند.
- class wsgiref.types.FileWrapper¶
یک
typing.Protocolکه یک دربرگیرندهی پرونده را توصیف میکند. برای یک پیادهسازی عینی از این پروتکل،wsgiref.util.FileWrapperرا ببینید.
مثالها¶
این یک برنامه کاربردی WSGI «Hello World» قابلاجرا است، که در آن شیء فراخوانیپذیر start_response باید از پروتکل StartResponse پیروی کند:
"""
Every WSGI application must have an application object - a callable
object that accepts two arguments. For that purpose, we're going to
use a function (note that you're not limited to a function, you can
use a class for example). The first argument passed to the function
is a dictionary containing CGI-style environment variables and the
second variable is the callable object.
"""
from wsgiref.simple_server import make_server
def hello_world_app(environ, start_response):
status = "200 OK" # HTTP Status
headers = [("Content-type", "text/plain; charset=utf-8")] # HTTP Headers
start_response(status, headers)
# The returned object is going to be printed
return [b"Hello World"]
with make_server("", 8000, hello_world_app) as httpd:
print("Serving on port 8000...")
# Serve until process is killed
httpd.serve_forever()
مثالی از یک برنامهی WSGI که پوشهی جاری را سرو میکند و پوشه و شمارهی پورت را بهصورت اختیاری از خط فرمان میپذیرد (پیشفرض: ۸۰۰۰):
"""
Small wsgiref based web server. Takes a path to serve from and an
optional port number (defaults to 8000), then tries to serve files.
MIME types are guessed from the file names, 404 errors are raised
if the file is not found.
"""
import mimetypes
import os
import sys
from wsgiref import simple_server, util
def app(environ, respond):
# Get the file name and MIME type
fn = os.path.join(path, environ["PATH_INFO"][1:])
if "." not in fn.split(os.path.sep)[-1]:
fn = os.path.join(fn, "index.html")
mime_type = mimetypes.guess_file_type(fn)[0]
# Return 200 OK if file exists, otherwise 404 Not Found
if os.path.exists(fn):
respond("200 OK", [("Content-Type", mime_type)])
return util.FileWrapper(open(fn, "rb"))
else:
respond("404 Not Found", [("Content-Type", "text/plain")])
return [b"not found"]
if __name__ == "__main__":
# Get the path and port from command-line arguments
path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000
# Make and start the server until control-c
httpd = simple_server.make_server("", port, app)
print(f"Serving {path} on port {port}, control-C to stop")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("Shutting down.")
httpd.server_close()