خطای remote server returned an error

خطای remote server returned an error

حدود ۵ دقیقه مطالعه

پیام «The remote server returned an error» یک خطای مستقل نیست؛ فقط پوششی است دور یک پاسخ ناموفق HTTP که برنامه شما هنگام درخواست به یک سرور دیگر دریافت کرده است. عددی که داخل پرانتز می‌آید — مثلاً (503) Server Unavailable — همان کد وضعیت واقعی است و کل عیب‌یابی از همان عدد شروع می‌شود؛ فهرست کوتاه معنی این کدها در انواع خطاهای هاست و دلیل آن‌ها آمده است.

این خطا دقیقاً از کجا می‌آید

در برنامه‌های ASP.NET که با WebClient یا HttpWebRequest نوشته شده‌اند، هر وقت سرور مقصد پاسخی با کد ۴xx یا ۵xx برگرداند، دات‌نت یک System.Net.WebException پرتاب می‌کند و متن آن دقیقاً همین جمله است. معادل همین رفتار در پشته‌های دیگر هم وجود دارد: در PHP اخطار failed to open stream: HTTP request failed!، در پایتون خروجی raise_for_status() و در نسخه‌های جدیدتر دات‌نت HttpRequestException.

نکته کلیدی این است که خطا لزوماً «در» سرور شما رخ نداده است. کد شما درخواستی به بیرون فرستاده — یک وب‌سرویس، درگاه پرداخت، سرویس پیامک، فید قیمت یا هر API دیگری — و پاسخ ناموفق گرفته است. اگر آن فراخوانی در مسیر رندر صفحه اصلی باشد، کل صفحه با خطا بالا می‌آید، حتی وقتی بقیه سایت کاملاً سالم است. به همین دلیل هم این خطا معمولاً بدون اینکه شما چیزی را تغییر داده باشید ظاهر می‌شود. برای اینکه مطمئن شوید دامنه و میزبانی خودتان از بیرون سالم دیده می‌شوند، یک بررسی سلامت سایت در همان ابتدا کار را محدودتر می‌کند.

قدم اول: کد وضعیت را بیرون بکشید

پیش از هر حدسی، عدد را پیدا کنید. در دات‌نت داخل بلوک catch فقط پیام خطا را لاگ نکنید؛ پاسخ را هم باز کنید. مقدار ex.Status اگر برابر ProtocolError باشد یعنی ارتباط برقرار شده و طرف مقابل پاسخ داده است؛ در این حالت ex.Response را به HttpWebResponse تبدیل کنید و StatusCode و مهم‌تر از آن بدنه پاسخ را ثبت کنید. متن واقعی خطا تقریباً همیشه در بدنه پاسخ است، نه در پیام استثنا.

اگر ex.Status چیز دیگری بود (مثل Timeout، NameResolutionFailure یا ConnectFailure)، اصلاً پاسخی در کار نبوده و مسئله در سطح شبکه، DNS یا مهلت زمانی است، نه در سطح HTTP.

۴xx یعنی درخواست شما ایراد دارد

  • ۴۰۰: بدنه یا پارامترهای درخواست نامعتبر است؛ اغلب پس از تغییر قالب داده یا هدر Content-Type.
  • ۴۰۱ و ۴۰۳: احراز هویت یا دسترسی؛ توکن منقضی شده، کلید API عوض شده، یا IP سرور شما در فهرست مجاز طرف مقابل نیست.
  • ۴۰۴: آدرس نقطه پایانی تغییر کرده یا نسخه قدیمی API از رده خارج شده است.
  • ۴۲۹: از سقف تعداد درخواست عبور کرده‌اید.

این دسته با تغییر در کد یا تنظیمات سمت شما حل می‌شود و انتظار برای بهبود خودبه‌خود بی‌فایده است.

۵xx یعنی طرف مقابل به مشکل خورده است

  • ۵۰۰: خطای داخلی برنامه مقصد.
  • ۵۰۲ و ۵۰۴: یک لایه میانی مثل پروکسی، CDN یا فایروال نتوانسته پاسخ بگیرد یا مهلتش تمام شده است؛ معنی دقیق هر کد در ارورهای سری ۵xx آمده است.
  • ۵۰۳: سرویس در دسترس نیست؛ فشار بار، حالت تعمیر یا متوقف‌شدن سرویس پشت وب‌سرور.

حواستان باشد که ۵۰۲، ۵۰۳ و ۵۰۴ را ممکن است یک لایه میانی تولید کرده باشد، نه خود برنامه مقصد؛ پس بدنه و هدرهای پاسخ را بخوانید تا بفهمید چه کسی جواب داده است. اگر هدر Retry-After برگشت، همان را مبنای تلاش بعدی قرار دهید.

از روی خود سرور تست بگیرید، نه از لپ‌تاپ

درخواست ناموفق از سرور شما ارسال شده، پس تست هم باید از همان‌جا انجام شود، نه از مرورگر لپ‌تاپ که مسیر شبکه و آی‌پی متفاوتی دارد. روی یک سرور ابری — که تفاوتش با میزبانی سنتی در رایانش ابری چیست توضیح داده شده — با دسترسی روت کامل می‌توانید با SSH یا Remote Desktop وصل شوید و همان درخواست را دستی بزنید:

curl -i -sS "https://api.example.com/endpoint" هدرها و بدنه پاسخ را نشان می‌دهد و curl -sS -o /dev/null -w "%{http_code} %{time_total}\n" "https://api.example.com/endpoint" فقط کد وضعیت و زمان پاسخ را برمی‌گرداند. برای دیدن جزئیات دست‌دادن TLS هم curl -v کافی است. این دستورها فقط می‌خوانند و چیزی را تغییر نمی‌دهند.

اگر curl هم شکست خورد، نام دامنه مقصد را با dig api.example.com یا nslookup از همان سرور بررسی کنید. رکورد حذف‌شده، TTL نامناسب یا یک resolver خراب روی سرور، دقیقاً همین خطا را می‌سازد؛ در چنین مواردی وضعیت رکوردها و پایداری سرویس DNS اولین چیزی است که باید بازبینی شود.

لاگ‌ها را با هم تطبیق دهید

روی ویندوز، Event Viewer در بخش Application و لاگ‌های IIS در مسیر C:\inetpub\logs\LogFiles نقطه شروع هستند؛ برای ردیابی دقیق‌تر می‌توان Failed Request Tracing را فعال کرد. روی لینوکس سراغ /var/log/nginx/error.log یا /var/log/httpd/error_log و لاگ خطای PHP بروید؛ روی سرورهای cPanel لاگ اختصاصی هر سایت زیر پوشه logs در خانه کاربر است.

اگر سرویس مقصد هم متعلق به خودتان است، لاگ دسترسی آن را با همان مهر زمانی کنار لاگ سرور فراخوان بگذارید. تطبیق دو طرف روی یک زمان مشخص، معمولاً به‌سرعت معلوم می‌کند که خطا از برنامه آمده یا از وب‌سرور و فایروال جلوی آن.

علت‌های رایجی که واقعاً دیده می‌شوند

  • قطعی یا کندی موقت سرویس شخص ثالث.
  • انقضای کلید، توکن یا گواهی سمت مقصد.
  • مسدود شدن IP سرور توسط فایروال یا WAF طرف مقابل؛ در سمت خودتان هم رفع بلاک آی پی در فایروال را بررسی کنید.
  • محدودیت خروجی روی سرور خودتان؛ سیاست دسترسی خروجی در میزبانی اشتراکی را ارائه‌دهنده تعیین می‌کند، در حالی که روی سرور مجازی یا اختصاصی کنترل قوانین خروجی با شماست.
  • مهلت زمانی کوتاه در کد در برابر پاسخ‌های کند مقصد.
  • ناسازگاری نسخه TLS در برنامه‌های قدیمی دات‌نت که معمولاً پیام متفاوتی درباره کانال امن SSL/TLS تولید می‌کند.

کاری کنید که دفعه بعد سایت پایین نیاید

راه‌حل پایدار حذف آن بخش از سایت نیست، بلکه جدا کردن سرنوشت صفحه از سرنوشت سرویس بیرونی است. برای هر فراخوانی خارجی مهلت زمانی مشخص تعیین کنید، تلاش مجدد را فقط برای خطاهای ۵xx و ۴۲۹ و با فاصله فزاینده انجام دهید، آخرین پاسخ موفق را کش کنید و در زمان خطا همان را نشان دهید یا آن بخش را با یک پیام کوتاه پنهان کنید. در کنار این‌ها یک پایش ساده روی نقطه پایانی بگذارید تا پیش از کاربران متوجه قطعی شوید.

اگر پس از خواندن کد وضعیت و لاگ‌ها هنوز منشأ خطا روشن نشد، بررسی پیکربندی وب‌سرور، فایروال و مسیر خروجی سرور کار تیم فنی است و می‌توانید از تیم پشتیبانی فنی برای ادامه عیب‌یابی کمک بگیرید.

آموزش‌های مرتبط