أكواد حالة HTTP: مرجع من 1xx إلى 5xx بأمثلة
تفتح أدوات المطوّر فترى تبويب الشبكة نصفه أحمر. نقطة النهاية تُرجع 502 في الإنتاج و200 محلياً، وزميل لك على Slack يسألك للتو: «هل ينبغي أن يكون هذا 401 أم 403؟». أكواد حالة HTTP ثلاثة أرقام موزّعة على خمس فئات، لكنّ الاختيار الخاطئ يُسرّب المعلومات، ويكسر تحسين محركات البحث (SEO)، ويحوّل مناوبات الطوارئ إلى كابوس.
هذا الدليل مرجع لأكواد حالة HTTP للمطورين. ستجد فيه جدولاً مرجعياً سريعاً لكل كود تصادفه فعلياً في الإنتاج، ومصفوفات قرار للأزواج التي يخلط الناس بينها (301 vs 302 و401 vs 403 و404 vs 410 و502 vs 504)، وقسم أدوات يوضح كيفية فحص أكواد الحالة من curl وfetch ومكتبة Python requests. كل كود مذكور أدناه مستند إلى RFC 9110، وهو المعيار الحالي لدلالات HTTP، وإلى سجل أكواد حالة HTTP في IANA.
مرجع سريع: أكواد حالة HTTP في جدول واحد
هذه الأكواد التي ستلتقي بها في الإنتاج، مجمَّعة حسب الفئة. أضف الجدول إلى مفضّلتك، وبقية المقال تشرح الأكواد الأكثر إشكالاً.
| الكود | الاسم | متى ستراه |
|---|---|---|
| 100 | Continue | إرسال جسم POST كبير مع Expect: 100-continue |
| 101 | Switching Protocols | مصافحة WebSocket، الترقية إلى HTTP/2 |
| 103 | Early Hints | الخادم يرسل ترويسات Link قبل الاستجابة الفعلية |
| 200 | OK | النجاح الافتراضي لـ GET وPUT وPATCH |
| 201 | Created | POST ينشئ مورداً (يُرجع Location) |
| 202 | Accepted | مهمة غير متزامنة في الطابور، العمل لم يكتمل بعد |
| 204 | No Content | نجاح DELETE، أو PUT دون جسم استجابة |
| 206 | Partial Content | طلب نطاق، تخطّي في الفيديو، تنزيل قابل للاستئناف |
| 301 | Moved Permanently | الرابط القديم تُقاعَد، محركات البحث تنقل وزن الروابط |
| 302 | Found | إعادة توجيه مؤقتة، الرابط الأصلي يبقى الرسمي |
| 303 | See Other | نمط Post/Redirect/Get بعد إرسال نموذج |
| 304 | Not Modified | GET مشروط مع تطابق ETag أو If-Modified-Since |
| 307 | Temporary Redirect | مثل 302، لكن مع الحفاظ على المنهج والجسم |
| 308 | Permanent Redirect | مثل 301، لكن مع الحفاظ على المنهج والجسم |
| 400 | Bad Request | JSON مشوّه، حقل مطلوب مفقود، فشل المخطط |
| 401 | Unauthorized | لا توجد بيانات اعتماد، أو رمز انتهى صلاحيته |
| 403 | Forbidden | مستوثَق لكن غير مسموح |
| 404 | Not Found | المورد غير موجود (أو تخفيه عمداً) |
| 405 | Method Not Allowed | POST إلى نقطة نهاية تقبل GET فقط (يجب تضمين Allow) |
| 408 | Request Timeout | العميل استغرق وقتاً طويلاً لإرسال الطلب |
| 409 | Conflict | فشل قفل تفاؤلي، مفتاح مكرر |
| 410 | Gone | المورد حُذف بشكل دائم ولن يعود |
| 415 | Unsupported Media Type | Content-Type خاطئ، مثلاً XML إلى واجهة JSON |
| 422 | Unprocessable Content | البنية صحيحة، لكن الدلالة خاطئة (خطأ تحقّق) |
| 425 | Too Early | خطر إعادة تشغيل بيانات مبكرة في TLS 1.3 |
| 428 | Precondition Required | الخادم يلزمك بـ If-Match لتفادي التحديثات المفقودة |
| 429 | Too Many Requests | تجاوز حد المعدل (يجب تضمين Retry-After) |
| 451 | Unavailable for Legal Reasons | DMCA، إزالة GDPR، حظر جغرافي |
| 500 | Internal Server Error | استثناء غير معالَج في كودك |
| 501 | Not Implemented | المنهج أو الميزة غير مدعومين (نادر في REST) |
| 502 | Bad Gateway | الخادم الأعلى أرجع استجابة غير صالحة |
| 503 | Service Unavailable | وضع صيانة أو إفراط في التحميل |
| 504 | Gateway Timeout | الخادم الأعلى لم يستجب في الوقت المحدد |
| 507 | Insufficient Storage | WebDAV نفذت لديه المساحة |
| 508 | Loop Detected | إعادة توجيه لا نهائية أو تكرار في WebDAV |
| 511 | Network Authentication Required | بوابة أَسر في فندق أو مطار يطلب تسجيل الدخول |
بقية المقال تفكّك كل فئة عبر مصفوفات قرار ومضادّات أنماط وعواقب الاختيار الخاطئ على SEO.
كيف تعمل أكواد حالة HTTP (تشريح الأرقام الثلاثة)
لماذا ثلاثة أرقام؟
أكواد حالة HTTP ثلاثة أرقام عشرية لأن HTTP/0.9 احتاج إشارة بطول ثابت يتفرّع عليها المحلِّل بسرعة، وتتسع في الوقت نفسه لأكواد جديدة. ثلاثة أرقام تمنحك 900 قيمة ممكنة (100–999)، وهذا أكثر بكثير مما تحتاج؛ سجل IANA اليوم يستخدم نحو 60 كوداً فقط.
الرقم الأول يمثل الفئة، والرقمان الثاني والثالث يحدّدان الكود المعيّن داخل تلك الفئة. على العميل الذي لا يتعرّف على 418 أن يتعامل معه بوصفه 4xx عاماً. RFC 9110 §15 ينص على ذلك صراحةً: على العملاء أن يعاملوا الأكواد غير المعروفة كأنها x00 من فئتها.
الفئات الخمس في لمحة
| الفئة | المعنى | هل الجسم مطلوب؟ | قابلة للتخزين المؤقت افتراضياً؟ |
|---|---|---|---|
1xx | إعلامية، استجابة مؤقتة، المزيد قادم | لا | لا |
2xx | نجاح، الطلب فُهم وقُبل | غالباً | يعتمد على المنهج |
3xx | إعادة توجيه، تحتاج إجراء إضافياً | اختياري | 301 و308 نعم؛ 302 و307 لا |
4xx | خطأ من العميل، خطؤك أنت، صحّح الطلب | نعم (مع شرح) | عموماً لا |
5xx | خطأ من الخادم، خطؤنا نحن، قد تنفع إعادة المحاولة | نعم (مع شرح) | لا |
عمود «قابلة للتخزين المؤقت افتراضياً» مهم. شبكات توصيل المحتوى (CDN) والمتصفحات تخزّن 301 و308 بشراهة وإلى الأبد، فاختيار كود إعادة توجيه خاطئ في الإنتاج يصعب التراجع عنه، لأن المستخدمين يحتفظون بإعادة التوجيه مخزَّنة محلياً. سنعود إلى هذه النقطة في قسم SEO.
إذا أردت التعمّق في بنية الـ URL (وهي ما تعمل عليه أكواد إعادة التوجيه)، فإن ترميز وفك ترميز URL: دليل المطورين يأخذك خطوة بخطوة عبر التشفير بالنسبة المئوية وسلاسل الاستعلام وخط الأنابيب على مستوى البايت الذي يقرّر متى يكون الـ URL صالحاً ابتداءً.
1xx — إعلامية (متى ستراها فعلاً)
معظم المطورين يقضون سنوات دون أن يروا 1xx مباشرةً. هذه استجابات مؤقتة، يقول فيها الخادم للعميل: «ما زلت هنا، تابع». أدوات المطوّر في المتصفح تخفيها عادةً، ومعظم مكتبات HTTP تطويها داخل الاستجابة النهائية.
ولكل كود أدناه، يفيدك مرجع MDN لأكواد استجابة HTTP إن أردت رأياً ثانياً في تعريف ما.
100 Continue
العميل يرسل Expect: 100-continue ضمن ترويساته وينتظر قبل بثّ جسم طلب كبير. الخادم يرد بـ 100 Continue إن كان مستعداً لاستلام الجسم، أو بـ 4xx إن كان سيرفض الطلب على أي حال. هذا يوفّر عرض النطاق في الرفعات الكبيرة؛ لا فائدة من إرسال 200 ميغابايت إن كان الخادم سيرفض الطلب بسبب ترويسة مفقودة.
curl -v -H "Expect: 100-continue" \
-H "Content-Type: application/octet-stream" \
--data-binary @big-file.bin \
https://api.example.com/upload
إن لم تجد < HTTP/1.1 100 Continue في خرج الوضع التفصيلي، فالغالب أن عميلك جرّد الترويسة أو أن الخادم لا يدعمها.
101 Switching Protocols
المصافحة التي تحوّل اتصال HTTP إلى اتصال WebSocket أو HTTP/2. العميل يرسل Upgrade: websocket، والخادم يرد بـ 101 Switching Protocols، ومن تلك اللحظة يتكلّم الاتصال بروتوكولاً مختلفاً. ستراها في تبويب الشبكة لأي تطبيق دردشة أو لوحة قيادة حيّة أو أداة تعاون.
103 Early Hints
كود حديث نسبياً (RFC 8297، 2017) يتيح للخادم إرسال ترويسات Link لتلميحات التحميل المسبق قبل أن تجهز الاستجابة الرئيسية. يبدأ المتصفح في جلب CSS وJS بينما يكمل الخادم العَرْض. وحتى 2026، يدعم كل من Cloudflare وFastly وVercel الكود 103 في الإنتاج، وهو البديل الحديث لدفع الخادم في HTTP/2 (الذي أُهمل في Chrome).
HTTP/1.1 103 Early Hints
Link: </styles.css>; rel=preload; as=style
Link: </app.js>; rel=preload; as=script
HTTP/1.1 200 OK
Content-Type: text/html
...
فحص مضادّ النمط. إذا كان عميلك لا يرى أكواد 1xx حين تتوقعها، فالمشكلة عادةً في وكيل عكسي. إصدارات nginx القديمة تجرّد Expect: 100-continue و103 Early Hints. راجع إعدادات الوكيل قبل أن تفترض أن الخادم معطّل.
2xx — نجاح (ما هو أبعد من 200)
إعادة 200 OK لكل شيء أكثر روائح الكود انتشاراً في واجهات REST. عائلة 2xx تحمل معلومات دلالية تجعل العملاء أذكى والذواكر المؤقتة أكفأ.
200 OK
الافتراضي. GET يُرجع المورد، وPUT يُرجع المورد المحدَّث (أو 204)، وPATCH يُرجع المورد بعد الترقيع. إن لم يكن لديك سبب لاستخدام كود أكثر تحديداً، فاستخدم 200.
201 Created
ينبغي لـ POST الذي ينشئ مورداً جديداً أن يُرجع 201 مع ترويسة Location تشير إلى المورد الجديد. هكذا يكتشف عملاء REST الـ URL الرسمي للشيء الذي أنشؤوه.
HTTP/1.1 201 Created
Location: /api/users/42
Content-Type: application/json
{"id": 42, "name": "Ada Lovelace"}
202 Accepted
الخادم قبل الطلب لكنه لم يُنهِ معالجته بعد. استخدمه للأعمال غير المتزامنة، فعلى العميل أن يستفسر دورياً، أو يشترك في webhook، أو يفحص نقطة نهاية للحالة. اقرنه بمعرّف مهمة في الجسم.
204 No Content
نجاح بلا جسم. شائع مع DELETE (المورد ذهب، فما الذي ستعيده؟)، ومع عمليات PUT حيث يعرف العميل سلفاً الحالة الجديدة. لن يغيّر المتصفح الصفحة الحالية إن أرجع نموذج إرسال 204، وهذا مفيد لإجراءات «أطلق وانسَ» في تطبيقات الصفحة الواحدة.
206 Partial Content
تُرجع لطلبات النطاق؛ العميل يطلب البايتات من 1000 إلى 2000 عبر ترويسة Range: bytes=1000-2000، ويرد الخادم بتلك الشريحة فقط. بثّ الفيديو والتنزيلات القابلة للاستئناف ومزامنة الملفات عبر HTTP كلها تعتمد على 206.
قرار: 200 vs 201 vs 204 لـ POST
| السيناريو | الكود | الجسم |
|---|---|---|
| POST ينشئ مورداً جديداً | 201 Created | المورد الجديد (أو معرّفه فقط) + Location |
| POST يطلق عملاً غير متزامن، النتيجة لم تجهز | 202 Accepted | معرّف المهمة، رابط الاستفسار |
POST إجراء بلا مورد (مثل /login) | 200 OK | نتيجة الإجراء (رمز، حالة) |
| POST ينجح لكن الاستجابة فارغة | 204 No Content | (لا شيء) |
إن ترددت بين 200 و201، فاسأل: «هل أنشأ الخادم مورداً يحمل الآن URL خاصاً به؟». نعم؟ فـ 201. لا؟ فـ 200.
3xx — إعادة توجيه (301 vs 302 vs 307 vs 308)
إعادات التوجيه أكثر الفئات سوء استخدام. الفروق بين 301 و302 و307 و308 تتلخّص في ثلاثة أسئلة متعامدة: هل النقل دائم، وهل المنهج محفوظ، وهل الاستجابة قابلة للتخزين المؤقت.
301 Moved Permanently
المورد انتقل ولن يعود. محركات البحث تنقل وزن الروابط إلى الـ URL الجديد. المتصفحات وCDN تخزّن 301 إلى أجل غير مسمى، فلو أعدت توجيه /old إلى /new بـ 301 ثم غيّرت رأيك، سيستمر المستخدمون الذين خزّنوا إعادة التوجيه في الذهاب إلى /new إلى الأبد (أو حتى يمسحوا الذاكرة المؤقتة).
تاريخياً، قد تعيد المتصفحات كتابة منهج الطلب على 301 (POST ← GET)، ولهذا أدخل HTTP/1.1 الكود 308 لمعالجة الأمر.
302 Found
إعادة توجيه مؤقتة. الـ URL الأصلي يبقى الرسمي، وعلى محركات البحث أن تواصل فهرسته. استخدمه لتوجيه اختبارات A/B وصفحات الصيانة وتدفقات «سجّل الدخول للمتابعة».
كحال 301، أعادت المتصفحات تاريخياً كتابة POST إلى GET على 302. إن أردت إعادة توجيه POST مع إبقائه POST، فاستخدم 307 بديلاً عنه.
303 See Other
يعيد كتابة المنهج إلى GET دائماً. هذا هو نمط Post/Redirect/Get: النموذج يُرسَل إلى /submit، فيُرجع الخادم 303 مع Location: /thank-you، ويقوم المتصفح بـ GET /thank-you. تحديث صفحة الشكر لا يعيد إرسال النموذج، وهذا ما صُمّم له 303.
304 Not Modified
الاستجابة المشروطة. العميل يرسل If-None-Match: "abc123" (أو If-Modified-Since)، فيفحص الخادم ما إذا تغيّر المورد، فإن لم يتغيّر يُرجع 304 بلا جسم، ويستخدم المتصفح نسخته المخزَّنة. هكذا تحافظ كل شبكة CDN وكل طبقة تخزين مؤقت على سرعة موقعك.
307 Temporary Redirect
كـ 302، لكن يجب ألّا يتغيّر المنهج. POST يبقى POST، والجسم محفوظ. استخدمه حين تريد إعادة توجيه مؤقتة على طلب غير GET.
308 Permanent Redirect
كـ 301، لكن المنهج يجب ألّا يتغيّر. الخيار الحديث الأكثر أماناً لإعادات التوجيه الدائمة على واجهات تقبل POST/PUT.
مصفوفة قرار: أي كود إعادة توجيه؟
| دائم (تخزين أبدي) | مؤقت (لا تخزّن) | |
|---|---|---|
| يجوز أن يتغيّر المنهج إلى GET | 301 Moved Permanently | 302 Found |
| يجب أن يبقى المنهج كما هو | 308 Permanent Redirect | 307 Temporary Redirect |
حالة خاصة: إن أردت تحديداً POST ← GET (نمط Post/Redirect/Get)، فاستخدم 303 See Other.
لصفحات HTML مع تنقّل المتصفح، يكون 301 و302 عادةً ملائمَين لأن GET يبقى GET. أما لواجهات API والنماذج، فيُفضَّل 308 و307 لتفادي إعادة كتابة المنهج بشكل مفاجئ.
4xx — أخطاء العميل (اختيار الصحيح منها)
4xx تعني أن العميل ارتكب خطأً ما. كلما أثرَيت مفردات 4xx لديك، صار استخدام واجهتك أسهل؛ يستطيع العملاء التفرّع على الكود بدلاً من تحليل سلاسل أخطاء.
400 Bad Request
خطأ صياغي عام. JSON مشوّه، أو حقل مطلوب مفقود على المستوى البنيوي، أو طلب لا يستطيع الخادم حتى تحليله. إن كان الطلب يُحلَّل لكنه يفشل في التحقق التجاري، ففضّل 422.
401 Unauthorized vs 403 Forbidden
أكثر زوج يُخلط بينه في HTTP. الفرق بسيط متى رأيته:
401 Unauthorized: الطلب يفتقر إلى مصادقة صالحة، والخادم لا يعرف من أنت. إعادة إرسال بيانات الاعتماد (أو تجديد الرمز) قد تحلّ المشكلة. الاستجابة يجب أن تتضمن ترويسةWWW-Authenticateوفق RFC 9110 §15.5.2.403 Forbidden: الخادم يعرف من أنت ويرفض على أي حال. إعادة إرسال الطلب لن تنفع. تحتاج بيانات اعتماد مختلفة أو صلاحيات مختلفة.
| ما تراه | الحقيقة |
|---|---|
401 مع WWW-Authenticate: Bearer | لا رمز، رمز منتهٍ، أو رمز غير صالح |
403 بعد تسجيل دخول ناجح | مسجَّل لكن المستخدم لا يستطيع الوصول إلى هذا المورد |
401 بعد تسجيل دخول ناجح | خطأ برمجي — على الأرجح تريد 403 |
مضادّ نمط: 403 بدلاً من 404. بعض المواقع تُرجع 403 حين يطلب مستخدم غير مصادَق /admin/dashboard، وهذا يسرّب وجود /admin/dashboard. GitHub يحلّ هذا بإرجاع 404 للمستودعات الخاصة التي لست عضواً فيها، فالمورد «غير موجود» من منظورك. هذا اختيار مقصود لإخفاء المعلومات، لا خطأ.
404 Not Found vs 410 Gone
كلاهما يقول «هذا المورد غير موجود هنا». الفرق في الديمومة وفي SEO.
404 Not Found: قد يوجد، وقد لا يوجد، وقد يعود. محركات البحث ستستمر في الفحص.410 Gone: كان هنا، وأُزيل عمداً، ولن يعود. محركات البحث تُسقطه من الفهرس بسرعة أكبر.
إن حذفت صفحة منتج وأردت إخراجها من فهرس Google الآن، فـ 410 هو الاختيار الصحيح. أما إذا كان الـ URL معطّلاً مؤقتاً فقط، فـ 404 كافٍ.
405 Method Not Allowed
الـ URL موجود لكنه لا يقبل هذا المنهج. الاستجابة يجب أن تتضمن ترويسة Allow تسرد المناهج المدعومة.
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
{"error": "POST is not allowed on this endpoint"}
نسيان ترويسة Allow هو أكثر انتهاك للعقد شيوعاً في واجهات REST المكتوبة يدوياً.
408 Request Timeout
العميل بدأ إرسال طلب ثم صمت، فاستسلم الخادم. مختلف عن 504 Gateway Timeout الذي يخصّ الخادم الأعلى؛ 408 يقول: «أنت أيها العميل أخذت وقتاً طويلاً».
409 Conflict
الطلب يتعارض مع الحالة الحالية. الاستخدام الأشيع: القفل التفاؤلي. العميل يرسل If-Match: "etag-v3" بينما ETag الحالي للخادم هو "etag-v4"، فيُرفض التحديث بـ 409.
410 Gone
انظر أعلاه: حذف دائم. مفيد لإخراج السجلات المحذوفة منطقياً من فهارس البحث.
415 Unsupported Media Type
العميل أرسل جسماً لا يفهمه الخادم. إرسال XML إلى واجهة تقبل JSON فقط يعطي 415. الاستجابة ينبغي أن تلمّح إلى الأنواع المقبولة.
422 Unprocessable Content
الطلب يُحلَّل بلا مشكلة، لكنه يفشل في التحقق الدلالي. رفع RFC 9110 هذا الكود من WebDAV إلى المعيار الأساسي في 2022. استخدم 422 لأخطاء التحقق:
{
"error": "validation_failed",
"details": [
{"field": "email", "message": "must be a valid email"},
{"field": "age", "message": "must be at least 13"}
]
}
إن لم تستطع واجهتك التمييز بين 400 و422، فالقاعدة العملية: 400 تعني «لا أستطيع حتى تحليل هذا»، و422 تعني «حلّلتُه ولا معنى له».
425 Too Early
يُرسل حين لا يريد الخادم المخاطرة بمعالجة طلب قد يكون إعادة تشغيل لبيانات مبكرة في TLS 1.3. ذو صلة في الغالب بشبكات CDN والوكلاء العكسيين.
428 Precondition Required
الخادم يصرّ على أن ترسل If-Match أو If-Unmodified-Since لتجنب فقدان التحديث. يُستخدم في واجهات التحرير التعاوني.
429 Too Many Requests
تجاوزت حد المعدل. الاستجابة يجب أن تتضمن Retry-After (بالثواني أو كتاريخ HTTP) كي يتسنى للعملاء المؤدّبين التراجع.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{"error": "rate_limited", "limit": 100, "window": "1m"}
451 Unavailable for Legal Reasons
الرقم إشارة إلى رواية برادبري. لكن حالة الاستخدام ليست خيالية: إزالات DMCA وطلبات «الحق في النسيان» وفق GDPR والحظر الجغرافي على مستوى الدولة، كلها تبرّر 451. ينبغي أن تتضمن الاستجابة ترويسة Link تشير إلى الجهة القانونية الموجِبة للحجب، وفق RFC 7725.
418 I’m a Teapot (البيضة المخفيّة)
نعم، حقيقي. RFC 2324 (مزحة كذبة أبريل 1998)، وأبقاها IETF في السجلات لأن منتجات كثيرة نفّذتها على سبيل المزاح. لا تشحن 418 في واجهة حقيقية؛ معظم الوكلاء العكسيين وموازِنات الحمل سيتعاملون معها بشكل خاطئ.
مصفوفة قرار: أي كود 4xx؟
| الموقف | الكود |
|---|---|
| الجسم مشوّه أو غير قابل للتحليل | 400 |
| لا مصادقة / رمز منتهٍ | 401 |
| مستوثَق لكن غير مسموح | 403 |
| الـ URL غير موجود (أو تخفيه) | 404 |
| الـ URL كان موجوداً، أُزيل عمداً | 410 |
| منهج HTTP خاطئ | 405 (مع Allow) |
Content-Type خاطئ | 415 |
| تعارض قفل تفاؤلي | 409 |
| خطأ تحقّق (يُحلَّل ولا يجتاز التحقق) | 422 |
| تجاوز حد المعدل | 429 (مع Retry-After) |
| محجوب لأسباب قانونية | 451 |
5xx — أخطاء الخادم (ما المعطّل فعلاً)
5xx تعني «خطؤنا نحن». مهندسو المناوبة يهتمّون بأي 5xx أيقظهم في الثالثة فجراً، لأن الكود يدلّك على الطبقة التي يجب أن تفحصها أولاً.
500 Internal Server Error
الكود الجامع. يعني تقريباً دائماً أن استثناءً غير معالَج تصاعد إلى المعالج الافتراضي للإطار. لا يخبرك بشيء عن السبب، ولهذا يهم التسجيل المهيكَل هنا أكثر من كود الحالة نفسه.
501 Not Implemented
الخادم لا يدعم المنهج إطلاقاً. مختلف عن 405 (هذا المنهج غير مسموح لهذا الـ URL)؛ 501 يقول: «هذا الخادم لا يعرف ما هو PROPFIND أصلاً». نادر في واجهات REST.
502 Bad Gateway
وكيل عكسي أو موازِن حمل تلقّى استجابة غير صالحة من الخادم الأعلى. الخادم الأعلى ردّ، لكن بمحتوى تالف أو بروتوكول خاطئ أو ترويسات مشوّهة أو اتصال انقطع في منتصف الاستجابة. إن رأيت 502 من شبكتك CDN، فالغالب أن الأصل ينهار أو يُرجع أجساماً مقطوعة.
503 Service Unavailable
الخادم يرفض تقديم الطلبات الآن عمداً. استخدمه لنوافذ الصيانة أو لاستجابات الإفراط الرشيقة. ينبغي تضمين Retry-After.
504 Gateway Timeout
الوكيل العكسي انتظر الخادم الأعلى ولم يستجب الأخير في الوقت المحدد. الخادم الأعلى بطيء أو متوقف، وهذا مختلف عن 502 الذي يردّ فيه الخادم الأعلى بمحتوى تالف.
502 vs 504: تشخيص المناوبة
| ما تراه | أول ما تفحصه |
|---|---|
502 Bad Gateway | الخادم الأعلى يردّ ببيانات غير صالحة، افحص سجلات الأصل بحثاً عن انهيارات، استجابات مشوّهة، عدم تطابق بروتوكولات |
504 Gateway Timeout | الخادم الأعلى معلَّق، افحص CPU الأصل، استعلامات قاعدة البيانات، استدعاءات API النازلة، وproxy_read_timeout للوكيل |
خلط شائع: استعلام قاعدة بيانات يستغرق 60 ثانية سيظهر بصورة 504 إن انتهت مهلة وكيلك عند 30 ثانية، لكنه سيظهر 500 إن انتهت مهلة خادم التطبيق عند 90 ثانية ورفع استثناءً. السبب الجذري واحد، والكود مختلف، وسطر السجل مختلف، فدرّب لوحات قيادتك على إبراز كليهما.
507 Insufficient Storage
خاص بـ WebDAV. القرص ممتلئ على الخادم. إن رأيت هذا من واجهة ليست WebDAV، فأحدهم يحمّل المعنى ما لا يحتمل.
508 Loop Detected
تكرار لا نهائي في عمليات PROPFIND ضمن WebDAV. نادر جداً.
511 Network Authentication Required
كود البوابات الأَسْرية. واي فاي الفندق أو المطار يرسل 511 ليقول لمتصفحك: «عليك تسجيل الدخول إلى البوابة أولاً». وتتضمن الاستجابة Location يشير إلى صفحة البوابة.
مصفوفة استكشاف الأخطاء: أي طبقة تفحص أولاً
| الكود | التطبيق | الوكيل | قاعدة البيانات | الشبكة |
|---|---|---|---|---|
500 | نعم | — | ربما (خطأ DB غير ملتقط) | — |
502 | — | نعم (الخادم الأعلى مشوَّه) | — | ربما (إعادة تعيين TCP) |
503 | نعم (راية صيانة) | نعم (رفض حد المعدل) | — | — |
504 | نعم (معالج بطيء) | نعم (إعداد المهلة) | نعم (استعلام بطيء) | نعم (DNS، فقد الحزم) |
مضادّات أنماط شائعة في أكواد حالة HTTP
الأخطاء الخمسة التالية تفسّر معظم الكود الرديء في مراجعات الواجهات.
1. تغليف الأخطاء بـ 200 OK
HTTP/1.1 200 OK
{"success": false, "error": "user_not_found"}
كل أداة مراقبة وكل CDN وكل ذاكرة مؤقتة تظنّ الآن أن الطلب نجح. منطق إعادة المحاولة يفشل. موازِنات الحمل المتنبّهة لكود الحالة توجّه الترافيك السيئ إلى خوادم خلفية «سليمة». هذا النمط جاء من JSON-RPC وورثه GraphQL؛ GraphQL يفعله لأن النجاحات الجزئية تحتاج إبلاغ أخطاء على مستوى الحقل، وهذا منصف. أما REST فلا عذر له: استخدم 4xx لأخطاء العميل و5xx لأخطاء الخادم، وضع التفاصيل المهيكلة في الجسم.
2. الخلط بين 401 و403
إن لم يكن 401 و403 متّسقَين عندك، فبإمكان المهاجمين تحسّس واجهتك لاكتشاف الموارد الموجودة. ضع سياسة: إما إرجاع 404 لـ «لا يحقّ لك رؤية هذا» (نهج GitHub للمستودعات الخاصة)، أو إرجاع 403 باتساق. عدم الاتساق يسرّب المعلومات.
3. إخفاء 403 خلف 404
أحياناً صحيح، وغالباً خطأ برمجي. إرجاع GitHub لـ 404 للمستودعات الخاصة مقصود، فوجود المستودع نفسه حسّاس. لكن إن أرجعت واجهتك 404 لـ «هذا الحساب موقوف»، فلن يستطيع المستخدمون الشرعيون التمييز بين كتابة اسم المستخدم بشكل خاطئ والإيقاف. وثّق سياستك صراحةً وطبّقها باتساق.
4. استخدام 500 ملاذاً افتراضياً
تجعل الأطر هذا سهلاً، وهنا تكمن المشكلة. كل استثناء غير ملتقط يصبح 500، وأنظمة التنبيه لديك لا تستطيع التمييز بين «قاعدة البيانات معطّلة» و«المستخدم مرّر UUID مشوّهاً». التقط أخطاء التحقق وارفع 400 أو 422. التقط NotFound من ORM وارفع 404. احتفظ بـ 500 للإخفاقات غير المتوقعة فعلاً، وعند رفعه سجّل معرّف طلب لتربط بين الأحداث.
5. سلاسل إعادة توجيه طويلة
كل قفزة تكلّف رحلة ذهاب وإياب. إن كان /old ← /intermediate ← /canonical، فهذا يعني عمليتَي بحث DNS إضافيتين ومصافحتَي TCP إضافيتين (في أسوأ الحالات). يخفّض Google أولوية الزحف للسلاسل الأطول من 3 قفزات تحديداً، وتُسقف المتصفحات سلاسل إعادة التوجيه عند نحو 20 لمنع الحلقات. اضغط السلاسل من المصدر: إعدادات CDN أو خريطة إعادة التوجيه في تطبيقك.
أكواد حالة HTTP وSEO
تتعامل محركات البحث مع أكواد الحالة كإشارات موثوقة بشأن الإبقاء على URL أو إسقاطه أو نقله. اختر خطأ، يتحرّك ترتيبك.
301 vs 302 (وزن الروابط)
301 Moved Permanently ينقل PageRank؛ Google يعامل الـ URL الجديد على أنه الوجهة الرسمية لكل الإشارات الموجَّهة إلى الـ URL القديم. 302 Found لا ينقل وزن الروابط (أو ينقله ببطء، حسب استدلالات Google). إن أعدت تسمية URL إلى الأبد، فاستخدم 301. إن أعدت توجيه ضيف إلى /login، فاستخدم 302.
404 vs 410 vs Soft 404
Google يميّز بين ثلاث حالات «مفقود»:
404 Not Found: يعيد Google الفحص دورياً ويُبقي الـ URL في الفهرس مدّةً.410 Gone: يُسقط Google الـ URL أسرع، غالباً ضمن دورة زحف واحدة.- Soft 404: مصطلح Google لصفحة تُرجع
200 OKلكنها تعرض رسالة «غير موجود». يكتشف Google هذا من أنماط المحتوى ويعامله كـ404على أي حال، لكنك أهدرت طلب زحف وربما خفّفت محتواك الحقيقي.
إن كنت تنظّف فهرساً قديماً، فأرجع 410 حقيقية للروابط التي أُزيلت بشكل دائم.
5xx وميزانية الزحف
زاحف Google يقلّل من معدّله حين يُرجع موقع 5xx باستمرار. تقرير «إحصاءات الزحف» في Search Console يُظهر هذا؛ ارتفاع مستمر في أخطاء 5xx قد يخفض ميزانية زحفك أياماً، ما يعني أن الصفحات الجديدة تأخذ وقتاً أطول حتى تُفهرس. عامِل معدلات 5xx مقياساً سيوياً، لا مقياس موثوقية فحسب.
200 OK في حقيقتها معطّلة
إعادة 200 OK مع صفحة خطأ (مضادّ نمط soft-404) أسوأ سيناريو لـ SEO. يفهرس Google رسالة الخطأ، ويصنّفها على لا شيء، ثم يكتشف الصفحة المعطّلة ببطء. أرجع دائماً كود الحالة الصحيح من الخادم، حتى لو عرض تطبيقك أحادي الصفحة واجهة خطأ ودودة.
كيف تفحص أكواد حالة HTTP (الأدوات)
لا يمكنك إصلاح ما لا تراه. ينبغي لكل مطوِّر يعمل بانتظام أن يتقن اثنتين على الأقل من هذه الأدوات.
لوحة الشبكة في أدوات المطوّر بالمتصفح
كلٌّ من Chrome وFirefox وSafari يعرض عمود Status في تبويب الشبكة. انقر بالزر الأيمن على ترويسة العمود لإضافة Status Text إن لم يكن ظاهراً. حيل مفيدة:
- Preserve log: الإبقاء على الإدخالات عبر التنقّلات لرؤية سلسلة إعادة التوجيه كاملة.
- التصفية بالحالة: اكتب
status-code:5xx(في Chrome) لرؤية أخطاء الخادم فقط. - Replay XHR: انقر بالزر الأيمن على أي طلب ← Replay XHR لإعادة تشغيله دون تحديث الصفحة.
لإعادات التوجيه، وسّع الطلب لرؤية كل قفزة وكود الحالة عند كل خطوة.
curl (الأداة الموسوعية)
curl يُظهر كل شيء. ثلاثة أنماط تحلّ 90% من تصحيح الأخطاء:
# Just the status code
curl -o /dev/null -s -w "%{http_code}\n" https://api.example.com/users/1
# Headers only (HEAD request, follow redirects)
curl -I -L https://example.com
# Full verbose with request and response headers
curl -v https://api.example.com/users/1
حين تُنشئ URL اختبارية تحوي رموزاً خاصة في سلاسل الاستعلام، استخدم --data-urlencode لتدع curl يتولى الترميز عنك، أو الصق الـ URL في أداة ترميز وفك ترميز URL للتحقق من البايتات التي ستذهب فعلاً على السلك.
# curl encodes the query value for you
curl -G "https://api.example.com/search" \
--data-urlencode "q=hello world & friends"
# Sends: GET /search?q=hello%20world%20%26%20friends
JavaScript fetch
الخاصية Response.status تحمل الكود الصحيح. Response.ok تساوي true لأي 2xx.
const res = await fetch('https://api.example.com/users/1');
console.log(res.status); // 200
console.log(res.statusText); // "OK"
console.log(res.ok); // true
if (!res.ok) {
if (res.status === 401) {
// refresh token and retry
} else if (res.status === 429) {
const retryAfter = Number(res.headers.get('Retry-After')) || 1;
await new Promise(r => setTimeout(r, retryAfter * 1000));
} else if (res.status >= 500) {
throw new Error(`Server error: ${res.status}`);
}
}
في axios، يعيش المنطق نفسه داخل المعترِضات:
import axios from 'axios';
axios.interceptors.response.use(
response => response,
error => {
const status = error.response?.status;
if (status === 401) {
// redirect to login
}
return Promise.reject(error);
}
);
Python requests
import requests
r = requests.get('https://api.example.com/users/1')
print(r.status_code) # 200
print(r.reason) # 'OK'
# Raises requests.exceptions.HTTPError for 4xx/5xx
r.raise_for_status()
# Manual handling
if r.status_code == 429:
retry_after = int(r.headers.get('Retry-After', '1'))
time.sleep(retry_after)
elif 500 <= r.status_code < 600:
raise RuntimeError(f'Server error: {r.status_code}')
raise_for_status() هو الاصطلاح في Python لـ «أفشل بصوت عالٍ على 4xx/5xx». استخدمه في السكربتات حين تريد استثناءات على الأخطاء بدلاً من التفرّع على status_code.
Postman وBruno
كلتاهما تتيح لك التأكيد على أكواد الحالة داخل سكربت اختبار:
// Postman/Bruno test script
pm.test("Status is 201", () => {
pm.response.to.have.status(201);
});
pm.test("Has Location header", () => {
pm.expect(pm.response.headers.get('Location')).to.match(/^\/users\/\d+$/);
});
شغّل هذه على بيئة staging ضمن CI لاكتشاف انتهاكات العقد قبل الإنتاج.
الأسئلة الشائعة
ما الفرق بين 401 و403؟
401 Unauthorized يعني أن الخادم لا يعرف من أنت؛ بيانات الاعتماد مفقودة أو منتهية أو غير صالحة. 403 Forbidden يعني أن الخادم يعرف من أنت ويرفض على أي حال. إن كان إرسال بيانات اعتماد مختلفة قد ينفع، فاستخدم 401. إن لم ينفع، فاستخدم 403.
متى أستخدم 301 وليس 302؟
استخدم 301 حين يكون النقل دائماً، فالـ URL القديم لن يعود أبداً، وتريد محركات البحث أن تنقل وزن الروابط إلى الـ URL الجديد. استخدم 302 لإعادات التوجيه المؤقتة حيث يبقى الـ URL الأصلي رسمياً (تدفقات تسجيل الدخول واختبارات A/B وصفحات الصيانة). لواجهات API، فضّل 308 و307 لأنهما يحفظان منهج الطلب.
ماذا يعني خطأ 502 Bad Gateway؟
502 يعني أن وكيلاً عكسياً أو موازِن حمل تلقّى استجابة غير صالحة من الخادم الأعلى. الخادم الأعلى ردّ، لكن بمحتوى تالف أو بروتوكول خاطئ أو ترويسات مشوّهة أو اتصال انقطع. مختلف عن 504 Gateway Timeout الذي يعني أن الخادم الأعلى لم يردّ إطلاقاً. أول ما تفحصه: سجلات خادم الأصل بحثاً عن انهيارات أو استجابات مقطوعة.
ما هو «soft 404»؟
«soft 404» صفحة تُرجع 200 OK لكنها في الواقع تعرض رسالة «غير موجود». يكتشفها Google استدلالياً ويعاملها كـ 404 على أي حال. تهدر ميزانية الزحف وقد تخفّف محتواك الحقيقي. أرجع دائماً أكواد 404 أو 410 حقيقية من الخادم، حتى لو عرض تطبيقك أحادي الصفحة واجهة خطأ ودودة.
متى أستخدم 422 بدلاً من 400؟
استخدم 400 Bad Request حين لا يستطيع الخادم تحليل الطلب أصلاً، مثل JSON مشوّه أو حقول بنيوية مفقودة أو أخطاء صياغية. استخدم 422 Unprocessable Content حين يُحلَّل الطلب بلا مشكلة لكنه يفشل في التحقق التجاري، مثل صياغة بريد إلكتروني خاطئة أو قيمة خارج النطاق أو حقول غير متّسقة دلالياً. القاعدة المختصرة: 400 للصياغة، و422 للدلالة.
كيف أستجيب لـ 429 Too Many Requests؟
اقرأ ترويسة Retry-After (عدد ثوانٍ أو تاريخ HTTP) وتراجَعْ على الأقل بهذا القدر قبل إعادة المحاولة. إن كانت Retry-After مفقودة، فاستخدم تراجعاً أُسّياً مع jitter ابتداءً من نحو ثانية واحدة. لا تعد المحاولة فوراً أبداً؛ هذه هي الطريقة المضمونة لتُحظَر.
هل ما زالت أكواد 1xx الإعلامية مستخدمة في 2026؟
نعم، لكن معظمها غير مرئي لكود التطبيق. 100 Continue و101 Switching Protocols ميزتان أساسيتان في HTTP/1.1. 103 Early Hints يستخدمه بشكل متزايد Cloudflare وFastly وVercel لدفع تلميحات التحميل المسبق قبل الاستجابة الرئيسية، وهو يحسّن Largest Contentful Paint بشكل ملحوظ. معظم مكتبات HTTP تطوي 1xx داخل الاستجابة النهائية، فلا تراها عادةً إلا في أدوات المطوّر أو في curl -v.
هل 418 «I’m a teapot» كود حالة حقيقي؟
نعم. RFC 2324 كانت مزحة كذبة أبريل من 1998، لكن منتجات كثيرة طبّقتها فأبقاها IETF في السجلات في RFC 7168. لا تشحن 418 في الإنتاج؛ كثير من الوكلاء العكسيين وموازِنات الحمل لا تتعامل معه بشكل صحيح، وهو لا يخدم غرضاً حقيقياً خارج المزحة.