یه API خوب فقط وقتی ارزش داره که در زمان خطا هم رفتار قابل‌فهمی داشته باشه. اگه کاربر شناسه محصولی رو بفرسته که وجود نداره، Token اشتباه داشته باشه یا داده نامعتبر ارسال کنه، نباید همیشه یه پاسخ عادی با وضعیت موفق دریافت کنه؛ چون در این حالت فرانت‌اند نمی‌فهمه درخواست واقعاً موفق بوده یا نه و مجبور میشه از روی متن پاسخ حدس بزنه چه اتفاقی افتاده.

برای همین در HTTP یه عدد استاندارد همراه پاسخ ارسال میشه که وضعیت نتیجه رو مشخص میکنه. به این عدد کد وضعیت پاسخ گفته میشه که اصطلاح انگلیسی اون Status Code هست. FastAPI هم ابزار آماده‌ای به اسم HTTPException داره که با استفاده از اون میشه خطا رو با Status Code مناسب و پیام واضح برگردوند.

Status Code در FastAPI چه کاربردی دارد؟

وقتی یه Request به API میرسه، سرور علاوه بر داده، وضعیت نتیجه رو هم برمیگردونه. مثلاً عدد 200 یعنی درخواست با موفقیت انجام شده، 404 یعنی چیزی که درخواست شده پیدا نشده و 401 یا 403 معمولاً به مشکلات مربوط به احراز هویت یا سطح دسترسی اشاره دارن.

این عدد برای فرانت‌اند خیلی مهمه، چون لازم نیست متن Response رو بررسی کنه تا بفهمه درخواست موفق بوده یا نه. فقط با Status Code میتونه تصمیم بگیره پیام موفقیت نشون بده، کاربر رو به صفحه Login بفرسته یا یه Error مناسب نمایش بده.

چرا نباید برای همه خطاها 200 برگردانیم؟

یه اشتباه رایج تو پروژه‌های مبتدی اینه که حتی وقتی عملیات Fail شده، همچنان پاسخ با 200 برگرده و فقط داخل JSON چیزی مثل "success": false قرار بگیره.

این روش شاید در ابتدا ساده به نظر برسه، ولی قرارداد HTTP رو خراب میکنه. از نگاه Client، درخواست موفق بوده، در حالی که منطق برنامه میگه خطا اتفاق افتاده.

بهتره وضعیت Response واقعاً با نتیجه عملیات هماهنگ باشه. اگه رکورد وجود نداره 404 برگرده، اگه درخواست از نظر داده مشکل داره 400 مناسب‌تره و اگه کاربر اجازه دسترسی نداره باید کد مناسب مربوط به دسترسی ارسال بشه.

HTTPException در FastAPI چیست؟

FastAPI برای قطع کردن اجرای Endpoint و برگردوندن یه خطای HTTP ابزار آماده‌ای داره که با اسم HTTPException شناخته میشه.

با این ابزار میتونیم هم Status Code رو مشخص کنیم و هم یه پیام قابل‌فهم برای Client بفرستیم. مثلاً اگه کاربر محصولی رو درخواست کنه که وجود نداره، لازم نیست Response رو دستی بسازیم؛ میتونیم مستقیم Exception مناسب ایجاد کنیم.

from fastapi import FastAPI, HTTPException

app = FastAPI()

products = {
    1: {"name": "Laptop"},
    2: {"name": "Mouse"}
}


@app.get("/products/{product_id}")
async def get_product(product_id: int):
    product = products.get(product_id)

    if product is None:
        raise HTTPException(
            status_code=404,
            detail="Product not found"
        )

    return product

اینجا اگه محصول وجود داشته باشه، همون داده برگردونده میشه؛ ولی اگه شناسه پیدا نشه، اجرای Endpoint متوقف میشه و FastAPI پاسخ 404 همراه با پیام خطا ارسال میکنه.

فرق 400، 401، 403 و 404 چیست؟

این چهار کد خیلی زیاد استفاده میشن و تفاوتشون مهمه. خطای 400 معمولاً یعنی خود Request از نظر ساختار یا منطق قابل قبول نیست. مثلاً کاربر مقدار غیرمجاز یا ترکیب اشتباهی از داده‌ها فرستاده.

کد 401 بیشتر زمانی استفاده میشه که کاربر هنوز به شکل معتبر احراز هویت نشده؛ مثلاً Token وجود نداره یا معتبر نیست. کد 403 زمانی کاربرد داره که هویت کاربر مشخصه، ولی اجازه انجام اون عملیات رو نداره.

کد 404 هم یعنی Resource موردنظر پیدا نشده؛ مثلاً محصول، کاربر یا سفارشی با شناسه‌ای که ارسال شده وجود نداره.

انتخاب درست این کدها باعث میشه API قابل پیش‌بینی‌تر و استانداردتر باشه.

پیام خطا باید چه شکلی باشد؟

Status Code مشخص میکنه چه نوع خطایی اتفاق افتاده، ولی معمولاً بهتره یه پیام قابل‌فهم هم داخل Response وجود داشته باشه تا Client بدونه مشکل دقیق‌تر چیه.

در HTTPException این پیام با پارامتر detail مشخص میشه.

پیام بهتره کوتاه، واضح و مناسب Client باشه. لازم نیست Traceback، مسیر فایل یا اطلاعات داخلی سرور رو داخل Error Response قرار بدید، چون این جزئیات برای کاربر نهایی کاربردی نیستن و ممکنه اطلاعات غیرضروری از ساختار پروژه رو آشکار کنن.

خطای قابل انتظار با باگ برنامه یکی نیست

هر Errorای نباید با HTTPException مدیریت بشه. اگه کاربر محصولی رو درخواست کرده که وجود نداره، این یه حالت قابل انتظار از رفتار API هست و 404 منطقیه.

اما اگه داخل کد یه خطای برنامه‌نویسی رخ داده، مثلاً متغیر اشتباه استفاده شده یا سرویس داخلی Crash کرده، نباید فقط برای پنهان کردن مشکل اون رو به یه 400 یا 404 تبدیل کنیم.

خطاهای قابل انتظار باید پاسخ مشخص داشته باشن، ولی باگ‌های واقعی باید ثبت و بررسی بشن تا توسعه‌دهنده علت اصلی رو پیدا کنه.

آیا همیشه باید متن خطا را یکسان برگردانیم؟

برای پروژه‌های کوچک، detail ساده کاملاً کافیه. ولی وقتی API بزرگ‌تر میشه، بهتره ساختار خطاها یکدست باشه تا فرانت‌اند مجبور نباشه برای هر Endpoint یه شکل متفاوت از Response رو مدیریت کنه.

مثلاً میشه یه ساختار ثابت برای خطاها داشت که شامل کد داخلی، پیام و در صورت نیاز جزئیات بیشتر باشه. این کار مخصوصاً وقتی چند Client مختلف مثل وب، موبایل و سرویس‌های دیگه از یه API استفاده میکنن خیلی مفیده.

اشتباه رایج: except کلی برای همه چیز

گاهی برای اینکه API هیچ وقت Crash نکنه، کل Endpoint داخل یه try/except بزرگ قرار میگیره و هر Exceptionای به یه پاسخ عمومی تبدیل میشه.

این کار معمولاً باعث میشه باگ واقعی پنهان بشه و دیباگ کردن پروژه سخت‌تر بشه. بهتره فقط خطاهایی رو مدیریت کنید که واقعاً انتظارشون رو دارید و بقیه خطاها اجازه داشته باشن وارد سیستم Logging و Error Monitoring بشن.

مدیریت خطا یعنی رفتار کنترل‌شده، نه مخفی کردن همه مشکلات.

جمع‌بندی

مدیریت خطا در FastAPI فقط برگردوندن یه متن قرمز نیست؛ Status Code بخشی از قرارداد API محسوب میشه و باید وضعیت واقعی Request رو نشون بده. HTTPException کمک میکنه خطاهای قابل انتظار رو با کد مناسب و پیام واضح برگردونید و فرانت‌اند هم راحت‌تر بتونه تصمیم بگیره چه واکنشی نشون بده.

برای درخواست نامعتبر معمولاً 400، برای مشکل احراز هویت 401، برای نداشتن دسترسی 403 و برای پیدا نشدن Resource کد 404 استفاده میشه. مهم‌تر از حفظ کردن این اعداد اینه که Response واقعاً نتیجه عملیات رو درست توصیف کنه.