ویژگی تصویر

معرفی کلی: کتابخانه http.server در پایتون

  /  پایتون   /  کتابخانه http.server در پایتون
بنر تبلیغاتی الف

کتابخانهٔ استاندارد http.server در پایتون یک ابزار ساده و سبک برای راه‌اندازی سرور HTTP محلی است. این ماژول برای توسعه، تست و آموزش بسیار مناسب است ولی نباید آن را در محیط‌های تولیدی با ترافیک بالا یا نیازمندی‌های امنیتی جدی به‌کار برد. در ادامه ساختار، کلاس‌ها، مثال‌های کاربردی و نکات امنیتی و بهینه‌سازی را بررسی می‌کنیم.

کلاس‌ها و اجزای مهم

چند کلاس و سازوکار اصلی در این ماژول وجود دارد که باید آنها را شناخت:

  • BaseHTTPRequestHandler: کلاس پایه برای پیاده‌سازی هندلرهای HTTP (GET, POST، و …).
  • SimpleHTTPRequestHandler: هندلری برای سرو فایل‌های محلی و نمایش دایرکتوریها.
  • CGIHTTPRequestHandler: برای اجرای اسکریپت‌های CGI (مانند Python CGI).
  • HTTPServer: سرور تک‌نخی ساده بر پایه socketserver.
  • ThreadingHTTPServer: نسخه‌ای که برای هر درخواست یک نخ جدا می‌سازد (مناسب برای توسعه).

مقایسهٔ سریع

کلاسکاربردمحدودیت
SimpleHTTPRequestHandlerسرو فایل‌های محلی و لیست کردن دایرکتوریامنیت محدود؛ مناسب تست محلی
CGIHTTPRequestHandlerاجرای اسکریپت‌های CGIپیچیدگی و مسائل امنیتی
ThreadingHTTPServerپاسخگویی همزمان بهتر در محیط توسعهنیاز به مدیریت همزمانی در اپلیکیشن

مثال پایه: راه‌اندازی سرور فایل با دستور آماده

python -m http.server 8000

این دستور در دایرکتوری جاری یک سرور HTTP روی پورت 8000 اجرا می‌کند و فایل‌ها را سرو می‌نماید. برای پایتون 2 معادل آن SimpleHTTPServer بود، اما در پایتون 3 از http.server استفاده می‌شود.

نمونهٔ کد: پیاده‌سازی ساده با Python

from http.server import HTTPServer, SimpleHTTPRequestHandler

PORT = 8000
Handler = SimpleHTTPRequestHandler

with HTTPServer(("", PORT), Handler) as httpd:
    print(f"Serving on port {PORT}")
    httpd.serve_forever()

در این کد یک سرور ساده روی همهٔ اینترفیس‌ها و پورت 8000 ایجاد می‌شود و از SimpleHTTPRequestHandler برای سرو فایل‌ها استفاده می‌گردد. serve_forever حلقهٔ اصلی را اجرا می‌کند تا درخواست‌ها پردازش شوند.

نوشتن هندلر سفارشی

برای کنترل دقیق‌تر روی پاسخ‌ها می‌توان BaseHTTPRequestHandler یا SimpleHTTPRequestHandler را ارث‌بری کرد و متدهای do_GET، do_POST و … را پیاده‌سازی نمود.

from http.server import HTTPServer, BaseHTTPRequestHandler
import json

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == "/api/hello":
            data = {"message": "سلام از سرور پایتون"}
            body = json.dumps(data).encode("utf-8")
            self.send_response(200)
            self.send_header("Content-Type", "application/json; charset=utf-8")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
        else:
            self.send_response(404)
            self.end_headers()

if __name__ == "__main__":
    server = HTTPServer(("127.0.0.1", 8080), MyHandler)
    print("Listening on 127.0.0.1:8080")
    server.serve_forever()

توضیح: این هندلر برای مسیر /api/hello یک پاسخ JSON برمی‌گرداند. از send_response، send_header و end_headers برای تنظیم هدرها استفاده شده و wfile برای نوشتن بدنه استفاده می‌شود. اگر مسیر متفاوت باشد، 404 باز می‌گرداند.

بهبود: استفاده از ThreadingHTTPServer

from http.server import ThreadingHTTPServer

server = ThreadingHTTPServer(("127.0.0.1", 8080), MyHandler)
server.serve_forever()

توضیح: به‌جای HTTPServer از ThreadingHTTPServer استفاده کنید تا هر درخواست در نخ جداگانه اجرا شود. این کار در توسعه مفید است اما برای تولید باید به مدیریت منابع و شرایط رقابتی دقت کنید.

ملاحظات امنیتی و محدودیت‌ها

  • http.server برای محیط تولید مناسب نیست—هیچ مکانیزم محافظتی مقابل حملات، محدودسازی نرخ یا احراز هویت ندارد.
  • SimpleHTTPRequestHandler ممکن است در برابر حملات directory traversal آسیب‌پذیر باشد اگر از مسیرهای غیرایمن استفاده شود؛ قبل از سرو فایل مسیر را به‌درستی نرمالیزه کنید.
  • برای HTTPS باید سوکت را با SSL ببندید (مثال در ادامه).

نمونه: فعال‌سازی HTTPS (غیرتولیدی)

import ssl
from http.server import HTTPServer, SimpleHTTPRequestHandler

httpd = HTTPServer(('0.0.0.0', 4443), SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket,
                               certfile='server.pem',
                               server_side=True)
httpd.serve_forever()

توضیح: این روش سوکت سرور را با ssl.wrap_socket می‌پوشاند تا ارتباطات رمزنگاری شوند. برای تست محلی بد است اما برای استفادهٔ واقعی باید از کتابخانه‌های حرفه‌ای‌تر مانند aiohttp، uvicorn/fastapi یا Gunicorn+TLS و گواهی‌های معتبر استفاده کرد.

نکات پیشرفته و بهترین تمرین‌ها

  • در صورت نیاز به عملکرد بالا از سرورهای تولیدی (nginx, Apache, uvicorn) استفاده کنید و http.server را به‌عنوان ابزار تست نگه دارید.
  • برای اجرای کدهای CGI از CGIHTTPRequestHandler استفاده کنید اما مراقب امنیت ورودی‌ها باشید.
  • در صورت سرو فایل‌ها، محدودیت دسترسی به دایرکتوری مشخص را اعمال کنید و از os.path.realpath برای جلوگیری از دسترسی ناخواسته بهره ببرید.
  • برای لاگینگ و مانیتورینگ از logging استاندارد پایتون استفاده کنید؛ BaseHTTPRequestHandler به‌طور پیش‌فرض اطلاعات مختصری لاگ می‌کند که می‌توان آن را بازتعریف کرد.

مثال ایمن‌تر برای ترجمه مسیرها

import os
from http.server import SimpleHTTPRequestHandler

class SafeHandler(SimpleHTTPRequestHandler):
    def translate_path(self, path):
        # مسیر پایه (DocumentRoot)
        base = os.path.abspath("/var/www/myapp")
        # مسیر درخواست‌شده را نرمالیزه کن
        requested = os.path.normpath(os.path.join(base, path.lstrip("/")))
        # اگر مسیر خارج از base باشد، برگردان پایه
        if not requested.startswith(base):
            return base
        return requested

توضیح: با بازنویسی translate_path مسیرهای درخواستی را نرمالیزه و به دایرکتوری ریشه محدود می‌کنیم تا از directory traversal جلوگیری شود. این روش سطح ایمنی را بالا می‌برد ولی باز هم برای محیط تولید باید از راهکارهای قوی‌تر استفاده کنید.

جمع‌بندی

کتابخانهٔ http.server ابزار قدرتمندی برای توسعه و تست محلی است: ساده، بدون پیکربندی پیچیده و با قابلیت گسترش. با این حال محدودیت‌های عملکردی و امنیتی دارد و نباید به‌عنوان جایگزین سرورهای تولیدی در نظر گرفته شود. با رعایت نکات ایمنی، استفاده از ThreadingHTTPServer در محیط‌های توسعه و انتقال بار به سرورهای پروکسی یا فریم‌ورک‌های حرفه‌ای می‌توانید از http.server به‌طور مفید بهره ببرید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: