چرا fetch به کد خطا احتیاج داره
خلاصهٔ کاملتر
نویسنده تو ادامهٔ پست قبلیش دربارهٔ کمبودهای Fetch API، این بار سراغ یه شکاف مشخص رفته: ریست شدن استریم با نوع مشخص. طبق اسپک، هر خطای سطح شبکه باید پرامیس رو با یه TypeError عمومی رد کنه. خطای DNS، دستدادن ناموفق TLS، رد شدن اتصال، ریست استریم توسط سرور و حلقهٔ ریدایرکت — همه یک خروجی یکسان دارن و اطلاعات تشخیصی عمداً نابود میشه.
به گفتهٔ نویسنده این کوری تو مرورگر یه ویژگی امنیتی لازمه: اگه شکست یه درخواست cross-origin دلیلشو لو میداد، میشد زیرساخت مقصد رو کاوش کرد — که آیا هاست resolve میشه، TLS تنظیم شده یا فلان پورت بازه. برای مدل تهدید مرورگر، پنهان کردن جزئیات معمولاً رفتار درستیه.
ولی HTTP/2 و HTTP/3 سیگنالدهی خطاشون خیلی فراتر از «یه چیزی خراب شد» میره. سرور موقع ریست کردن یه استریم HTTP/2 فریم RST_STREAM میفرسته که یه کد خطای ۳۲ بیتی همراهشه، و HTTP/3 دو مکانیزم مستقل RESET_STREAM و STOP_SENDING داره. RFC 9113 صراحتاً میگه REFUSED_STREAM یعنی سرور اصلاً درخواست رو پردازش نکرده، پس کلاینت میتونه حتی متدهای غیرidempotent رو هم با خیال راحت دوباره بفرسته.
همین تضمینِ امنبودن retry چیزیه که Fetch نابودش میکنه، چون آخرش یه TypeError دست شما میرسه که با خطای DNS فرقی نداره. سه سیگنال معنادار دیگه هم همین سرنوشتو دارن: CANCEL که ممکنه درخواست تا حدی پردازش شده باشه، NO_ERROR برای بسته شدن تمیز، و INTERNAL_ERROR برای خرابی سمت سرور.
راهحل پیشنهادی نویسنده یه پروپوزال تو TC39 هست که یه ویژگی استاندارد code به آبجکتهای Error اضافه میکنه، دقیقاً از همون کیسهٔ آپشن سازنده که cause تو ES2022 بهش اضافه شد. پروپوزال فعلاً تو Stage 1 قرار داره و قراره برای Stage 2.7 بررسی بشه. اکوسیستم عملاً این الگو رو پذیرفته: نود از ۲۰۱۷ بیش از ۲۰۰ کد ERR_* داره و Deno، Bun، axios، Stripe و Prisma هم .code روی خطاهاشون میذارن.
سمت Fetch، طرح اینه که یه فیلد داخلی «کد خطای شبکه» به مفهوم network error اضافه بشه و موقع رسیدن به مرز API به .code روی همون TypeError تبدیل بشه. کدی که این ویژگی رو چک نکنه اصلاً تحت تأثیر قرار نمیگیره. تاکسونومی هم عمداً کوچیک شروع میشه: چهار کد سطح-استریم بیشترین ارزش رو دارن و یکیشون همون قفل retry امن رو باز میکنه.
بخش امنیتی ماجرا هم دیده شده: کدهای سطح-استریم امنن چون بعد از برقراری اتصال و به انتخاب خود سرور فرستاده شدن، ولی کدهای پیشاز-اتصال مثل خطای DNS یا TLS باید تو درخواستهای cross-origin حذف بشن. رانتایمهای سمت سرور که مدل تهدید CORS رو ندارن میتونن کلاً از این بررسی رد شن. همین کد روی استریم بدنهٔ پاسخ هم به کار میآد، جایی که خطا بعد از رسیدن هدرها اتفاق میافته.
نکات کلیدی:
- اسپک Fetch هر خطای شبکه رو به یه TypeError بدون کد و دلیل تبدیل میکنه
- کدهای RST_STREAM و معادلهای HTTP/3 معنای عملی دارن، مخصوصاً «پردازش نشد، دوباره بفرست»
- پروپوزال TC39 یه ویژگی code به سازندهٔ Error اضافه میکنه، سازگار با کد قدیمی
- تاکسونومی پیشنهادی با چهار کد سطح-استریم شروع میشه و بعداً رشد میکنه
- کدهای پیشاز-اتصال برای جلوگیری از نشت اطلاعات باید تو مرورگر و cross-origin پنهون بمونن




