آموزش

کد وضعیت HTTP: راهنمای عملی خطاهای رایج

کد وضعیت HTTP را درست تفسیر کن: تفاوت ۳۰۱ و ۳۰۲، چرا ۴۰۳ با ۴۰۱ فرق دارد، و چرا ۵۰۳ معمولاً تقصیر سرور خودت نیست.

آموزش

لاگ سرور را باز کرده‌ای و ستون status پر است از عددهایی که هیچ‌کدامشان «۲۰۰» نیستند. مشتری زنگ می‌زند که «سایت بالا نمی‌آید»، ولی سایت بالا می‌آید؛ فقط مرورگر او یک ۴۰۳ گرفته و تو داری دنبال مشکل PHP می‌گردی. این مقاله برای همان لحظه است: تشخیص اینکه کد وضعیت HTTP دقیقاً دارد چه چیزی به تو می‌گوید، و کدام‌شان را باید در کد درست کنی و کدام را در Nginx یا DNS.

اول کد وضعیت را از کجا ببینی، نه اینکه حدس بزنی

قبل از هر تحلیلی، پاسخ خام سرور را بگیر. مرورگر خیلی چیزها را پنهان می‌کند؛ curl نه:

curl -sSI https://example.com/old-page | head -n 20
curl -sS -o /dev/null -w "%{http_code} %{time_total}s %{redirect_url}\n" https://example.com/

فلگ -I فقط هدرها را می‌گیرد، -L اگر بگذاری زنجیرهٔ ریدایرکت را دنبال می‌کند و همان‌جاست که می‌فهمی سه تا ۳۰۱ پشت سر هم خورده‌ای. خروجی -w هم کد نهایی و زمان کل را چاپ می‌کند. اگر عددی که می‌بینی با چیزی که در مرورگر دیده‌ای فرق دارد، احتمالاً CDN یا کش میانی پاسخ را عوض کرده و باید هدر cf-cache-status یا x-cache را هم نگاه کنی.

برای دیدن وضعیت‌ها در حجم بالا، لاگ اکسس را مستقیم می‌شمارم:

awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

اگر ستون نهم لاگ تو کد وضعیت نیست، فرمت لاگ سفارشی است و باید اول log_format را در Nginx چک کنی. این شمارش در ده ثانیه به تو می‌گوید مشکل سیستمی است یا مربوط به یک مسیر خاص.

۳۰۱ در برابر ۳۰۲: کدام را در کد بگذاری

هر دو ریدایرکت دائمی‌اند و هر دو وزن SEO را منتقل می‌کنند. تفاوت واقعی‌شان در کش مرورگر و در متد درخواست است. ۳۰۱ یعنی «این آدرس برای همیشه عوض شده» و مرورگرها اجازه دارند پاسخ را کش کنند؛ ۳۰۲ یعنی «فعلاً اینجا نرو، آنجا برو» و کش نمی‌شود. در عمل، تفاوت را وقتی می‌بینی که یک ریدایرکت اشتباه زده‌ای و می‌خواهی برگردانی: با ۳۰۱، کاربرهایی که قبلاً سایت را دیده‌اند تا پاک‌کردن کش مرورگر همچنان به مقصد غلط می‌روند. با ۳۰۲ این درد را نداری.

انتخاب من: برای تغییر ساختار دائمی URL، ۳۰۱ بگذار. برای تست، برای ریدایرکت موقت کمپین، و برای هر چیزی که ممکن است تا فردا عوض شود، ۳۰۲. اگر شک داری، ۳۰۲ بگذار؛ هزینه‌اش یک هدر اضافه در هر درخواست است، نه بیشتر.

یک نکتهٔ فنی که خیلی‌ها را زمین می‌زند: در ۳۰۱ و ۳۰۲، مرورگر می‌تواند متد POST را به GET تبدیل کند. اگر فرمی را با ۳۰۱ ریدایرکت می‌کنی، بدنهٔ درخواست از دست می‌رود. برای حفظ متد باید ۳۰۷ یا ۳۰۸ بدهی. این‌جا اشتباه می‌کنند: یک فرم پرداخت را با ۳۰۱ به صفحهٔ تشکر می‌فرستند و بعد می‌بینند داده‌های POST نرسیده، در حالی که لاگ فقط یک ۳۰۱ سالم نشان می‌دهد.

در Nginx، ریدایرکت را با return بنویس نه rewrite؛ خواناتر است و از حلقهٔ ریدایرکت جلوگیری می‌کند:

location = /old-page { return 301 /new-page; }
location = /promo     { return 302 https://example.com/campaign; }

۴۰۱ و ۴۰۳: دو خطای کاملاً متفاوت که یکی گرفته می‌شوند

۴۰۱ یعنی «تو هویتت را ثابت نکردی». ۴۰۳ یعنی «تو را می‌شناسم، ولی اجازه نداری». این تفاوت در عیب‌یابی حیاتی است، چون مسیر رفعشان از هم جدا می‌شود. اگر لاگ پر از ۴۰۱ است، مشکل در احراز هویت است: توکن منقضی، کوکی گم‌شده، یا هدر Authorization که پروکسی میانی حذفش کرده. اگر پر از ۴۰۳ است، کاربر لاگین کرده و مشکل در سطح دسترسی است.

یک الگوی تکراری که زیاد می‌بینم: فایل‌های استاتیک سایت ۴۰۳ می‌دهند ولی صفحهٔ اصلی سالم است. علتش تقریباً همیشه مجوز فایل روی دیسک است، نه کد برنامه:

namei -l /var/www/example.com/wp-content/uploads/2024/05/image.jpg

namei -l کل مسیر را از ریشه نشان می‌دهد و همان‌جا می‌بینی یک دایرکتوری میانی مجوز 700 دارد و Nginx که با کاربر www-data اجرا می‌شود نمی‌تواند داخلش برود. این‌جا اشتباه می‌کنند: به‌جای اصلاح مجوز همان دایرکتوری، یک‌جا chmod -R 777 می‌زنند. نتیجه این است که خطا برای چند ساعت می‌رود و بعد برمی‌گردد، چون اسکریپت آپلود بعدی دوباره مجوز درست را ست می‌کند. مجوز درست برای دایرکتوری‌ها 755 و برای فایل‌ها 644 است.

در سمت برنامه، ۴۰۳ را عمداً و با پیام روشن برگردان. تفاوت بین «۴۰۳» و «۴۰۴» برای کاربر نهایی مهم است: اگر صفحه‌ای وجود دارد ولی کاربر اجازه ندارد، ۴۰۴ برگرداندن فقط سردرگمی می‌سازد و در لاگ هم رد پا باقی نمی‌گذارد.

۵۰۳: چرا تقریباً همیشه تقصیر سرور تو نیست

۵۰۳ یعنی سرور موقتاً نمی‌تواند درخواست را پردازش کند و مشکل در سمت زیرساخت است، نه در درخواست کاربر. این کد را بیشتر از هر جای دیگر روی CDN و لودبالانسر می‌بینی، وقتی بک‌اند جواب نمی‌دهد یا ظرفیت تمام شده. تفاوتش با ۵۰۰ در همین «موقت» بودن است: ۵۰۰ یعنی برنامه خطا داد، ۵۰۳ یعنی برنامه حتی فرصت جواب دادن پیدا نکرد.

اگر سایت خودت ۵۰۳ می‌دهد و CDN جلوی آن نیست، معمولاً یعنی تعداد ورکرهای PHP-FPM تمام شده. با این دو دستور تأییدش کن:

systemctl status php8.2-fpm --no-pager
grep -E "pm.max_children|pm.max_requests" /etc/php/8.2/fpm/pool.d/www.conf

اگر در لاگ FPM خط server reached pm.max_children setting, consider raising it را دیدی، مشکل همان است. بالا بردن pm.max_children جواب می‌دهد، ولی رایگان نیست: هر ورکر حافظه می‌گیرد و اگر عدد را بی‌حساب بالا ببری، سرور به swap می‌خورد و همه‌چیز کندتر می‌شود. عدد درست را از روی حافظهٔ آزاد حساب کن، نه از روی حدس. اگر روی هاست لینوکس هستی و به سقف منابع می‌خوری، این نقطه‌ای است که باید به فکر ارتقای پلن باشی.

برای پایش این وضعیت، هشدار روی کد وضعیت بگذار نه روی «سایت باز نشد». راهنمای پایش آپتایم سایت دقیقاً همین را پوشش می‌دهد: چطور هشدار بگیری بدون اینکه هر ری‌استارت کوتاه یک پیام کاذب بسازد.

جدول تصمیم سریع

کدمعنی کوتاهاول کجا را بگرد
301دائمی جابه‌جا شدهقواعد ریدایرکت در Nginx یا افزونهٔ سئو
302موقت جابه‌جا شدههمان، ولی کش مرورگر را چک نکن
401احراز هویت نشدهکوکی، توکن، هدر Authorization
403دسترسی ممنوعمجوز فایل و دایرکتوری، قواعد deny
404پیدا نشدمسیر فایل، قواعد rewrite
503سرویس در دسترس نیستورکرهای FPM، ظرفیت، CDN

یک تلهٔ رایج در جدول بالا: ۴۰۴ را با ۴۱۰ قاطی نکن. ۴۱۰ یعنی منبع برای همیشه رفته و دیگر برنمی‌گردد؛ برای صفحات حذف‌شدهٔ محصول همین را بگذار، نه ۴۰۴. تفاوتش در این است که ۴۱۰ به خزنده می‌گوید دیگر سراغش نیاید.

اگر می‌خواهی بفهمی این کدها چقدر روی سرعت واقعی اثر دارند، اول باید بدانی کدام درخواست‌ها کند هستند. راهنمای تست سرعت سایت روش تفسیر نتایج را توضیح می‌دهد و کمکت می‌کند بین یک ۳۰۱ کند و یک ۵۰۳ واقعی فرق بگذاری. برای سایت‌های وردپرسی هم بهینه‌سازی سرعت وردپرس نقطهٔ شروع بهتری است، چون نیمی از این کدها از افزونه‌های ریدایرکت می‌آیند.

پرسش‌های پرتکرار

تفاوت ۳۰۱ و ۳۰۲ در سئو چقدر مهم است؟

هر دو وزن صفحه را منتقل می‌کنند، پس از نظر رتبه تفاوت چشمگیری ندارند. تفاوت اصلی در رفتار کش مرورگر است: ۳۰۱ کش می‌شود و برگرداندنش سخت‌تر است، ۳۰۲ نه. اگر مطمئنی تغییر دائمی است ۳۰۱ بگذار، وگرنه ۳۰۲.

چرا سایت من ۴۰۳ می‌دهد ولی خودم می‌توانم بازش کنم؟

چون تو با حساب مدیر وارد شده‌ای و بقیه بدون آن حساب درخواست می‌فرستند. این تقریباً همیشه یعنی قاعدهٔ دسترسی یا مجوز فایل برای کاربر مهمان درست تنظیم نشده. با یک پنجرهٔ ناشناس یا curl بدون کوکی تست کن تا همان خطا را ببینی.

خطای ۵۰۳ را باید به هاستینگ گزارش بدهم یا خودم حل کنم؟

اگر CDN جلوی سایت است و ۵۰۳ از آن می‌آید، اول وضعیت بک‌اند را چک کن. اگر بک‌اند سالم است، مشکل سمت CDN است. اگر بک‌اند جواب نمی‌دهد و ورکرهای FPM پر شده‌اند، مشکل منابع است و باید یا تنظیمات را اصلاح کنی یا پلن را ارتقا بدهی.

کد وضعیت ۲۰۰ ولی صفحه خالی؛ این هم خطاست؟

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

قدم بعدی: همین حالا آن یک دستور awk را روی لاگ اکسس اجرا کن. اگر بیش از پنج درصد درخواست‌هایت ۴۰۳ یا ۵۰۳ است، مشکل واقعی سایت تو آن است، نه چیزی که تا حالا دنبالش می‌گشتی.

پشتیبانی سرورنت

تیم فنی و تحریریه‌ی سرورنت — تخصص در زیرساخت، شبکه و میزبانی وب.

هاست وردپرس
اشتراک‌گذاری:

دیدگاه‌ها ۰

هنوز دیدگاهی ثبت نشده؛ اولین نفر باشید!

دیدگاه خود را بنویسید

سرویس مرتبط

هاست وردپرس

استک اختصاصی وردپرس با LiteSpeed Enterprise و NVMe — نصب خودکار، آپدیت امن، استیجینگ و کشی که سایت شما را در صدر نتایج گوگل نگه می‌دارد.