البحث في الموقع
المحتوى عن 'http'.
-
OAuth 2 هو آليّة للتّرخيص تسمح للتطبيقات بطلب وصول محدود إلى حسابات المستخدمين في خدمات HTTP، مثل Facebook وGitHub وDigitalOcean. يعمل OAuth 2 بتوكيل الخدمة المستضيفة لحساب المستخدم باستيثاق هذا الحساب، ثمّ السّماح للتطبيقات الخارجيّة بالوصول إلى حساب المستخدم هذا. يوفّر OAuth 2 مسارًا لترخيص تطبيقات الويب وتطبيقات سطح المكتب والأجهزة المحمولة. هذا الدّرس موجّه لمطوّري التّطبيقات، وهو يُلقي الضّوء على أدوار OAuth 2 وأنواع الرُّخَص المتاحة، وكذلك يستعرض مجالات استخدامه وسير عمليّة التّرخيص. لنبدأ بالتّعرّف على أدوار OAuth. أدوار OAuth يُحدِّد OAuth أربعة أدوار: مالك المحتوى العميل خادوم المحتوى خادوم التّرخيص سنُفصّل كلًّا من هذه الأدوار في الفقرات التّالية. مالك المحتوى: المستخدم مالك المحتوى هو المستخدم الذي يُرخِّص لتطبيقٍ الوصول إلى حسابه. وصول التّطبيق إلى حساب المستخدم محدودٌ "بنطاق" (scope) الترخيص الممنوح (مثلاً: صلاحيّة القراءة والكتابة). خادوم المحتوى/التّرخيص: الواجهة البرمجيّة (API) يستضيف خادوم المحتوى حسابات المستخدمين المحميّة، ويتحرّى خادوم التّرخيص هويّة المستخدم ثمّ يمنح التّطبيق رمز وصول (access token). من وجهة نظر مطوّر التّطبيقات، فإنّ الواجهة البرمجيّة للخدمة تؤدّي كلا الدّورين، دور خادوم المحتوى ودور خادوم التّرخيص. سنُشير إلى هذين الدّورين مجتمعين على أنّهما دور الخدمة أو الواجهة البرمجيّة. العميل: التّطبيق العميل هو التّطبيق الّذي يريد الوصول إلى حساب المستخدم، وقبل أن يستطيع ذلك، يجب أن يحصل على "ترخيص" المستخدم، وعلى هذا التّرخيص أن يُصادَق من الواجهة البرمجيّة. سير البروتوكول نظريًّا بعد أن تعرّفنا على أدوار OAuth، دعونا نلقِ نظرةً على المخطّط التالي، والذي يبيّن كيف تتفاعل هذه الأدوار فيما بينها: وفيما يلي شرح أكثرُ تفصيلًا للخطوات المُبيّنة في المُخطّط: يطلب التطبيق رخصةً للوصول إلى الخدمة من المستخدم إن رخّص المستخدم الطّلب، فإنّ التطبيق يحصل على إذن بالتّرخيص يطلب بعدها التطبيق رمز وصول (access token) من خادوم التّرخيص (الواجهة البرمجيّة) مُقدّمًا ما يُثبت هوّيته مع إذن التّرخيص الّذي حصل عليه. إن كانت هويّة التّطبيق موثّقة وإذن التّرخيص سليمًا، أصدر خادوم التّرخيص (الواجهة البرمجيّة) رمز وصول (access token) يمنحه للتّطبيق، لتكتمل حينئذٍ عمليّة الترخيص. يطلب التّطبيق من خادوم المحتوى (الواجهة البرمجيّة) المحتوى المطلوب، مُقدّمًا رمز الوصول الّذي حصل عليه. إن كان رمز الوصول سليمًا، قدّم خادوم المحتوى (الواجهة البرمجيّة) المحتوى المقصود للتطبيق قد يختلف مسار العمليّة الفعليّ بحسب نوع الرّخصة المُستخدمة، ولكن هذه هي الفكرة العامّة. سنستعرض أنواع الرُّخَص المُختلفة في فقرة لاحقة. تسجيل التّطبيق قبل استخدام OAuth في تطبيقاتك، عليك تسجيل التّطبيق في الخدمة المعنيّة. يجري التسجيل عادةً من خلال نموذج في قسم المُطوّرين أو الواجهة البرمجيّة في موقع الخدمة على الويب، حيث ينبغي عليك تقديم البيانات التالية (وربّما معلومات أخرى عن تطبيقك): اسم التّطبيق موقع التّطبيق رابط إعادة الّتوجيه (Redirect URL) أو الاستدعاء الرّاجع (Callback URL) تُعيد الخدمة توجيه المستخدم إلى رابط إعادة التّوجيه الّذي توفّره بعد ترخيصه لتطبيق (أو رفضه)، وعليه فإنّ هذا الرابط هو المسؤول عن التّعامل مع رموز الترخيص أو رموز الوصول (access tokens). مُعرّف العميل وكلمة سرّ العميل ستمنحك الخدمة بعد تسجيل تطبيقك "وثائق اعتماد العميل" المؤلّفة من معرّف العميل وكلمة سرّ العميل. معرّف العميل هو سلسلة من الحروف مكشوفة للعموم تستخدمها الواجهة البرمجيّة للخدمة لتحديد هويّة التّطبيق، ولبناء روابط التّرخيص المُقدّمة للمستخدمين. أمّا كلمة سر العميل فتُستخدم للاستيثاق من هويّة التّطبيق بالنّسبة للواجهة البرمجيّة للخدمة عندما يطلب التّطبيق الوصول إلى حساب المُستخدم، ويجب أن تبقى سرّيّة بين التّطبيق والواجهة البرمجيّة. إذن التّرخيص في فقرة "سير البروتوكول نظريًّا"، تبيّن الخطوات الأربع الأولى كيفيّة الحصول على إذن بالتّرخيص ورمز للوصول. يعتمد نوع الإذن على طريقة طلب التّطبيق للتّرخيص، وأنواع الأذون الّتي تدعمها الواجهة البرمجيّة. يعرّف OAuth 2 أربعة أنواع من أذون التّرخيص، يمكن الاستفادة من كلّ منها في حالات مُختلفة: رمز التّرخيص (Authorization Code): تستخدمه التّطبيقات الّتي تعمل على الخواديم ضمنيّ (Implicit): تستخدمه تطبيقات الويب وتطبيقات الأجهزة المحمولة (أي التّطبيقات الّتي تعمل على جهاز المُستخدم) كلمة مرور مالك المحتوى: تستخدمها التّطبيقات الموثوقة، كتلك الّتي تتبع للخدمة ذاتها كلمة مرور العميل: تستخدم في حالة الوصول للواجهة البرمجيّة للتّطبيقات سنشرح أنواع الأذون وحالات استخدامها بالتّفصيل في الفقرات التّالية. الإذن من نوع "رمز الترخيص": هذا النّوع من الأذون هو الأكثر استخدامًا لأنّه مُصمّم للتطبيقات الّتي تعمل على الخواديم، حيث لا يُكشف النّص المصدريّ للتّطبيق للعموم، وحيث يمكن الاحتفاظ بسرّيّة كلمة سرّ العميل بصورة تامّة. ويعتمد سير التّرخيص هنا على إعادة التّوجيه، ممّا يعني أنّه على التّطبيق أن يكون قادرًا على التّفاعل مع وكيل المستخدم (كمتصفّح الويب الّذي يستخدمه) وعلى استقبال رموز التّرخيص الّتي توفّرها الواجهة البرمجيّة والّتي تمرّ من خلال وكيل المستخدم. سنشرح الآن سير عمليّة التّرخيص في هذا النّوع من الأذون: سير التّرخيص بالرّمز الخطوة 1: رابط رمز الترخيص يُعطى المُستخدم في البداية رابطًا لرمز التّرخيص يُشبه هذا: https://cloud.digitalocean.com/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read فيما يلي شرحٌ لمكوّنات الرابط: https://cloud.digitalocean.com/v1/oauth/authorize: نقطة الوصول إلى قسم التّرخيص في الواجهة البرمجيّة client_id=client_id: مُعرّف العميل للّتطبيق (كيفيّة تحديد الواجهة البرمجيّة لهويّة التّطبيق) redirect_uri=CALLBACK_URL: المكان الّذي تعيد الخدمة توجيه وكيل المستخدم إليه بعد منح رمز الترخيص response_type=code: يُبيّن أنّ تطبيقك يطلب إذنًا بالحصول على رمز ترخيص scope=read: يُعيّن مستوى الوصول الّذي يطلبه المُستخدم الخطوة 2: يُرخّص المستخدم التّطبيق عندما ينقر المُستخدم الرّابط، يجب عليه أوّلًا تسجيل الدّخول إلى الخدمة، وذلك للتّحقق من هويّة المُستخدم (ما لم يكن قد سجّل دخوله من قبل). ثم تعرض عليه الخدمة ترخيص أو رفض وصول التّطبيق إلى حسابه. فيما يلي مثال عن صفحة ترخيص التّطبيق: هذه الصّورة مُلتقطة من صفحة ترخيص DigitalOcean، ونرى فيها التّطبيق "Thedropletbook App" يطلب إذنًا بقراءة حساب المُستخدم "manicas@digitalocean.com". الخطوة 3: يتلقّى التطبيق رمز التّرخيص إذا نقر المُستخدم "Authorize Application"، فإنّ الخدمة تُعيد تحويل وكيل المستخدم إلى رابط إعادة التّوجيه الّذي حدّده التّطبيق أثناء تسجيل المُطوِّر له، وتُرفق الخدمة مع الرّابط رمز التّرخيص. مثال على الرّابط (مُفترضين أنّ التّطبيق هو "dropletbook.com"): https://dropletbook.com/callback?code=AUTHORIZATION_CODE الخطوة 4: يطلب التّطبيق رمز الوصول (Access Token) يطلب التّطبيق من الخدمة رمز وصول، مُمرّرًا لها رمز التّرخيص مع تفاصيله، بما في ذلك كلمة سرّ العميل، والّتي تُرسل جميعها إلى رابط الحصول على رمز الوصول الخاصّ بالخدمة. فيما بلي مثال على طلب POST يُرسل إلى رابط رمز الوصول في DigitalOcean: https://cloud.digitalocean.com/v1/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL الخطوة 5: يتلقّى التّطبيق رمز الوصول إن كان التّرخيص سليمًا، فإنّ الواجهة البرمجيّة تردّ على الطّلب بجواب يحوي رمز الوصول (مع رمز إعادة تجديد الرّخصة، غير إلزاميّ) إلى التّطبيق. يبدو الجواب مثل هذا: {"access_token":"ACCESS_TOKEN","token_type":"bearer","expires_in":2592000,"refresh_token":"REFRESH_TOKEN","scope":"read","uid":100101,"info":{"name":"Mark E. Mark","email":"mark@thefunkybunch.com"}} أصبح التّطبيق الآن مُرخّصًا! وبإمكانه استخدام الّرمز للوصول إلى حساب المُستخدم عن طريق الواجهة البرمجيّة للخدمة، محدودًا بنطاق الوصول، إلى أن تنتهي مدّة الرّمز أو يُسحب التّرخيص. في حال أُصدر رمز إعادة تجديد الرّخصة (refresh token)، فبإمكان التّطبيق استخدامه للحصول على رمز وصول جديد في حال انتهى مدّة السّابق. الإذن الضّمنيّ يُستخدم نوع الأذون الضّمنيّ في تطبيقات الويب (التي تعمل في المتصفح) وتطبيقات الأجهزة المحمولة، حيث يصعب ضمان سرّية كلمة سرّ العميل. يقوم هذا النّوع من الأذون على مبدأ إعادة التّوجيه أيضًا، إلّا أنّ رمز الوصول يُعطى لوكيل المُستخدم ليقوم بدفعه إلى التّطبيق، وبهذا قد يُكشف للمُستخدم وللتّطبيقات على جهازه. لا يتضمّن سير التّرخيص في هذا النّوع هوّيّة التّطبيق، بل يعتمد على رابط إعادة التّوجيه (الّذي سُجّل في الخدمة) للوصول إلى هذا الهدف. لا يدعم هذا النّوع من الأذون رموز إعادة تجديد التّرخيص. يسير التّرخيص في هذا النّوع كما يلي: يُطلب من المُستخدم ترخيص التّطبيق، ثمّ يُمرّر خادوم التّرخيص رمز الوصول إلى وكيل المُستخدم، الّذي ينقله بدوره إلى التّطبيق. إن كُنت مُهتمًّا بالتّفاصيل، فتابع القراءة. سير التّرخيص الضّمنيّ الخطوة 1: رابط التّرخيص الضّمني يُعرض على المُستخدم رابط التّرخيص، الّذي يطلب رمزًا من الواجهة البرمجيّة، يبدو هذا الرّابط مُشابهًا لرابط رمز التّرخيص، باستثناء أنّه يطلب رمز token بدلًا من code (لاحظ نوع الجواب المطلوب "token"): https://oauth.example.com/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read ملاحظة: لا تدعم DigitalOcean حاليًا التّرخيص الضّمني، لذا ذكرنا رابطًا وهميًّا "oauth.example.com". الخطوة 2: يرخّص المُستخدم التّطبيق عندما ينقر المُستخدم الرّابط، يجب عليه أوّلًا تسجيل الدّخول إلى الخدمة، وذلك للتّحقق من هويّة المُستخدم (ما لم يكن قد سجّل دخوله من قبل). ثم تعرض عليه الخدمة ترخيص أو رفض وصول التّطبيق إلى حسابه. فيما يلي مثال عن صفحة ترخيص التّطبيق: نرى في الصّورة التّطبيق "Thedropletbook App" يطلب إذنًا بقراءة حساب المُستخدم "manicas@digitalocean.com". الخطوة 3: يتلقّى وكيل المُستخدم رمز الوصول مع رابط إعادة التّوجيه إذا نقر المُستخدم "Authorize Application"، فإنّ الخدمة تُعيد تحويل وكيل المستخدم إلى رابط إعادة التّوجيه الّذي حدّده التّطبيق أثناء تسجيل المُطوِّر له، وتُرفق الخدمة مع الرّابط رمز الوصول. مثال على الرّابط: https://dropletbook.com/callback#token=ACCESS_TOKEN الخطوة 4: يتبع وكيل المُستخدم مسار إعادة التّوجيه يتبع وكيل المُستخدم رابط إعادة التّوجيه مع احتفاظه برمز الوصول. الخطوة 5: يُرسل التّطبيق نصًّا برمجيًّا لاستخراج رمز الوصول يُعيد التّطبيق صفحة ويب تحوي نصًّا برمجيًّا بإمكانه استخراج رمز الوصول من رابط إعادة التّوجيه الكامل الّذي احتفظ به وكيل المُستخدم. الخطوة 6: يُمرّر رمز الوصول إلى التّطبيق يُنفّذ وكيل المستخدم النّصّ البرمجيّ ويُمرّر رمز الوصول المُستخرَج إلى التّطبيق. أصبح التّطبيق الآن مُرخّصًا! وبإمكانه استخدام الّرمز للوصول إلى حساب المُستخدم عن طريق الواجهة البرمجيّة للخدمة، محدودًا بنطاق الوصول، إلى أن تنتهي مدّة الرّمز أو يُسحب التّرخيص. ملاحظة: لا تدعم DigitalOcean حاليًا التّرخيص الضّمني، لذا ذكرنا رابطًا وهميًّا "oauth.example.com". الإذن بالوصول إلى كلمة مرور مالك المُحتوى في هذا النّوع من التّرخيص، يزوّد المستخدم التّطبيق مباشرةً باسم حسابه وكلمة مروره، ليستخدمها للحصول على رمز الوصول من الخدمة. يجب استخدام هذا النّوع من الأذون في الخوادم عندما لا تكون الأنواع الأخرى مُناسبة فقط. ويجب استخدامه فقط في حال كان التّطبيق موضع ثقة المُستخدم، كأن يكون تابعًا للخدمة ذاتها، أو أن يكون نظام التّشغيل على حاسوب المُستخدم هو ما يطلب الوصول. سير التّرخيص بالحصول على كلمة مرور المُستخدم بعد أن يُعطي المستخدم كلمة مروره للتّطبيق، يطلب التّطبيق رمز الوصول من خادوم التّرخيص. يُشبه طلب POST ما يلي: https://oauth.example.com/token?grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID إن كان اسم المُستخدم وكلمة المرور صحيحين، يُعيد خادوم التّرخيص رمز وصول للتّطبيق ويُصبح التّطبيق مُرخّصًا! ملاحظة: لا تدعم DigitalOcean حاليًا التّرخيص بالحصول على كلمة المرور، لذا ذكرنا رابطًا وهميًّا "oauth.example.com". الإذن بالوصول إلى كلمة مرور العميل في هذا النّوع من التّرخيص، يوفّر التّطبيق طريقة للوصول إلى حسابه الخاصّ على الخدمة. من الأمثلة الّتي يكون فيها استخدام هذا النّوع مُفيدًا أن يرغب التّطبيق بتحديث وصفه أو رابط إعادة التّوجيه المُسجّلين في الخدمة، أو أن يصل إلى بيانات أخرى حول حسابه على الخدمة عن طريق الواجهة البرمجيّة. سير التّرخيص بالحصول على كلمة مرور العميل يطلب التّطبيق رمز الوصول مُرسلًا مُعرَّفه وكلمة مروره إلى خادوم التّرخيص، فيما يلي مثال عن طلب POST: https://oauth.example.com/token?grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET إن كان مُعرّف التّطبيق وكلمة مروره صحيحين، يُعيد خادوم التّرخيص رمز وصول للتّطبيق ويُصبح التّطبيق مُرخّصًا باستخدام حسابه الخاصّ! ملاحظة: لا تدعم DigitalOcean حاليًا التّرخيص بالحصول على كلمة مرور العميل، لذا ذكرنا رابطًا وهميًّا "oauth.example.com". مثال على استخدام رمز الوصول بعد أن يحصل التّطبيق على رمز الوصول، إمكانه استخدام هذا الّرمز للوصول إلى حساب المُستخدم عن طريق الواجهة البرمجيّة للخدمة، محدودًا بنطاق الوصول، إلى أن تنتهي مدّة الرّمز أو يُسحب التّرخيص. فيما يلي مثال عن طلب يُرسل للواجهة البرمجيّة للخدمة باستخدام curl، لاحظ أنّه يتضمّن رمز الوصول: curl -X POST -H "Authorization: Bearer ACCESS_TOKEN""https://api.digitalocean.com/v2/$OBJECT" على فرض أنّ رمز الوصول سليم، فإنّ الواجهة البرمجيّة تُعالج الطّلب حسب ما صُمِّمت؛ وإلّا أعادت الواجهة خطأ "invalid_request"، كما يحدث عند انتهاء مدّة التّرخيص أو استخدام رمز خاطئ. سير الحصول على رمز إعادة تجديد الرُخصة يؤدّي استخدام رمز وصول بعد انتهاء مدّة صلاحيّته إلى "خطأ رمز غير سليم (Invalid Token Error)". في هذه النّقطة، يمكن استخدام رمز إعادة تجديد الرّخصة في حال أُصدَر مع رمز الوصول للحصول على رمز وصول جديد من خادوم التّرخيص. فيما يلي مثال على طلب POST للحصول على رمز وصول جديد مُستخدمين رمز إعادة تجديد: https://cloud.digitalocean.com/v1/oauth/token?grant_type=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&refresh_token=REFRESH_TOKEN الخاتمة إلى هناك نكون قد وصلنا إلى ختام دليل OAuth. من المُفترض أن لديك الآن فكرة جيّدة عن البروتوكول وكيف يعمل، ومتى يمكن استخدام كلّ نوع من الأذون. إذا أردت تعلّم المزيد عن OAuth 2، اطّلع على هذه المصادر القيّمة (بالإنكليزيّة): How To Use OAuth Authentication with DigitalOcean as a User or Developer How To Use the DigitalOcean API v2 The OAuth 2.0 Authorization Framwork ترجمة (بشيء من التّصرّف) لمقال Introduction to OAuth 2 لصاحبه Mitchell Anicas.
-
إذا التقى شخصان في قرى الهيمالايا، حيِّا أحدهما الآخر قائلًا: "هل جسدك معافى؟" وأما في اليابان فقد ينحنيان أحيانًا، وفي عُمان يطبع كلّ منهما قبلة على أنف الآخر بعد التصافح، في كمبوديا وتايلاند، يضمّ كلّ منهما يديه وكأنّه يدعو. كل هذه الوسائل هي "بروتوكولات" للتواصل، أي سلسلة بسيطة من الرموز ذات المعنى والّتي تمهّد لتبادل حديث مُفيد. في عالم الويب، لدينا بروتوكول فعّال جدًّا على مستوى التّطبيقات يُمهّد الحواسيب حول العالم لتبادل الأحاديث النّافعة، واسمه Hypertext Transfer Protocol، أو HTTP اختصارًا؛ وهو بروتوكول يُصنّف ضمن طبقة التّطبيقات فوق TCP/IP، وهو أيضًا بروتوكول للتواصل. كثيرًا ما يغيب شرح HTTP في دروس التصميم والتطوير للويب، وهذا أمرٌ مُخزٍ: ففهمه يُعينك في تحسين تفاعل المستخدم وتحقيق أداء أفضل للموقع وإنشساء أدوات فعّالة لإدارة المعلومات على الويب. هذا المقال هو الجزء الأول من سلسلة تهدف إلى تعليم أساسيّات HTTP، وكيف يمكن استخدامه بفعّاليّة أكبر. سنطّلع في هذا الدّرس على محلّ HTTP من الإنترنت. ما معنى بروتوكول تواصل؟ قبل الدّخول في التفاصيل، لنتخيّل موقفًا بسيطًا يحدث فيه تواصل بين طرفين، ولكي يحدث هذا التواصل، فإن على الطّرفين (برنامجين كانا أم جهازين أم شخصين... إلخ.) أن يتّفقا على: الصياغة (تنسيق البيانات) الدلالات (معلومات التحكم والتعامل مع الأخطاء) التوقيت (تطابق السرعة والتتالي) عندما يلتقى اثنان، فإنّهما يتفاهمان من خلال بروتوكل تواصل: ففي اليابان مثلًا، يؤدي أحدهما حركة جسدية، كأن يحني ظهره. وهذه هي الصياغة المعتمدة في التواصل. وفي عادات اليابان، تدل حركة الانحناء هذه (وحركات أخرى مشابهة) على التّحيّة. وبحركة انحناء أحد الشخصين للآخر تنطلق سلسلة من الأحداث بينهما مرتبة بتوقيت معيّن. يتركّب بروتوكل التواصل عبر الشبكات من المكوّنات ذاتها. فأمّا الصّياغة فهي سلسلة من الحروف كالكلمات المفتاحيّة المُستخدمة في كتابة البروتوكول، وأمّا الدلالات فهي المعاني المُرتبطة بكلّ من هذه الكلمات، وأمّا التوقيت فهو ترتيب تبادل هذه الكلمات بين الطّرفين. ما محلّ HTTP من الإنترنت؟ يقوم HTTP نفسه فوق بروتوكولات أخرى. فعند الاتصال بموقع ويب مثل www.example.org، يستخدم وكيل المستخدم (user agent) مجموعة بروتوكولات TCP/IP، والتي صُمّمت في عام 1970 مؤلّفة من 4 طبقات: طبقة الوصلة (Link)، والتي تصف الوصول إلى الوسيط المادّي (كاستخدام بطاقة الشبكة مثلًا) طبقة الإنترنت، والتي تصف كيفيّة تغليف البيانات وتوجيهها (IP أو Internet Protocol) طبقة النقل (Transport)، والتي تصف كيفية نقل البيانات من نقطة الانطلاق إلى الوجهة (TCP وUDP) طبقة التطبيقات (Application)، والتي تصف معنى وصياغة الرسائل المنقولة (HTTP) فـ HTTP إذًا هو بروتوكول على مستوى التطبيقات يقوم على الطبقات السابقة، لا تنسَ هذه الفكرة. يُساعد فصل هذا النّموذج في طبقات على تطوير أجزاءه بصورة منفصلة دون الحاجة لإعادة تصميمها جميعًا. فمثلًا، يمكن تطوير TCP، باعتباره بروتوكولًا في طبقة النّقل، دون الحاجة لتعديل HTTP كونه برتوكولًا في طبقة التّطبيقات. لكن الواقع العمليّ يجعل التفاصيل أكثر تعقيدًا عند الحاجة للوصول إلى تواصل ذي أداء عالٍ. سنركّز في الأجزاء الأولى من هذه السّلسلة على فصل الطّبقات كما هو مُعرَّف في نموذج TCP/IP. صُمِّم HTTP بغرض تبادل المعلومات بين برنامجين من خلال رسائل تُسمّى رسائل HTTP، وتؤثّر طريقة تشكيل هذه الرسائل في العميل (client) والخادوم (server) والأطراف الوسيطة (كالخواديم الوكيلة proxies). لنتواصل مع خادوم! يُعتبر المنفذ رقم 80 المنفذ المبدئيّ للاتّصال بخواديم الويب، ويمكن التأكّد من ذلك بتجربة نُجريها من الطّرفيّة. افتح الطّرفية (أو سطر الأوامر) وجرّب الاتصال بـ www.opera.com على المنفذ 80 مُستخدمًا الأمر التالي: telnet www.opera.com 80 من المُفترض أن يكون الناتج: Trying 195.189.143.147... Connected to front.opera.com. Escape character is '^]'. Connection closed by foreign host. كما نرى فإن الطرفيّة تحاول الاتصال بالخادوم ذي عنوان IP 195.189.143.147. إن لم نفعل شيئًا آخر سيغلق الخادوم الاتصال بنفسه. من الممكن بالطّبع استخدام منفذ آخر بل وحتّى بروتوكول تواصل آخر، ولكن هذه هي الإعدادات الشّائعة. لنتحدّث بلغة HTTP! لنحاول ثانية التواصل مع الخادوم. أدخل الرسالة التالية في الطرفية (أو سطر الأوامر): telnet www.opera.com 80 ما إن يُؤسّس الاتصال، اكتب رسالة HTTP التالية بسرعة (قبل أن يُغلق الخادوم الاتصال بنفسه)، ثم اضغط Enter مرّتين: GET / HTTP/1.1 Host: www.opera.com تُحدّد هذه الرسالة: GET: أي أننا نريد "الحصول على" تمثيل البيانات. /: أي أنّ المعلومات التي نريدها مخزنة في جذر الموقع. HTTP/1.1: أي أننا نتحدث ببروتوكول HTTP ذي الإصدارة 1.1. Host:: أي أننا نريد الوصول إلى الموقع المُحدّد. www.opera.com: اسم الموقع هو www.opera.com. على الخادوم الآن أن يُجيب طلبنا. من المفترض أن تمتلئ نافذة الطرفية بمحتوى مشابه لما يلي: HTTP/1.1 200 OK Date: Wed, 23 Nov 2011 19:41:37 GMT Server: Apache Content-Type: text/html; charset=utf-8 Set-Cookie: language=none; path=/; domain=www.opera.com; expires=Thu, 25-Aug-2011 19:41:38 GMT Set-Cookie: language=en; path=/; domain=.opera.com; expires=Sat, 20-Nov-2021 19:41:38 GMT Vary: Accept-Encoding Transfer-Encoding: chunked <!DOCTYPE html> <html lang="en"> ... يقول الخادوم هنا: "أنا أتحدث HTTP الإصدارة 1.1. نجحَ طلبك، لذا أجبت بالرمز 200." الكلمة OK ليست إلزامية والهدف منها شرح معنى الرمز للبشر - وهي تُشير في حالتنا إلى أن الأمور تسير على ما يرام وأن رسالتنا قُبلت. يلي ذلك سلسلة من "ترويسات HTTP" التي تُرسل لتصف الرسالة، وكيف يجب أن تُفهم. أخيرًا نجد محتويات الصفحة المُستضافة على جذر الموقع، والّتي تبدأ بـ <!DOCTYPE html>.
-
كان ختام المقالة السّابقة قولُنا أن بروتوكول HTTP يدير التّفاعل بين عميل وخادوم، وقد شرحنا فكرة ترويسات HTTP. سيكون لدينا الكثير مما يُقال عن هذه الترويسات في أجزاء تالية من هذه السّلسلة، فهذه الترويسات تؤثّر في التّفاعل بين الطّرفين وفي أداء الموقع. أمّا اليوم، فسنطّلع على جانب لا يقلّ أهمّيّة عن التّرويسات، وهو رموز إجابات HTTP. نزهة في الشوارع خرجت ذات صباح قاصدًا مقهى لأقرأ كتابًا، لكنّني وجدت المقهى مُغلقًا حينها، وقد كُتب على لوحة على الباب أنّ احتفالًا يُقام خلال هذا الأسبوع، ولذلك فإنّ المقهى سينتقل مؤقتًا ليُقدّم القهوة في شاحنة الطّعام (التي سمّوها "307") قرب النهر. ذهبت إلى ذلك المكان واستمتعت بشرب القهوة. قرّرت بعدئذٍ التجوّل في مكتبتي المفضّلة في المدينة، فوجدتها مُغلقةً كذلك، إلّا أنّني رأيت لوحة على الباب تقول أن المكتبة ستتوسع ولذلك انتقلت بشكل دائم إلى مبنى جديد في 301 شارع برنرز-لي. لم يُزعجني ذلك، فالمكان قريب. ذهبت إلى هناك فاستقبلني الموظّفون بالتّرحاب: "200 سلامة!". حسنًا، أنا أبالغ قليلًا، لكنّك فهمتني! في طريقي إلى البيت، وجدت متجرًا مهجورًا غطّى الغبار أبوابه في 410 شارع برنرز-لي، وقد أُلصقت ورقةٌ على الباب تقول أنّ صاحب المحلّ تقدّم بطلب إشهار الإفلاس واضطّر إلى إغلاق المتجر، إلى الأبد. وكأنّ العجائب لم تنتهِ اليوم، إذ رأيت في نهاية 500 شارع برنرز-لي مبنى من 4 طوابق وقد انهار بالكامل. ما الذي حدث هنا؟! لم يكن يومي سيئًا بالمجمل، لذا قرّرت أن أكمل يومي بكتابة مقال عن رموز HTTP الّتي تُرسلها الخواديم إلى العملاء الّذين يرسلون الطّلبات. صياغة جواب HTTP وسطر الحالةتطرّقنا في المقال السّابق إلى السّطر الأول من صيغة الطّلبات الّتي يُرسلها العميل (بما في ذلك أفعال HTTP). وسنركّز الآن على السّطر الأول من رسالة الجواب الّتي تصل من الخادوم، ومعاني الرّموز المختلفة الّتي تظهر في هذا السّطر. لاحظ التّشابه بين نوعي الرّسائل (الطّلبات والإجابات). فكما ينصّ توثيق الإصدارة 1.1 من HTTP: إما إن تكون رسالة HTTP طلبًا من العميل إلى الخادوم أو جوابًا من الخادوم للعمل. من حيث الصّياغة، لا يختلف نوعا الرّسائل إلى في السّطر الأوّل، والذي إمّا أن يكون سطر طلب (للطلبات) أو سطر حالة (للإجابات)، وفي خوارزميّة تحديد طول متن الرّسالة (القسم 3.3). يُدعى السّطر الأول في الجواب إذًا سطر الحالة. يبدأ السّطر بإصدارة بروتوكول HTTP ثمّ مسافة ثم رمز من ثلاثة أرقام، ثم مسافة ثمّ جملة تشرح الرّمز، كهذا المثال: HTTP/1.1 200 OKالجملة القصيرة الأخيرة غير إلزامية وعلى العملاء تجاهلها، ولا ينبغي أن يستخدمها برنامج بغرض تفسير الجواب. لنطّلع الآن على بعض أكثر رموز الحالة شيوعًا وما يعنيه كلّ رمز منها. رموز الحالة في HTTP200، كلّ شيء على ما يرام! في كلّ مرّة يريد شخصٌ ما زيارة الصّفحة الرئيسيّة لموقع Opera، يُرسل العميل طلبًا إلى http://www.opera.com/ برسالة مثل هذه: GET / HTTP/1.1 Host: www.opera.com Accept-Language: fr User-Agent: BrowseAndDream/1.0يُحلّل الخادوم الرّسالة الّتي وصلته من العميل ويُرسل جوابًا بناء على ما فهمه من الرابط والترويسات. وكما ذكرنا في المقالتين السّابقتين، يكون الهدف الأهمّ هو إدارة التّواصل بين الطّرفين بما يحقّق أقصى فائدة لكليهما. إن فهم الخادوم الرّسالة، فإنّه يرسل رسالة تبدأ بـ200 OK، أي أنّ كلّ شيء على ما يُرام. تحوي الرسالة بضع ترويسات إجابة ثمّ محتوى الصّفحة، والّذي قد يختلف بناءً على ترويسات الطّلب، فلا إجابة مُطلقة. فكما في كل تفاوض، يجري حوارٌ بين الطّرفين للوصول إلى أفضل تسوية. فيما يلي مثالٌ عن إجابة على الطّلب السّابق: HTTP/1.1 200 OK Date: Fri, 24 Aug 2012, 13:56:44 GMT307، انتقلتُ مؤقّتًا إلى مكان آخر يمكن للخادوم أن يجيب العميل برسالة تبيّن أنّ المحتو قد انتقل مؤقتًا إلى مكان آخر. ويفيد هذا عندما تريد إعادة توجيه العميل إلى صفحة مُعيّنة لفترة قصيرة. افترض مثلًا موقعًا يُعطي توقّعات الطقس لتاييبي، وقد شبّ إعصار هائل مؤخّرًا فيها. سيكون من المفيد إعلام المُستخدمين بوقوع هذا الإعصار حتى هدوئه. قد يكون الطّلب مثل هذا: GET /taiwan/weather/today HTTP/1.1 Host: meteo.example.orgقد يرغب الخادوم بإجابة العميل قائلًا: "سأنقلك إلى صفحة أخرى تُعطيك معلومات مفصّلة عن الأزمة الحاليّة في تاييبي". قد تبدو الإجابة مثل هذه: HTTP/1.1 307 Temporary Redirect Date: Fri, 24 Aug 2012, 13:56:44 GMT Location: http://meteo.example.org/taiwan/weather/crisisيتبع المتصفح عادةً الوجهة الجديدة المذكورة في سطر Location. يمكن أن يطلب الخادوم إعادة التّوجّه إلى نطاق آخر على الويب. وحالما تنتهي الأزمة، يمكن للخادوم إزالة إعادة التّوجيه. ينبغي ألّا يتذكّر العميل إعادة التّوجيه للأبد. فهذا مُهمّ في حالة الإشارات المرجعيّة وسجل التصفّح. من الممكن تصميم برنامج يُدير عمليّات إعادة التّوجيه هذه بطريقة مُفيدة. لا يرى المُستخدم إعادة التّوجيه في معظم المتصفّحات، ولكن من الممكن إرسال متن مع جواب إعادة التّوجيه يعرض على المستخدم رسالة تحوي رابطًا للمكان الجديد يُسمح للمُستخدم بنقره. 301، تغيّر العنوان بشكل دائم عند إدارة المعلومات على موقع ويب، قد نحتاج إلى إعلام العميل (ومستخدميه) أن الصّفحة المطلوبة قد انتقلت بشكل دائم. ففي الشّركات، يُعاد تنظيم الأقسام أحيانًا بعد الاتّحاد مع شركة أخرى أو عند تغيّر الأولويّات. لنفترض مثلًا أن وحدة الآلات الكهربائيّة في شركة تقنية قد ضُمَّت إلى قسم الإلكترونيّات. وعندها يمكن إعادة توجيه عميل يطلب: GET /section/electromech/about HTTP/1.1 Host: inc.example.comإلى: HTTP/1.1 301 Moved Permanently Date: Fri, 24 Aug 2012, 13:56:44 GMT Location: http://inc.example.com/section/electronic/aboutالفرق بين الرمز 307 الّذي شرحناه في الفقرة السّابقة، والرّمز 301، أنّ التّغيّر في العنوان دائم في حالة الرّمز الثّاني، وهي رسالة واضحة من الخادوم للعميل تطلب منه أن يُغيّر الإشارات المرجعيّة المحفوظة لديه إلى العناوين الجديدة. يمكن للمتصفّح تنفيذ ذلك من تلقاء نفسه أو بعد استشارة المستخدم. لإعادة توجيه الروابط القديمة فائدتان مُباشرتان. الأولى هي كسب ثقة المستخدمين بموقعك، بأن تُبدي اهتمامك بالمُحافظة على المعلومات الّتي تستضيفها. والثّانية هي استقرار الموارد، فالمواقع الّتي تُعرف بمحافظتها على الرّوابط تكون أكثر احتمالًا لأن تُشير إليها مواقع أخرى على المدى البعيد، ممّا يزيد ترتيب الموقع في مُحرّكات البحث. 410، وداعًا يا صديقي العزيز! تحتاج بعض المواقع أحيانًا إلى إبلاغ العميل باختفاء المعلومات الّتي كانت موجودة على رابط مُعيّن للأبد. وقد يكون لهذا مُبرّراته. نحن نعلم أن الروابط الجيّدة لا تتعطّل؛ ولكنّ الرّمز 410 Gone هو الوسيلة الوحيدة المناسبة لتعطيلها. لنكن أكثر دقّة: هذا الرّمز هة طريقة لإخبار المستخدمين أن المحتوى الّذي كان موجودًا من قبل على هذا الرابط قد حُذِفَ عمدًا. وهذا معناه أن الخادوم يطلب من العُملاء الّذي يقصدون هذا الرّابط ألّا يتذكّروه. ففي متصفّح يستخدم الإشارات المرجعيّة وسجّلات التّصفّح، يُعتبر هذا الرّمز إبلاغًا للمتصفّح بسلامة حذف هذا الرّابط. افترض شبكة اجتماعيّة يُطلب فيها الوصول إلى صفحة مُستخدم: GET /people/jeanpaulsartres HTTP/1.1 Host: socialnetwork.example.comقرّر المستخدم أن يُغادر شبكتك الاجتماعيّة ويُغلق حسابه، قد تُريد أن تُبلغ غيره من المستخدمين الّذين يطلبون صفحته من سجلّ المتصفّح أو إشاراته المرجعيّة: HTTP/1.1 410 Gone500، يا للمصيبة! قد يتعذّر على الخادوم إجابة الطّلب لسبب مجهول. لا يتدخّل HTTP على الإطلاق في تفاصيل عمل الموقع، مثل طريقة تخزين قواعد البيانات على الخادوم، أو كيف يجلب الخادوم البيانات ويُعالجها. ربّما توقّف الطّلب عند برنامج مُعيّن على الخادوم ولم يصل الجواب، وعندها يُبلغ الخادوم العميل ومستخدمه عن وقوع خطأ ما غير معروف بجواب مثل هذا: HTTP/1.1 500 Internal Server Errorاستخدام سطور الحالة في الإجابات الّتي تُرسلها الخواديمعند تصميم نظام لإدارة المحتوى، يكون من الضّروري فصل الطّبقات بصورة موارد وروابط إلى هذه الموارد، فهذا مُفيد عند إجابة طلبات العملاء بالمعلومات الصّحيحة، وتقديم المحتوى للبرامج أو للبشر هو شيء جوهريّ في صفة الخواديم. ولأنّ المعلومات تتغيّر وتتطوّر،فإنّ تصميم الخواديم بما يراعي هذه النّقطة يُعطيها مرونة أكبر. لا تهدف هذه السّلسلة إلى شرح تفاصيل تطبيق إجابات الخواديم من النّاحية البرمجيّة، ولكنّنا سنستعرض مثالين يُفيدان كنقطتي انطلاق، على الرّغم من أنّهما قد لا يُفيدان في حالة المواقع الضّخمة الّتي تضمّ آلاف الرّوابط. إعادة التّوجيه في Apacheفي حال أردت إعادة توجيه http://inc.example.com/section/electromech/about إلى http://inc.example.com/section/electronic/about، يمكن إضافة ملف .htaccess في جذر الموقع يحوي التّعليمات التّالية: RewriteEngine On RewriteBase / RewriteRule ^/section/electromech/about /section/electronic/about [L,R=301]مُلاحظة: هنالك طرق أخرى لتنفيذ هذا الغرض، كاستخدام httpd.conf أو قواعد البيانات أو من خلال النّصوص البرمجيّة... إلخ. واختيار الطّريقة المناسبة يعتمد على تصميم النّظام. إعادة التّوجيه في nginxخادوم Nginx هو الآخر شائع الاستخدام، وخصوصًا على شبكات توفير المحتوى (CDNs). يمكن إعادة كتابة المثال السّابق لاستخدامه مع nginx: server { listen 80; server_name inc.example.com; rewrite ^/section/electromech/about http://inc.example.com/section/electronic/about permanent; }تصنيف رموز HTTPتعرّفنا على بضع رموز HTTP فيما سبق، ولكنّها أكثر من ذلك، وبعض هذه الرّموز ذائع الصّيت مثل 404 Not Found، وبعضها مغمور لا يُرى كثيرًا. وفي كلا الحالتين يمكن الاستعانة بالرّقم الأوّل للرّمز لأخذ فكرة عن معناه، كون هذا الرقم يُشير إلى العائلة الّتي ينتمي إليها الرّمز: 1xx (بيان): وصل الطّلب، وتجري مُعالجته.2xx (نجاح): وصل الطّلب وفُهم وقُبل.3xx (إعادة توجيه): يُطلب إجراء تالٍ لإكمال الطّلب.4xx (خطأ من جهة العميل): صياغة الطّلب خاطئة أو يتعذّر تحقيقه.5xx (خطأ من جهة الخادوم): فشل الخادوم في تحقيق طلب يبدو سليمًا.الخلاصةإلى هنا نكون قد وصلنا إلى نهاية دراستنا لرموز حالة HTTP. أحثّك على الاطّلاع على كلّ رمز والتّعرّف على فائدته. لبعض هذه الرموز تأثيرات خاصّة على التّخزين المؤقّت وعلى متن رسالة HTTP؛ سنُلقي نظرةً على التّخزين المؤقت لاحقًا. تذكّرتُرسل الخواديم رموز حالة HTTP لتزويد العميل بمعلومات سريعة عن الجواب.تؤثّر رموز HTTP في التّخزين المؤقّت ومُعالجة الرّوابط من جهة العميل.تُصنّف رموز HTTP ضمن عدّة مجموعات.ترجمة (بشيء من التّصرّف) لمقال HTTP: Response Codes لصاحبه Karl Dubosy.
-
تعلمنا في الجزء السابق أن HTTP بروتوكول على مستوى التطبيقات. حان الوقت لنفهم كيفية استخدام هذا البروتوكول للتواصل بين العميل والخادوم. جلب الأشياء من الويب تذكر أن عميل HTTP (وهو المتصفح عادةً) هو الطرف الذي يبدأ بإرسال الطلب إلى الخادوم. يسمح بروتوكول HTTP للعميل بالتعبير عن نيّته من خلال بضعة مُكوّنات: الرابط (URI)، وأفعال HTTP، وترويساته. تسمية الأشياء تمثّل الروابط (URIs) حجر الأساس في الويب، لأنّها تحل مشكلة مهمّة على مستوى الإنترنت بكاملها، وهي مشكلة منح الأشياء مُعرّفًا تنفرد به على الشّبكة. افترض أنّك سألت شخصًا أن يجلب لك شيئًا ويُحضره إليك، يمكن عدّ الطرق الممكنة للطلب على الأصابع. فعادةً ما تُعرّف الكلمات الّتي تستخدمها الشيء الّذي تريده. بإمكانك أن تطلب من صديقك قائلًا: "اجلب لي الكتاب." قد يجيبك صديقك: "حاضر. ولكن أي كتاب؟". فتقول أنت: "الكتاب في الغرفة الأخرى." فيذهب صديقك إلى الغرفة ويسأل: "أي كتاب قلت؟" فتقول أنت وقد شعرت بالضّيق: "الأخضر!" ليقول صديقك: "تمهّل لحظة... هناك كتابان أخضران في الغرفة!" وعندها تنهض لتحضر الكتاب بنفسك. كان الأمر ليكون أكثر بساطة لو أننا وحدنا طريقة نُحدّد فيها الأشياء بطريقة مميّزة للوصول إليها لاحقًا. إحدى الوسائل الممكنة هي الاعتماد على الذاكرة. كيف نعطي الأوامر لشخص ما ليحضر إلينا الغرض المطلوب؟ لنُنشئ نظامًا لذلك: قص ورقات صغيرة أو استخدم ورق الملاحظات اللّصّاق. ضع هذه الأوراق على الأغراض في الغرفة المجاورة أو على الطّاولة (كالكتب مثلًا). اكتب مُعرّفًا مُميِّزًا على كل ورقة. كرّر العملية في غرفة مجاورة أو على طاولة مجاورة. تذكّر أن هذا النّظام لا يقتصر على أغراضك، بل يمتد ليسمح بنوعٍ من التّواصل بين الأغراض جميعها. طبّقت هذا النّظام على أغراضي، فكتبت على كل قطعة ورق واحدًا من المُعرّفات التالية: myRoom.org/table/book/001 myRoom.org/shelf/book/002 otherRoom.org/cup/001 otherRoom.org/flower/001 otherRoom.org/book/001 أعتقد أنك الآن فهمت ما أقصد. لدينا الآن نظام من اللصاقات الّتي تستخدم لتحديد كل شيء في المكان بدقة. في الويب، نحن نتعامل مع فضاء معلومات واللصاقات المُستخدمة ليست سوى الروابط (URIs). الوصول إلى الأشياء المُسمَّاة شرحنا كيف يُبنى طلب HTTP في المقال السابق من خلال الطرفية. استخدمنا بناءً بسيطًا مع فعل HTTP المُسمّى GET مع ترويسة واحدة: Host. GET / HTTP/1.1 Host: www.opera.com القائمة الكاملة لأفعال HTTP الحالية هي: OPTIONS، GET، HEAD، POST، PUT، DELETE، TRACE، CONNECT. لكل فعل دورٌ مختلف عن الأفعال الأخرى وسنشرح ذلك في المقالات التالية. أكثر الأفعال استخدامًا هو GET، ففي كلّ مرة نُدخل عنوان HTTP في شريط العناوين في المتصفح، فإنّنا نرسل طلب GET إلى خادوم. في عالم الويب يُرسل العميل معلومات أكثر (المزيد من ترويسات HTTP) إلى الخادوم للتفاهم على المطلوب. يستغل الخادوم هذه المعلومات ليُعدّل الجواب بما يناسب الترويسات. تتوفّر أداة عمليّة جدًا في Opera Dragonfly لإنشاء طلبات HTTP مُخصّصة وفحص إجابة الخادوم. يمكنك إيجادها في قسم Network في تبويب "Make Request". هنالك ثلاث مناطق في تبويب Make Request: الرابط (URL): مُعرّف المُحتوى (أو عنوان الويب) متن الطّلب (Request body): ما سيُرسله العميل إلى الخادوم (يُرسل الزّر "Send request" الطّلب إلى الخادوم عبر الشّبكة) الجواب (Response): جواب الخادوم بعد إرسال الطّلب تخصيص طلب HTTP انسخ http://www.opera.com/ إلى قسم URL. انسخ والصق طلب HTTP التّالي إلى قسم "Request body" في تبويب Network. أضفنا الترويسة Accept-Language إلى طلب HTTP السابق. اضغط الزر "Send request". GET / HTTP/1.1 Host: www.opera.com Accept-Language: en سيُجيب خادوم Opera بجواب HTTP مؤلّف من بضع ترويسات يليها محتوى المستند. قد تحتاج إلى تمرير النافذة، لأن الجواب قد يكون طويلًا. لاحظ أن المُستند باللغة الإنكليزيّة، ليس فقط من حيث اللغة الّتي كتب بها، بل أيضًا يُنصّ على ذلك صراحةً في خاصّة lang على ال عنصر html: <!DOCTYPE html> <html lang="en"> لنُجرّب الفرنسيّة: GET / HTTP/1.1 Host: www.opera.com Accept-Language: fr سُيجيب الخادم هذه المرة بالفرنسيّة، ويتبيّن ذلك في نص المستند وفي مصدره: <!DOCTYPE html> <html lang="fr"> لاحظ أنّنا استخدمنا الرابط نفسه بالضّبط (http://www.opera.com/) ولكنّنا تلقّينا إجابتين مُختلفتين لا لشيء إلا لأننا غيّرنا الترويسة Accept-Language. لاحظ أيضًا أنّ الخادوم أجاب بترويسات كثيرة تُعطينا معلوماتٍ عن حالة المحتوى ونوعه... إلخ. يسمح هذا للعميل بتعديل أسلوب معالجة المستند. يمكنك تجربة لغات مُختلفة مثل اليابانية (ja) والألمانية (de)... إلخ. ما الذي يحدث إن طلبنا لغة غير موجودة على الخادوم؟ جرّب مثلًا الصّينيّة (zh): GET / HTTP/1.1 Host: www.opera.com Accept-Language: zh ستتلقى النسخة الإنكليزية من الموقع. هل هذا مُحيّر؟ الحقيقة أنّ هذا الأمر يعتمد على تصميم الموقع ذاته. فقد يُصمم جواب HTTP بأسلوب آخر، كأن يُجيب الخادوم "لا، ما من نسخة صينية من الموقع لدينا"، أو "ليست لدينا نسخة صينية، ولكن لدينا اللغات التالية: ...). ولكن فريق تجربة المستخدمين في Opera قرر إرسال النسخة الإنكليزية من الموقع عند طلب لغة غير مُتوفّرة. المسألة مسألة اختيار، فلا قاعدة تُفرض على المواقع بهذا الشأن. ولهذا السّبب أقوم عادةً بتعليم مُصمّمي تجربة الاستخدام ومُطوّري الواجهات بعض أساسيّات HTTP، فهو بروتوكول يتوسّط التفاعل بين العميل والخادوم، وعليه فإنّ فهمه يُساعد في تصميم تفاعلات ذات معنى عند بناء المواقع، وذلك للبشر والآلات معًا (كالبرامج الّتي تستخدم الواجهات البرمجيّة (APIs) وما شابهها... إلخ). تذكّر URI: نظام لتعريف المعلومات على الشبكة. أفعال HTTP: يتضمّن البروتوكول حاليًا الأفعال التّالية: OPTIONS، GET، HEAD، POST، PUT، DELETE، TRACE، CONNECT. وقد تعرّفنا في هذه المقالة على أكثرها استخدامًا وهو GET. ترويسات HTTP:** الترويسات هي بيانات إضافية يُرسلها العميل لإعطاء معلومات أكثر عن البيانات المُتبادلة بين العميل والخادوم. تُفيد بعض هذه الترويسات الخادوم بحيث يختار الأسلوب الأفضل للإجابة. ترجمة (بشيء من التّصرّف) لمقال HTTP: Let’s GET It On! لصاحبه Karl Dubosy.
-
أصبحت الفترة التي تزامنت مع ظهور الوسائل والطرق الجديدة التي يحاول المطورون استخدامها لإقناع الزائرين بالصور المتخصصة والمحتوى الديناميكي وإضافة الفيديو فترةً مهمة لتحميل صفحة الموقع ومصدر قلق دائم لمطوري الويب، خاصةً تلك الوسائط التي تحتاج وقت كبير في التحميل. وقد يظهر هذا القلق واضحًا عند إضافة أي محتوى جديد على اختلاف نوعه إلى صفحة الموقع، وهنا يتطلب من الموقع الخاص بك إنشاء طلبيات HTTPS (بروتوكول نقل النص التشعبي الآمن) إضافية تعمل بدورها على إبطاء موقعك بشكل تدريجي. سوف أتحدث في هذا المقال عن طلبيات خادم HTTPS، وعن ماهية الأدوات التي يجب استخدامها لتتبع هذه الطلبيات وأيضًا سوف أوضح الطرق التي يمكنك بها تقليص تلك الطلبيات داخل موقع ووردبريس الخاص بك. ما هي طلبيات خادم HTTPs وهل لها تأثير على تجربة المستخدم؟ بالطبع لا توجد هناك أهمية أكبر من أهمية تجربة المستخدم التي تعمل على جذب الزوار للموقع والاشتراك فيه أو شراء منتجاتك، أو التعرف على المزيد من المعلومات حول خدماتك. فهنا يظهر واضحًا جدًا أن أي خطأ بسيط يمكن أن يعرّض هذه التجربة للخطر فمثلًا لو كان لديك صفحة ويب تستغرق بضع ثوانٍ قليلة للتحميل، فهذا وحده كافٍ أن يعرّض معدل التحويل لديك للخطر. لذا ولتجنب ذلك، عليك التعرف على هذه المعلومات حول طلبيات خادم HTTPS ولماذا تحدث. ففي كل مرة يزور شخص ما موقع الويب الخاص بك أو إحدى صفحاته (وركّز هنا في عدد الصفحات الموجودة على موقعك)، إذ يقدّم متصفحه طلبًا إلى خادم موقع الويب الخاص بك وهذا يتكرر مع كل صفحة يقوم بزيارتها. وهنا تكمن مسؤولية موقع الويب الخاص بك في إرسال كل ملف بما يحتوي عليه (النصوص والصور التي عادة ما يشتمل عليها أغلب المواقع بالإضافة إلى الفيديو، وملفات CSS، وملفات جافاسكربت، …إلخ) ويتلقى كل ملف من تلك الملفات طلب خادم منفصل. وبعد أن تعالج جميع طلبيات الخادم وتنقل الملفات إلى المتصفح، يمكن تحميل موقع الويب الخاص بك على الشاشة، ولكن تخيل ماذا سوف يحدث إذا كان موقع Wordpress الخاص بك يحتوي على عشرات أو حتى مئات الملفات لإرسالها إلى متصفحات من يزوره؟ توقع فعليًا زمن تحميل الصفحات، بالطبع هذا شيء غير مستحب إن كان الزمن كبيرًا! وقد يزداد الأمر سوءًا بشكل كبير مع تزايد شعبية الموقع وتلقي طلبيات خادم HTTPS كثيرة في وقت واحد. مثال على ذلك: 40٪ من الناس لا يتحملون الانتظار وقد يفقدون صبرهم إذا كان عليهم الانتظار أكثر من ثلاث ثوان لتحميل الصفحة. و قد أشارت دراسة كيس ماتريكس إلى أن التأخير لمدة ثانية واحدة في استجابة الصفحة عندما يتفاعل الزائر معها قد يكلف ما يصل إلى 7٪ من التحويلات؛ لذا، تحتاج إلى العثور على طريقة لتقليص عدد الملفات التي يجب إرسالها إلى المتصفح إذا كنت تريد أن تظل أوقات التحميل هذه مقبولة. فمن غير المعقول أن يكون الحل هو تقليل عدد الصور أو المحتوى الديناميكي أو الانتقال إلى الحد الأدنى من التصميم الخاص بك بحيث تخسر بذلك ميزة العرض الخاصة بموقعك و يصبح الأمر مملًا للغاية. بالرغم من أهمية حجم وكمية الملفات، إلا أنه يتوفر هناك العديد من الطرق في ووردبريس للتغلب على ذلك. الأدوات الخاصة بتتبع طلبيات خادم HTTPS وما يتعلق به من حسن الحظ أن هناك عدد من الأدوات تساعدك في تخطي عقبة تخمين السبب وراء ظهور شاشة الموت البيضاء لدى زوار موقعك ومعرفة ما يسبب ذلك. وتعمل أيضًا على تتبع مصدر التأخر في أوقات تحميل موقعك. أعرض هنا إليك بعض الأدوات المجانية والموثوقة. أدوات التطوير في كروم إذا كنت تريد رؤية دقيقة ومتعمقة في المتصفح كروم للمدة التي يستغرقها كل عنصر وملف يعالج على موقع ووردبريس الخاص بك. ابدأ أولًا بفتح نافذة متصفح جوجل ثم انتقل إلى صفحة الإعدادات التي تسمى أدوات المطور (Developer Tools) كما يظهر في الصورة. ستفتح عند الضغط عليها لوحة تحكم جديدة على الجانب الأيمن من الشاشة. حينئذ اضغط فوق علامة التبويب Network "الشبكة"، ومن هنا ستتمكن من معرفة الإجراءات التي تحدث في صفحتك. وستتمكن أيضًا من البحث بحثًا دقيقًا في توقيت كل ملف على حدة للتأكد لمعرفة أيها قد يكون سببًا في زيادة الضغط (الحمل) على صفحتك. أداة PageSpeed Insights لتحليل الأداء والسرعة من غوغل هذه الأداة ليست الوحيدة بالطبع التي تقدمها جوجل لمساعدتك في اكتشاف المشكلات المتعلقة بطلبيات خادم HTTPS من الناحية المثالية، فإذا كنت من مستخدمي أدوات التطوير فمن الواجب عليك الاستفادة من الأداة PageSpeed Insights التي يجب أن تكون ضمن قائمتك. تحلل PageSpeed إحصاءات محتوى صفحة الويب ثم تقدم اقتراحات لتحسين سرعة تلك الصفحة. انتقل إلى صفحة PageSpeed Insights وضع رابط الصفحة التي تريد تحليلها وسوف تقدم لك نتائج تفصيلية تقيّم فيها أداء الصفحة على الجوال وكذلك على سطح المكتب. يقدم لك كل تقييم من هذه التقييمات درجة من 100 تبين مدى جودة الأداء ومن ثم يقدم لك نصائح حول كيفية تحسين موقعك لتحسين الأداء. أداة GTmetrix أداة GTmetrix هي أداة تقييم واختبار سرعة الموقع وستوفر لك درجة تقيِّم موقع الويب الخاص بك. وتتميز أداة GTmetrix أنها تتعامل في عملية شرح أداء موقعك بطريقة أكثر شمولًا وثقة من جوجل لذلك، بالرغم من ظهور العلامات الحمراء و الصفراء (وهي ليست جيدة)، إلا أنه يمكنك التمرير فوق كل نقطة من نقاط البيانات ومعرفة متوسط الدرجات وأوقات التحميل. وهذا سيعطي فكرة أكثر واقعية حول مستوى أداء صفحات موقعك. عند تقييمك من GTmatrix، تتلقى نصائح قياسية حول كيفية تحسين السرعة والأداء لصفحتك. كل تلميح يظهر بجانبه الدرجة المطابقة، وهذا يتيح لك معرفة المكان الذي أنجزت فيه الأمور بشكل جيد، وتعطي مقترحات للتحسين. وإذا كنت تريد المزيد من المساعدة في تلك المناطق الأضعف، فما عليك سوى النقر على السهم المتجه للأسفل وسيخبرك بالملفات التي يمكن أن تستخدم بعض الأعمال. أداة Pingdom الأداة Pingdom تتشابه إلى حد كبير مع أداة GTmetrix في عملها و كيفية تقديم المعلومات. وقد تجد أن الاختلاف الرئيسي بين الأداتين هو في السرعة التي توفر بها نتائجها وأيضًا الواجهة هذه أجمل قليلًا. و لكن من ناحية أخرى، ستتلقى نفس التقييم الدقيق تقريبًا من كلا الأداتين وهذا هو بالضبط ما تحتاجه إذا كنت تحاول توفير الوقت في تقييم مشاكل موقعك وتريد تضييق نطاق ما لا يعمل. الأداة WebPageTest لن يمر ذكر أدوات اختبار صفحات الويب دون ذكر الأداة WebPageTest هنا. مع أن الموقع قليل الشكوك والنتائج ليست سهلة القراءة مثل بعض الأدوات الأخرى، إلا أنني أحب الرسم البياني الشريطي المستخدم لعرض المدة التي يستغرقها كل ملف للتحميل. رغم أنه قد يكون هناك قدر هائل من البيانات في هذه الصفحة ولا توجد نصائح حول كيفية حل مشكلات التباطؤ المحددة، ما زلت أعتقد أن طريقة عرض العناصر الأثقل جيدة نوعًا ما. يمكنك دائمًا استخدام هذا بالاقتران مع أدوات المُطوِّر لتضييق نطاق العناصر ذات الإشكالية في موقعك. كيفية تقليل عدد طلبيات خادم HTTPS لموقع وورد الخاص بك وبعد أن تعرفت على كيفية تحديد المناطق المسببة لضعف أداء موقع الويب الخاص بك، دعنا نتحدث عن كيفية حل المشكلة كاملة من بدايتها وهي تقليل عدد طلبيات خادم HTTPS لموقع ووردبريس الخاص بك. أقدم إليك 9 خطوات يمكنك القيام بها وبذلك تحتفظ على عدد معقول من الطلبيات في موقعك. 1) حذف الصور غير الضرورية هذا ليس معناه أنه يتوجب عليك التضحية بالصور من أجل خفض طلبيات الخادم ولكن بدلًا من ذلك، أعتقد أنه يجب عليك التركيز والحفاظ على مكتبة الوسائط الخاصة بموقعك خالية من أي صور لا ضرورة لها أبدًا. لذا، إذا كانت هناك صور لا تستخدمها أو حتى لو كنت تفكر في استخدامها في المستقبل فيمكنك التخلص منها. في النهاية لن تضيف شيئًا لموقعك سوى إضافة وزن إضافي وطلبيات للخادم وموقعك ليس بحاجة إليها. 2) حذف الملفات الأخرى غير الضرورية وقد تُظهر لك أدوات تقييم سرعة صفحتك التي ذكرتها أن الصور ليست هي التي تسبب المشكلة، وتتفاجأ أن هناك إضافة لتغذية الوسائط الاجتماعية أو وجود فيديو مدمج في الصفحة. فأنصحك أنه إذا كان هناك أي شيء على موقعك ليس ضروريًا ويتسبب في الضغط، فقم بإلغائه. اشمل على ذلك الإضافات والقوالب التي قمت بتثبيتها، ولكن التي لا تستخدمها في الوقت الحالي. 3) ضغط وتقليص حجم الملف من الأشياء الأخرى التي يتوجب عليك فعلها هو تثبيت إضافة تدعى WP Smush التي تتولى عملية ضغط صور موقعك. فإذا كنت ترغب في الحفاظ على صور موقعك الجميلة وذات الدقة عالية على موقعك بجودة سليمة تحتاج إلى ضغطه. 4) إنشاء عفريت صور CSS باستخدام CSS، يمكنك إنشاء ما يعرف باسم عفاريت الصورة (Image Sprite وهي تقنية تقوم على مبدأ استعمال صورة واحدة تحتوي على مجموعة من الخلفيات واستعمالها في جميع أزرار الموقع ويرجع الهدف من استعمال هذه التقنية إلى تسريع تحميل الموقع والتقليل من استخدام موارد استضافة الموقع). فعليًا سوف يجمع ملف CSS هذا جميع ملفات الصور الخاصة بك ويضعها في ملف واحد. استعن بهذا الدليل من W3 Schools لإنشاء عفريت. 5) فعّل خاصية التحميل الكسول هل سمعت عن التحميل الكسول (lazy loading)؟ ربما تسمع به لأول مرة، وسأقرب لك فكرة عمله. هنالك إضافات خاصة ترسل طلبيات للخادم عندما يقوم المستخدم بالتمرير لأسفل إلى صورة على الصفحة، وهذا الإجراء يحفظ موقع الويب الخاص بك ويقلل من الاضطرار إلى إرسال طلبيات الخادم غير الضرورية إلى المتصفح التي لم يسبق لزوارك الوصول إليها من قبل. 6) تجاهل الأصول غير ذات الصلة عملية التجاهل هذه تقوم بها إضافة تسمى WP Asset Cleanup وهي خاصة بووردبريس وتعمل بشكل مشابه لكيفية عمل إضافات التحميل الكسول. فبدلًا من التركيز على تأخير طلبيات الخادم للصور التي لم تتم مشاهدتها، تستكشف هذه الإضافة ما إذا كان هناك إضافة أو ملف أو مادة عرض أخرى موجودة داخل القالب الخاص بك، ولكن ليس على تلك الصفحة المحددة وبعد ذلك تحفظ هذا الأصل من أن يتم تحميله والكشف عنه في تلك الصفحة. وبالتالي، يصبح هناك تقليل لعدد طلبيات الخادم التي تذهب إلى المتصفحات. 7) استخدام الإضافة Hummingbird استعمال إضافة التخزين المؤقت (caching) أمرًا ضروريًا لمواقع ووردبريس، وخصوصًا تكمن أهميته عندما يكون موقع ووردبريس الخاص بك يتعامل مع زوار دائمين للموقع. وبذلك ليست هناك حاجة فعلاً لمعالجة طلبيات الخادم نفسها إذا لم يتغير شيء، وبالتالي فإن إضافة التخزين المؤقت تعمل على ذلك وتزيل كل ما ليس له حاجة. ومن الإضافات المهمة في ووردبريس إضافة Hummingbird التي تؤدي دورها بشكل مثالي مع إدارة التخزين المؤقت للمتصفح، فهي تعتني أيضًا بضغط الملفات، وملفات CSS، وملفات JavaScript وتصغير ملفات html، كما يضيف CDN (أي اختصار شبكة توصيل المحتوى وهي عبارة عن مجموعة من الخوادم الموزعة بكل أنحاء العالم تعمل على إيصال المحتوى الثابت لمواقع الويب إلى المستخدمين حسب موقعهم الجغرافي بأقرب وقت وأقصر مسافة) وتعمل إضافة CDN على تسريع الأمور بشكل أكبر ومنح إمكانية الوصول إلى تقارير الأداء في حالة عدم رغبتك في استخدام أحد العناصر الثلاثة أعلاه لتقييم حالة سرعة موقعك. 8) دمج ملفات الجافا سكريبت و ال سي اس اس تحتوي مواقع ووردبريس على العديد من ملفات CSS وJavaScript فبدلًا من إرسال كل ملف كطلب خادم منفصل إلى متصفحات الزوار، يمكن دمجهم في ملف واحد منفرد لكل نوع. ضع باعتبارك أن ملف CSS المدمج الخاص بك يجب أن يكون داخل رأس موقع الويب الخاص بك، وملف جافاسكربت في التذييل. 9) الحد من الصور الخارجية يظهر هذا واضحًا وأكثر شيوعًا عند تعليقات المدونة. هل تعلم أنه إذا تركت نظام التعليق الافتراضي الخاص بووردبريس في مكانه فإنه سوف يستخدم تلقائيًا Gravatar (صورة تشخيصية ثابتة وهي عبارة عن خاصية أوتوماتيكية لسحب صور المعلقين وسيرهم) وبذلك تصبح هذه الصور طلبيات خادم إضافية يتعين عليك إرسالها إلى كل المتصفحات، فماذا لو كانت المدونة معروفة ومشهورة بالطبع سوف تصبح هناك فوضى. ولكن في ووردبريس يوجد هناك بعض الإضافات الخاصة بالتعليقات وتعمل على تجنب هذه المشكلة. الخلاصة أخيرًا مما يميز تطوير مواقع ووردبريس أن هناك الكثير من الأشياء التي تستطيع القيام بها داخل الموقع و تحسين أداءه، ولكن أحيانًا نغفل كيف يمكن لموقعنا الخاص بما يحتويه من قوالب وإضافات وصور رائعة تبرز جماله أنها قد تكون بشكل مفرط يفوق الحد في نظر المستعرض الذي يحاول ببساطة معالجة الموقع بالكامل. ومع ذلك، في وورد بريس عليك أن لا تخف أبدًا، فإذا استخدمت أداة مراقبة السرعة للصفحة وتابعت عليها دومًا وأيضًا التزمت بنصائح الحد من طلبيات الخادم التسعة التي ذكرتها في الأعلى، أعتقد أنك بذلك سوف تجعل أداء موقعك جيدًا. ترجمة -وبتصرف- للمقال How to Reduce HTTP/S Requests in WordPress لصاحبته Brenda Barron
-
- طلبيات https
- https
-
(و 4 أكثر)
موسوم في:
-
يُخفّض الضّغط من أوقات الاستجابة من خلال تقليص حجم استجابة HTTP. يُعدُّ Gzip طريقةَ الضّغط الأكثر شيوعًا وفعاليّةً في الوقت الحاضر و عادةً ما يُقلّص حجم الاستجابة بما يقارب 70%. في عام 2009، كانت 90% من حركة البيانات على الإنترنت تعبر من خلال متصفّحات تدعم Gzip. أمّا اليوم: يمكنك القيام بذلك على خادم مبنيٍّ على Apache من خلال الملف .htaccess: # BEGIN GZIP <ifmodule mod_deflate.c> AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript </ifmodule> # END GZIP يُمثّل ما سبق قائمةً بأنواع MIME التي سيُطبّق عليها الضّغط حينئذٍ. يمكنك التعديل على هذه القائمة كما ترى مناسبًا لتشمل جميع أصولك النّصيّة التي ستخدّمها: يُقدّم مشروع HTML5 Boilerplate إعدادات الخواديم لجميع الخواديم الشائعة. هذه هي نسخة المشروع لملف htaccess. <IfModule mod_filter.c> AddOutputFilterByType DEFLATE "application/atom+xml" \ "application/javascript" \ "application/json" \ "application/ld+json" \ "application/manifest+json" \ "application/rdf+xml" \ "application/rss+xml" \ "application/schema+json" \ "application/vnd.geo+json" \ "application/vnd.ms-fontobject" \ "application/x-font-ttf" \ "application/x-javascript" \ "application/x-web-app-manifest+json" \ "application/xhtml+xml" \ "application/xml" \ "font/eot" \ "font/opentype" \ "image/bmp" \ "image/svg+xml" \ "image/vnd.microsoft.icon" \ "image/x-icon" \ "text/cache-manifest" \ "text/css" \ "text/html" \ "text/javascript" \ "text/plain" \ "text/vcard" \ "text/vnd.rim.location.xloc" \ "text/vtt" \ "text/x-component" \ "text/x-cross-domain-policy" \ "text/xml" </IfModule> ترجمة -وبتصرف- للمقال Active Gzip Compression لصاحبه Chris Coyier
-
- ضغط
- الشيفرة المصدرية
-
(و 2 أكثر)
موسوم في:
-
تظهر لنا الإحصاءات أن أكثر من 80٪ من تطبيقات الويب ومواقع الويب مدعومة بخوادم الويب مفتوحة المصدر. في هذه المقالة، سألقي نظرة على خوادم الويب المفتوحة المصدر الأكثر شعبية، وأراجع تاريخها وتقنياتها وميزاتها وغير ذلك. وسوف أقدم أيضًا بعض النصائح حتى تتمكن من النشر بسهولة على واحد من خوادم الويب هذه بنفسك. وفقًا لويكيبيديا ، فإن خادوم الويب هو "نظام حاسوبي يعمل على معالجة الطلبات عبر بروتوكول HTTP، وهو بروتوكول الشبكة الأساسي المستخدم لتوزيع المعلومات على الشبكة العالمية، ويمكن أن يشير المصطلح إلى النظام بأكمله، أو تحديدًا إلى البرنامج الذي يشرف على الطلبات" ، في هذه المقالة سنتعامل مع البرامج التي تعالج طلبات الويب من المستخدمين النهائيين. Apache HTTP تم إطلاق خادوم Apache HTTP - والذي غالبا ما يشار إليه باسم httpd أو Apache- في عام 1995، واحتُفل بعيد ميلاده العشرين في فبراير 2015. يشغل Apache 52٪ من جميع المواقع على مستوى العالم، وهو خادوم الويب الأكثر شعبية في العالم. يغلب أن يكون Apache مشغلا على لينكس ، ولكن يمكنك أيضا تشغيله على OS X و ويندوز. ليس غريبا أن Apacheمرخص بموجب رخصة Apache الإصدار 2. وهو يستخدم معمارية الوحدات، والتي يمكن بها إضافة وحدات جديدة لتمديد عمل الخادوم وزيادة ميزات أخرى . على سبيل المثال سيؤدي تحميل الوحدة mod_proxy إلى السماح للبروكسي على الخادوم الخاص بك، وسيعمل mod_proxy_balancer على تمكين موازنة التحميل لجميع البروتوكولات المدعومة. اعتبارا من الإصدار 2.4 صار Apache يدعم HTTP/2 من خلال الوحدة الجديدةmod_http2. وبما أن خادوم Apache HTTP هو خادوم الويب الأكثر شعبية منذ عام 1996، فإنه "يستفيد من الوثائق الكبيرة والدعم المتكامل من مشاريع البرامج الأخرى ." يمكنك العثور على مزيد من المعلومات حول Apache في صفحة مشروع. NGINX بدأ Igor Sysoev تطوير NGINX مرة أخرى في عام 2002. وقد طوّر NGINX جوابًا على ما يسمى مشكلة C10K ، وهو اختصار لــ "كيف يمكنك تصميم خادوم الويب الذي يمكنه التعامل مع عشرة آلاف اتصال متزامن ؟ " . NGINX يحل هذا المشكل وهو الثاني على قائمة خوادم الويب المفتوحة المصدر حسب الاستخدام، فهو يشغل ما يزيد عن 30٪ من المواقع. يعتمد NGINX على معمارية الأحداث الموجهة (event-driven) غير المتزامنة ، وذلك ما يساعده في تحقيق هدفه ، ألا وهو التعامل مع أكبر عدد ممكن من الاتصالات ، وبسبب ذلك أصبح خادوم الويب الأكثر شعبية جدًا بين مديري الأنظمة بسبب استخدامه لموارد خفيفة وقدرته على التوسع بسهولة. يتم إصدار NGINX تحت رخصة BSD-like ، ولا يقتصر استخدامه على خدمة الويب فحسب، بل أيضًا كخادوم وكيل proxy أو موازن التحميل load-balancer ، يمكنك العثور على مزيد من المعلومات حول NGINX في موقع المجتمع. Apache Tomcat Apache Tomcat هو حاوية جافا (اسمها الكامل Java servlet) مفتوح المصدر. وهو برنامج جافا بقدرات ملقمات الويب، على الرغم من أن servlet يمكن أن تستجيب لأي أنواع من الطلبات، فإنها استخدامها شائع فقط في تنفيذ التطبيقات المستضافة على خوادم الويب. servlet هي نظير تقنيات الويب الديناميكية الأخرى مثل PHP و ASP.NET، تم التبرع بالشيفرة المصدرية لــ Apache Tomcat من قبل شركة Sun Microsystems إلى مؤسسة Apache للبرمجيات في عام 1999، وأصبحت مشروع Apache الأعلى قيمة في عام 2005. وهي حاليًا تحتل 1٪ فقط من جميع المواقع. يستخدم Apache Tomcat -والذي يصدر تحت رخصة Apache الإصدار 2- عادة لتشغيل تطبيقات الجافا . ومع ذلك، فإنه يمكن تمديده بـ Coyote لأداء دور خادوم الويب العادي لكي يخدم الملفات المحلية كوثائق HTTP ، يمكنك الإطلاع على مزيد من المعلومات على موقع المشروع. غالبًا ما يتم ذكر Apache Tomcat مع خوادم تطبيقات الجافا المفتوحة المصدر الأخرى. مثل JBoss و Wildfly و Glassfish Node.js Node.js هي بيئة جافا سكريبت من جانب الخادوم ، وهي تعمل لتشغيل تطبيقات الشبكة، لا تحتل Node.js إلا مكانة منخفضة في السوق ، فنسبة تشغيلها لا تتجاوز 0.2٪ من المواقع . طور هذه البيئة في الأصل Ryan Dahl في عام 2009 ، وتسيرها الآن مؤسسة Node.js وبمساعدة مؤسسة لينكس. الفرق بين Node.js وغيرها من خوادم الويب الشعبية الأخرى هو أنها بيئة تشغيل عابرة للمنصات لتشغيل تطبيقات الشبكة، تطبّق Node.js معمارية الأحداث الموجهة event-driven القادرة على الإدخال والإخراج غير المتزامن. هذه الخيارات في التصميم هي الأمثل إنتاجية وقابلية للتوسع في تطبيقات الويب مما يسمح بتشغيل الاتصالات وألعاب المتصفح في الوقت الحقيقي، يظهر الفرق أيضًا في أن Node.js هو في الحقيقة جزء من مراحل تطوير الويب (HTML, CSS, and JavaScript)، على عكس Apache أو NGINX التي هي جزء من العديد من البرامج المختلفة. يتم إصدار Node.js تحت مزيج من التراخيص . يمكن الحصول على مزيد من المعلومات على الموقع الإلكتروني للمشروع . Lighttpd أطلق Lighttpd في أول إصدار له في مارس 2003. وهو حاليًا يشغل 0.1٪ من المواقع ويتم توزيعه تحت رخصة BSD. يميز Lighttpd أنه يعمل بموارد أقل مقارنة بالخوادم الأخرى (من حيث الذاكرة ، والمعالج) وهذا يجعله أسرع أداء واستجابة ، وهو يستخدم معمارية الأحداث الموجهة event-driven architecture ، ويعتبر الخيار الأمثل في حال كثرة الاتصالات المتزامنة وموارد أقل من العتاد، يدعم Lighttpd الكثير من التقنيات مثل : FastCGI, SCGI, Auth, Output-compression, URL-rewriting. كثيرًا ما يستعمل Lighttpd مع إطار العمل Ruby on Rails وإطار العمل Catalyst. لمزيد من المعلومات حوله قم بزيارة الصفحة الرئيسية للمشروع . نصائح إذا كنت ترغب أن تجرب واحدا من خوادم الويب الأكثر شعبية فأنا أوصي بشدة بتحميل التجميعية LAMP (Linux, Apache, MySQL, PHP) أو التجميعية LEMP (Linux, NGINX, MySQL, PHP) ، هناك الكثير من هذه التجميعيات المتاحة التي توفير نكهات مختلفة ، وعادة ما يتم توفيرها كمثبتات بنقرة واحدة، أو متوفرة كحزمة في مدير برامجك على لينوكس. بعد الانتهاء بنجاح من عملية التثبيت يمكنك بدء تشغيل خادوم الويب الخاص بك، ومحاولة إخراج المثال المشهور مرحبا بالعالم . انها طريقة رائعة للبدء في اكتشاف مداخل ومخارج خادوم الويب الخاص بك، وكيف تعمل خوادم الويب في الحياة التقنية الحقيقية. ترجمة -وبتصرّف- للمقال Top 5 open source web servers لصاحبه Robin Muilwijk حقوق الصورة البارزة محفوظة لـ Freepik
-
يُعتبر خادوما الويب Apache و Nginx الأكثر شهرةً من بين الخواديم المفتوحة المصدر في عالم الشبكة العنكبوتيّة، على اعتبار أنّهما مسؤولان عن خدمة وتأمين نصف تدفّق البيانات على الإنترنت، وعلى مَقدرة على تولّي مُختلف حجوم الأحمال، والعمل مع برمجيات أخرى في سبيل توفير حزمة من خدمات الويب الشاملة والكاملة لتلبية مُختلف الاحتياجات. بينما يَتشارك الخادومان Apache و Ngnix العديد من الميّزات والخاصيّات، فلا يُمكن اعتبارهما مُتشابهان، أو التفكير بأن أحدهما هو بديل عن الآخر، فكل منهما يتفّوق عن الآخر بشيءٍ ما، وعلى مُدير النظام فهم وإدراك لماذا يجب اختيار أحدهما دون الآخر، فهذا الدليل يَهدف إلى مُناقشة كيف أنّ كُل خادوم يَتميّز ويَبرز في شيء ويُخفق في آخر. مقدّمة عامّةسيتمّ أخذ نظرة سريعة عن تاريخ وبداية المشروعين وخواصّهم العامّة قبل التعمّق في الاختلاف بينهما. تاريخ خادوم الويب Apacheأَنْشَأَ “روبت ماك كول” (Robert McCool) “خادم الـ HTTP أباتشي” (Apache HTTP Server) في عام 1995، وتمّ مُتابعة تطويره تحت مظلّة “مُنشأةُ برمجيات أباتشي” (Apache Software Foundation) مُنذ العام 1999، وكان هذا الخادم هو المشروع الأساسي للمُنشأة والأكثر شهرةً عن باقي البرمجيات، فأصبح ببساطة يُشار إليه بالاسم “Apache”. يُعتبر خادم الويب أباتشي الخادم الأكثر استخدامًا على الإنترنت منذ العام 1996، وبسبب هذه الشهرة، استفاد أباتشي من توثيق ودعم باقي مشاريع البرمجيات الأُخرى. يَختار مُدراء الأنظمة الخادم أباتشي غالبًا بسبب مرونته، وقُدرته على التحمّل، وتوفّر دعمه العالي والمُنتشر، كما يُحسب له قابليته على التوسّع عبر نظام الوحدات (modules) الديناميكيّة، واستطاعته على مُعالجة عدد كبير من اللغات المُفسّرة (interpreted languages) من دون الحاجة إلى برمجيّة مٌستقلّة وسيطة. تاريخ خادوم الويب Nginxبَدأ “ايجور سيسيوﭫ” في عام 2002 العمل Nginx للإجابة وحلّ المُشكلة المعروفة بالاسم C10K، والّتي كانت تُشكّل تحدّيًا كبيرًا لخوادم الويب لتُصبح قادرة على تولّي عشرة آلاف اتصال مُتزامن (concurrent) وذلك في تلبية حاجة الويب الحديث، وأُنتجت الإصدارة الأوليّة والمُتاحة للعُموم في عام 2004 مُقدمةً حلًا لهذه المُشكلة، وذلك بالاعتماد على معماريّة مدفوعة بالحالة (event-driven) ولا مُتزامنة. انتشر Nginx كالنار في الهشيم مُنذ إصداره، بمُقتضى خفته واستخدامه الخفيف للمَوارد، وقدرته على التوسّع وتحمّل الضغط العالي وبأقل عتاد مُمكن، وتفوّق Nginx بتأمين المُحتوى الثّابت (static content) بسرعة، وبتصميمه لتمرير الطلبات الديناميكيّة (المُتغيّرة) إلى برمجيات أُخرى قادرة على مُعالجة هذا النوع من المُحتوى. يختار مُدراء الأنظمة الخادم Nginx غالبًا بسبب استهلاكه الأمثل للمَوارد، واستجابته العالية مع الضغط المتزايد. معماريّة مُعالجة الاتصال (Connection Handling Architecture)يَكمن الاختلاف الواضح بين أباتشي و Nginx في طريقة كلٍ منهما في مُعالجة الاتصالات وتدفّق البيانات (traffic)، وربّما هذا السبب وراء الاختلاف في طريقة كل من الخادمين في الاستجابة إلى حالة تدفّق البيانات المُختلفة. وحدات أباتشي (Apache Modules)يقدّم أباتشي تشكيلةً من وحدات المُعالجة المُتعدّدة (multi-processing)، والّتي يُطلق عليها بـ MPMs، والغرض منها تحديد آليّة مُعالجة طلبات العميل، ويَسمح ذلك مُدراء الأنظمة عامّةً بالتبديل بين معماريّة مُعالجة الاتصال بسهولة، والوحدات هي: mpm_prefork: تَستنسخ وتُوالد هذه الوحدة الخاصّة بالمُعالجة عمليّات (processes) باستخدام سلسلة وحيدة (single thread)، على أنّ تكون كل عمليّة لمُعالجة طلب، ويستطيع كل ابن مُعالجة اتصال واحد في نفس الوقت، وطالما أنّ عدد الطلبات أقل من عدد العمليّات، فستكون هذه الوحدة سريعةً جدًا، ولكن يَنخفض الأداء بسرعة بعد تخطّي الطلبات عدد العمليّات، ولذلك لا يُعتبر هذا النمط بالخيار الجيّد للعديد من السيناريوهات، فكل عمليّة لها تأثير بليغ على استهلاك الذاكرة (RAM)، ولهذا السبب تُصعّب هذه الوحدة من عمليّة التوسّع بطريقة مُلائمة، ومع هذا تبقى هذه الوحدة خيارًا جيّدًا إن تمّ استخدامها مقترنةً مع مُقوّمات (components) أُخرى لم تُبنى بالأساس آخذةً بعين الاعتبار السلاسل (threads)، فلغة PHP ليست سلسلة آمنة (thread-safe)، ولذلك يُنصح بهذه الوحدة باعتبارها الطريقة الوحيدة الآمنة للعمل مع mod_php والّتي هي وحدة من وحدات أباتشي لمُعالجة هذا النوع من الملفّات. mpm_worker: تستنسخ وتُوالد هذه الوحدة عمليّات (processes) كل منها ذات قُدرة على إدارة سلاسل مُتعدّدة (multiple threads)، تستطيع كل واحدة من هذه السلاسل مُعالجة اتصال وحيد، تُعتبر هذه السلاسل أكثر كفاءة من العمليّات، بسبب أنّ هذه الوحدة تتوسّع (scales)، وتتحمّل المزيد من الضغط أفضل من الوحدة prefork MPM، وباعتبار أنّه يوجد سلاسل أكثر من العمليّات، فهذا يعني أيضًا أنّ الاتصالات الجديدة تستطيع مُباشرةً استهلاك واستخدام سلسلةبدلًا من اضطرارها إلى الانتظار لتوفّر عمليّة مُتاحة. mpm_event: تَعمل هذه الوحدة بشكل مُشابه إلى الوحدة worker، ولكنها مُحسّنة لتتولّى اتصالات keep-alive، فعند استخدام الوحدة worker فإن الاتصال سيَحتفظ بالسلسلة (thread) بصرف النظر فيما إذا كان الطلب نشطًا فيما صُنع من أجله ما دام الاتصال محفوظًا نشطًا، فالوحدة mpm_event تتولّى الاتصالات keep-alive بالاحتفاظ جانبًا بسلاسل مكرّسة لمُعالجتها، وبتمرير الطلبات النشطة إلى سلاسل أُخرى، وهذا من شأنه أنّ يُبعد الوحدة من الغوص بطلبات keep-alive، الأمر الّذي يُجيز بتنفيذ الطلبات (execution) بشكل أسرع، وهذا الأسلوب أصبح يعمل بشكل مُستقر مع الإصدار Apache 2.4. أصبح الأمر أكثر وضوحًا، حيث تقدّم خوادم أباتشي بنية معماريّة مرنة للاختيار بين مُختلف الاتصالات وخوارزمية مُعيّنة في مُعالجة الطلبات، وبُنيت هذه الخيارات في الدرجة الأولى من تطوّر الخادم والحاجة المُتزايدة للاتصالات المُتزامنة لتواكب طبيعة الإنترنت بعد تغيرها وتطوّرها. آليّة مُعالجة الاتصال في خادوم Nginxقَدِم Nginx إلى عالم خوادم الويب بعد قدوم أباتشي، مَبنيًّا ومُعدًّا لمشاكل الاتصالات المُتزامنة (concurrency) الّتي تواجه المواقع عند التوسّع، مُحمّلًا بهذه المعرفة، صُمّمَ Nginx من جذوره ليستخدم خوارزميّة في مُعالجة اتصالات مدفوعة بالحالة (event-driven)، غير مُستوقفة (non-blocking)، ولا مُتزامِنة. يستنسخ ويُوالد Nginx من العمليّات العاملة (worker processes)، ويستطيع كلٍ مِنها مُعالجة آلاف الاتصالات، وتُنجذ العمليّات العاملة ذلك عن طريق تطبيق/تنفيذ آلية حلقيّة سريعة، والّتي تفحص بشكل مُستمر حالات العمليّات (processes events)، وإن فصل المُهمّة الفعليّة عن الاتصالات يسمح لكلعامل بالاهتمام بنفسه باتصال فقط عند بدء حالة جديدة. يتموضع كل اتصال مُعالج من قبل العامل ضمن حلقة الحالة (event loop) في مكان تواجد بقية الاتصالات، وتُعالج الأحداث بشكل لا مُتزامن ضمن الحلقة، ليتمّ إنجاز المُهمّة بطريقة غير مُستوقفة (non-blocking)، وعندما يُغلق الاتصال سيتمّ نزعه من الحلقة. يَسمح هذا الأسلوب من مُعالجة الاتصال Nginx بتحمّل الضغط العالي بشكل لا يُصدّق وبأقل المَوارد المُتاحة، وباعتبار أنّ الخادم ذو سلسلة وحيدة (single-threaded) ولا تتوالد العمليّات لتُعالج كل اتصال جديد، فإن استهلاك المُعالج (CPU)، والذّاكرة يبقى ثابتًا نسبيّا، حتّى في أوقات الذروة. كيف يُعالج أباتشي و Nginx المُحتوى الثّابت والمحتوى الديناميكي (المُتغيّر)إن أبرز ما يتمّ النظر إليه عند المُقارنة بين الخادمين هي طريقة كلٍ منهما في التعامل مع طلبات المُحتوى الثّابت (static)، والمُحتوى المُتغيّر (dynamic). كيف يتعامل أباتشي مع المُحتوى الثّابت والمُتغيّرتستطيع خوادم أباتشي التعامل مع المُحتوى الثّابت باستخدام الطريقة التقليديّة المُعتمدة على الملفّات، ويعود أداء هذه الإجراءات (operations) في الدرجة الأولى على دور ووظيفة أساليب الوحدات (MPM) المشروحة سابقًا. يستطيع أباتشي أيضًا مُعالجة المُحتوى الديناميكي (المُتغيّر) بدمج مُعالج اللغة المُراد مُعالجتها داخل كل من نماذجه العاملة (worker instances)، وهذا يَسمح له بتنفيذ المُحتوى الديناميكي داخل خادم الويب نفسه بدون الحاجة إلى الاعتماد على مُقوّمات خارجيّة، ومن المُمكن تفعيل هذه المُعالجات الديناميكيّة (المُتغيّرة) من خلال استخدام وحدات قابلة للتحميل بشكل ديناميكي. إن قدرة أباتشي على مُعالجة المُحتوى الديناميكي بشكل داخلي تعني أنّ الإعداد يُصبح أسهل لمُعالجة هذا النوع من المُحتوى، فليس من الضروري تنسيق عمليّة الربط مع برمجيات إضافيّة، وتستطيع الوحدات وبسهولة أنّ تقوم بالتبديل عندما تتغيّر مُتطلّبات المُحتوى. كيف يتعامل Nginx مع المُحتوى الثّابت والمُتغيّرلا يَملك Nginx بطبيعته أي قدرة على مُعالجة المُحتوى الديناميكي، ولمُعالجة شيفرة PHP وطلبات المُحتوى الديناميكي، فإن على Nginx تمرير الطلبات إلى مُعالج خارجي من أجل التنفيذ (execution) والانتظار ريثما يتم الانتهاء من مُعالجة هذا المُحتوى ليتمّ إعادة إعادته، ومن ثم عرض النتائج على العميل. يَنبغي على مُدراء الأنظمة الانتباه إلى أنّ الأسلوب الّذي ينتهجه Nginx يستوجب إعدادًا بينه وبين المُعالج وباستخدام واحدًا من البرتوكولات الّتي يفهمها Nginx أمثال: HTTP, FastCGI, SCGI,uWSGI, memcache، وهذا من شأنه أنّ يُعقّد الأمور بعض الشيء، خصوصًا عند مُحاولة توقّع عدد الاتصالات اللازم السماح بها، حيثُ أنّه سيتمّ استخدام اتصالًا إضافيًا لكل مُعالج يتمّ استدعاؤه. من ناحية أخرى، إن هذا الأسلوب يقدّم بعضًا من الأفضليّة، عندما نعلم أنّ مُفسّر المُحتوى الديناميكي غير مُدمج في عمليّة العامل، وتكلفة هذه الطريقة ستُدفع للمُحتوى الديناميكي فقط، وعلى أنّ يُقدّم المُحتوى الثّابت بطريقة مُباشرة، ولا يتمّ الاتصال بالمُفسر إلا عند الحاجة، والجدير بالذكر أنّ أباتشي يستطيع العمل بهذا الأسلوب، ولكن بعمله ذلك سيتخلّى عندها عن بعض ميزاته. الاختلاف بين الإعداد الموزّع (Distributed) والإعداد المركزي (Centralized)يَعتبر مُدراء الأنظمة الاختلاف الأكبر والبارز بين هذين الخادمين هو فيما إذا كان الإعداد والتخصيص على مُستوى المسار مسموحًا أو لا ضمن مسارات (directories)المُحتوى. فلسفة Apache في الإعداديُضمّن أباتشي خيارًا للسماح بالإعداد لكل مسار عن طريق تَفحُّص (inspecting) وتفسير (interpreting) التعليمات أو التوجيهات الموجودة في الملفات المخفيّة داخل مسارات المُحتوى نفسها، وهذه الملفّات معروفة بملفات .htaccess. باعتبار أنّ هذه الملفّات تَقطن داخل مسارات المُحتوى نفسها، فعند مُعالجة طلبٍ ما، فإن أباتشي يَفحص كل جزء من مسار الملفّ المطلوب باحثًا عن ملفّ .htaccess ليُطبّق التوجيهات الّتي بداخله، وهذا من شأنه أنّ يسمح للإعداد اللامركزي لخادم الويب، والذي غالبًا ما يُستخدم لإنجاز: إعادة كتابة عنوان الموقع (URL rewrites)تقييد الوصول (access restrictions)التفويض والمُصادقة (authorization and authentication)سياسات التخبئة (caching policies)بالطبع يُمكن للأمثلة السابقة إعدادها عن طريق ملفّ إعدادات أباتشي الرئيسي، ولكن استخدام ملفات.htaccess يَملك بعض الميزات: أوّلًا، باعتبار أنّها تُفسّر في كل مرّة توجد بها مع المسار المطلوب، فهي تُنفّذ مُباشرةً بدون إعادة تحميل الخادم.ثانيًا، تجعل من المُمكن السماح للمُستخدِمين غير المصرّح لهم بالتحكم بجانب معيّن من المُحتوى الخاصّة بهم بدون إعطائهم تحكم كامل لملفّ الإعدادات.يُقدّم هذا النمط من الإعداد طريقة سهلة ونموذجيّة، وخاصّة لبعض برمجيات الويب، مثل أنظمة إدارة المُحتوى (CMS)، لغرض إعداد بيئتها بدون مَنح إذن وصول إلى ملفّ إعدادات مركزيّ، وكما هو معروف يُستخدم هذا الأسلوب مع مزودات الاستضافة المُشتركة (shared hosting providers) لصون والحفاظ على الإعدادات الرئيسية مع إمكانيّة منح العُملاء أفضليّة التحكّم بمسارات مُعيّنة. فلسفة Nginx في الإعدادلا يُفسّر Nginx ملفّات .htaccess، ولا يُقدّم أي آليّة للتعامل مع كل مسار من دون استخدام ملفّ إعدادات رئيسي، قد يبدو هذا الأسلوب أقل مرونةً من أسلوب أباتشي، ولكن من ناحية أُخرى فلهذا الأسلوب أفضليته. إن عدم الاعتماد على نظام ملفّات .htaccess الخاصّ بالإعداد على مستوى المسارات يُقدّم سرعةً في الأداءً، فخادم أباتشي عليه القيام بتفحّص المسار الجذر لكل طلب يصله، وعند وجود ملفّ أو أكثر خلال عمليّة البحث، يتم قراءة محتوياته وتفسيرها، ولكن Nginx لا يفعل ذلك، فهو يخدم الطلبات بسرعة أكبر بالاعتماد على مكان وحيد للبحث عنه. أفضليّة أُخرى مُتعلّقة بالحماية، فإن توزيع ملفّات الإعدادات على مستوى المسارات يوزّع مسؤوليّة الحماية على كل المُستخدِمين، الّذين قد يكونوا في معظم الأحوال غير موثوقون لتولّي هذه المُهمّة بالشكل الأمثل، فعندما يقوم مُدير النظام بتولّي مُهمة التحكم بالخادم ككل، يمنع ذلك من حدوث أخطاء، والتي قد تحدث في حال منح صلاحيات وصول لأطراف أُخرى. يجدر الذكر أنّه من المُمكن تعطيل تفسير ملفّات .htaccess’ فيأباتشي`، في حال أنها تُشكل نوعًا من القلق لمُدير النّظام. الاختلاف بين تفسير الملفّات وتفسير URIلا يقتصر الاختلاف بين الخادومين على ما سبق فقط، فيظهر الاختلاف الآخر في كيفيّة تفسير كلٍ منهما للطلبات (requests) وربطها مع المَوارد المُتواجدة على النّظام. كيف يُفسر Apache الطلباتيقدّم أباتشي القدرة على تفسير الطلب إما كمَورد فيزيائي (حقيقي) على نظام الملفّات (filesystem) أو عنوان URI الّذي قد يحتاج أسلوب أكثر تجرّد، ويستخدم أباتشي بشكلٍ عام للأسلوب الأول كتل (blocks) وهي إما <Directory> أو <Files>، بينما يستخدم كتل <Location>للمَوارد الأكثر تجرّدًا. صُمّم أباتشي من الأساس كخادم ويب، لذلك في مُعظم الأحيان فإن السلوك الافتراضيّ هو تفسير الطلبات كمَوارد نظام ملفّات (filesystem)، حيثُ يبدأ بتتبّع جذر المُستند وإلحاقه بجزئية الطلب متبوعًا باسم المُضيف (host) ورقم المنفذ في مُحاولة لإيجاد الملفّ المطلوب، بمعنى آخر وببساطة، تتمثّل هرميّة نظام الملفّات على الويب كشجرة مُستند. يُقدّم أباتشي عددًا من البدائل عندما لا يتوافق الطلب مع نظام الملفّات المقصود، فمثلًا من المُمكن استخدام الموجّه Alias لربط عنوان البديل، مع العلم أنّ استخدام الكتل <Location> هو طريقة للتعامل مع URI نفسها بدلًا من نظام الملفّات، كما يُمكن استخدام التعابير النمطيّة (regular expression)، والّتي من المُمكن استخدامها لتطبيق الإعداد بسهولة أكبر في كامل نظام الملفّات. يُعوّل أباتشي على نظام الملفّات بشكل كبير، يظهر ذلك جليًا في اعتماده على ملفّات .htaccessلإعداد كل مسار، حتّى أنّ التوثيق الرسميّ الخاصّ به يحذر من استخدام كتل مُعتمدة على URI في تقييد الوصول عندما يكون الطلب يَعتمد بشكل أو بآخر على نظام الملفّات. كيف يُفسّر Nginx الطلباتأُنشِأ Nginx ليكون خادمًا للويب وخادمًا وكيلًا/وسيطًا (proxy server)، ونظرًا إلى المعماريّة المطلوبة للعمل بهذه الأدوار، فإنه يعمل بشكل رئيسي مع URIs، والتحويل إلى نظام الملفّات عند الضرورة. يُمكن رؤية ذلك في بعض جوانب بناء وتفسير ملفّات إعدادات Nginx، فلا يوفّر Nginx آليّة لتحديد إعدادًا لمسار نظام الملفّات، بل يَستعيض عنها بتحليل URI نفسه. يُمكن توضيح ذلك بالمثال، كتل الإعداد الأوليّ لـ Nginx هي: server و location، الكتلة serverتُفسّر المُضيف الجاري طلبه، بينما الكتل مسؤولة عن مُطابقة أجزاء من URI التي تأتي بعد المُضيف والمنفذ، في هذه المرحلة يتمّ تفسير الطلب كـ URI، وليس كعنوان على نظام الملفّات. يتوجّب في نهاية المطاف على جميع الطلبات أنّ تُربط مع عنوان على نظام الملفّات وذلك للملفّات الثّابتة، فأولًا، سيَختار Nginx كتل server و location الّتي سوف تتولّى الطلب، ومن ثم ضم جزر المُستند مع الـ URI. إن تحليل ومُعالجة الطلب قبل كل شيء على شكل URIs بدلًا من عناوين نظام الملفّات يَسمح لـ Nginxالعمل بسهولة وعلى حدٍّ سواء كخادم وسيط (بروكسي)، وكخادم بريد، وخادم ويب، فقد تمّ إعداده ليُلائم كيف له أنّ يستجيب لأنماط الطلبات المُختلفة، ولا يفحص Nginx نظام الملفّات حتّى يكون جاهزًا ليَخدم الطلب، وهذا يُفسّر لماذا هو لا يُطبّق نمط ملفّات .htaccess. الوحداتيتوسع كلا الخادومان عن طريق نظام الوحدات، ولكن طريقة عملهما تختلف عن الآخر بشكل كبير. كيف يستخدم أباتشي نظام الوحدات (Modules)؟يَسمح نظام وحدات أباتشي بطريقة آليّة وديناميكيّة بتركيب ونزع الوحدات ليتناسب مع مُتطلّبات مُدير النظام خلال عمليّة تشغيل الخادم، وتتواجد نواة أباتشي دائمًا بكل جاهزية، بينما يُمكن تشغيل أو تعطيل الوحدات، أو حتّى حذفها أو إضافة ما يلزم إلى الخادم. يستخدم أباتشي الوحدات في العديد من المهام، ونظرًا للباع الطويل لمنصة أباتشي، فيتوفّر عدد هائل من مكتبات الوحدات، والّتي من المُمكن استخدامها في تعديل بعض الوظائف الداخليّة في بنية خادم أباتشي، فمثلًا الوحدة mod_php تقوم بدمج مُفسّر PHP داخل كل عامل (worker). لا تنحصر الوحدات لمُعالجة المُحتوى الديناميكي (المُتغيّر) فقط، فيُمكن استخدامها في العديد من الوظائف، فيُمكن استخدامها في: rewriting URLs: إعادة كتابة العناوينauthenticating: المُصادقةlogging: التّتبّعcaching: التخبئةcompression: الضغطproxying: الوساطةencrypting: التشفيركيف يتعامل Nginx مع نظام الوحدات (Modules)يُطبّق ويتعامل Nginx مع نظام الوحدات، ولكن يختلف الأمر عما هو في نظام أباتشي، فلا تُحمّل الوحدات بشكل ديناميكي في نظام Nginx، لذلك يجب على هذه الوحدات أنّ تُختار وتُترجم (compiled) إلى النواة. قد يبدو الأمر صعبًا للعديد من المُستخدمين وخاصّة لهؤلاء الذين لا يُحبذون صيانة برمجياتهم المُترجمة (compiled) بدون الاستعانة بنظام حزم تقليدي، وعلى الرغم من أنّ حزم الموزّع تتضمّن الوحدات الأكثر استخدامًا، ولكن عند الحاجة إلى وحدة غير شائعة، سيتوجب على مُدير النظام بناء الخادم من المصدر بنفسه. تَبقى وحدات Nginx مع ذلك ذات فائدة، وتسمح لمُدير النّظام بتحديد ماذا يجب على الخادم أنّ يحتوي من وظائف، أيضًا بعض المُدراء ينظر إلى الأمر من منظور الحماية، حيثُ أنّ المُكوّنات الاعتباطيّة لا يُمكن أن تُدرج داخل الخادم. تُقدّم وحدات Nginx مقدرات مُماثلة للوحدات الّتي المُقدّمة من أباتشي، على سبيل المثال، توفّر وحدات Nginx: proxying support: الوساطةcompression: الضغطlogging: التّتبّعrewriting: إعادة كتابة العنوانauthentication: المُصادقةencryption: التشفيرالدعم والتوافُقيّة والتوثيقيجب دائمًا التأكد من آليّة بناء الخادم ومُتطلباتها، وما الّذي على مُدير النّظام عمله لبناء خادم يعمل بأبسط الإمكانيات، وما هو حجم الدعم والمُساعدة المتوفّر لهذه البرمجية. الدعم في أباتشييُعرف الخادم أباتشي بباعه الطويل في هذا المجال، ولذلك فإن الدعم الخاصّ به متواجد وبقوّة، حيثُ يتوفّر توثيق مُمتاز لمكتباته الخاصّة به ومكتبات الطرف الثالث (الخارجيّة)، وعلى كافّة المُستويات، سواء كان لنواة الخادم أو للجزئيات المُرتبطة ببرمجيات أُخرى. يتوفّر بجانب التوثيق، العديد من الأدوات ومشاريع الويب لتسريع بدء العمل مع بيئة الخادم، وهي موجودة ضمن المشاريع نفسها أو مُتوفّرة ضمن برمجيات الحزم المعروفة. يَملك أباتشي بشكلٍ عام دعمًا قويًا من قِبل مشاريع الطرف الثالث، وذلك بسبب حصته السوقيّة، وقِدَمه، كما يَملك مُعظم مُدراء الأنظمة بشكل أو بآخر معرفة جيّدة بخادم أباتشي، ليس فقط بسبب انتشاره، ولكن أيضًا بسبب أنّ معظمهم بشكل أو بآخر يستخدم الاستضافة المُشتركة (shared-hosting)، والّتي تعتمد على خادم أباتشي بشكل حصري، لمقدرته الإدارية الموزّعة باستخدام ملفّ .htaccess. الدعم في Nginxيكسب Nginx المزيد من الدعم مع ازدياد المُستخدِمين بسبب أدائه العالي، ولكن يبقى عليه التطوير من نفسه في بعض الجزئيات. قد كان من الصعب إيجاد توثيق مفهوم وواضح بالغة الإنكليزية للخادم Nginx في البداية، نظرًا إلى أنّ تطويره وتوثيقه تمّ بالغة الروسية، ومع ازدياد الاهتمام بالمشروع، أصبح هناك وفرة من المصادر على الموقع الرسميّ وغيره من الدعم الخارجي. أصبح الدعم متوفّرًا أكثر من ذي قبل فيما يخص تطبيقات الطرف الثالث، وبدأت بعض الحزم بتقدم خيارات الإعداد التلقائي سواءً لـ أباتشي أو Nginx، وعند عدم توفّر الدعم، فإن إعداد Nginx مع البرمجيات البديلة عادةً ما يكون واضحًا ومُيسرًا طالما أنّ برمجية الطرف الثالث تملك توثيقًا جيّدًا لمُتطلّباتها. استخدام Apache و Nginx معًاتمّ عرض فوائد وقصور كلا الخادومين، ويجب على مُدير النّظام في هذه المرحلة أنّ يُحدّد أيًا منهما يُناسب احتياجاته، ولكن يجد العديد من المُستخدِمين أنّه من المُمكن تقوية خادوم الويب عند استخدام كلٍ من أباتشي و Nginx جنبًا إلى جنب. إن إتمام هذه الشراكة يتمّ عن طريق تَمَوْضُع Nginx أمام أباتشي كوكيل/وسيط عكسي (reverse proxy)، وهذه يسمح لـ Nginx بمُعالجة جميع الطلبات من العُملاء، الأمر الّذي يَسمح بالاستفادة من سرعة Nginx وقدرته على تولّي عدد كبير من الاتصال في وقتٍ واحد. إن خدمة الملفّات الثّابتة بسرعة كبيرة ومباشرةً إلى العُملاء، هو الأمر الّذي يتفوّق به Nginx، ولكن وللمُحتوى الديناميكي، ملفات PHP مثلًا، سيُوكل Nginx الطلبات إلى أباتشي لمُعالجتها والعودة بصفحة بالنتيجة النهائيّة، ليستطيع Nginx عندها تمرير المُحتوى إلى العميل. يعمل هذا الإعداد بشكل جيّد للعديد من مُدراء الأنظمة، وذلك بسبب أنّه يسمح لـ Nginx ليعمل كآلة فرز وتصنيف، بمعنى أنّه سيتولّى مُعالجة جميع الطلبات طالما أنّه يستطيع ذلك، وتمرير ما لا يستطيع التعامل معه، وبتخفيض الطلبات المطلوب من خادم أباتشي تولّيها، سيُخفف بعضًا من الاستيقاف (blocking) الّذي قد يحدث عندما يستهلك أباتشي المزيد من المُعالج. يَسمح هذا الإعداد أيضًا لمُدراء الأنظمة بالتوسّع عن طريق إضافة خادم خلفي (backend) على حسب الحاجة والضرورة، ومن المُمكن إعداد Nginx لتمرير الطلبات إلى تجمّع (pool) من الخوادم بسهولة، الأمر الّذي يزيد من الأداء والفعاليّة. الختاميُقدّم كلًا من أباتشي و Nginx مُرونة في الاستخدام، وقوّةً في الأداء، والتفضيل بينهما هو لأمرٌ يَعتمد على تقدير مُتطلبات ووظائف الخادم، وعلى مُدير النّظام أنّ لا يسأل: هو أفضل خادم ويب؟، بل السؤال الّذي يجب سؤاله هو، ما هو أفضل خادم ويب لمشروعي الّذي يتطلّب كذا وكذا؟ يوجد بالفعل اختلافات بين المشروعين، هذه الاختلافات من شأنها أن تأثر على الأداء، والقدرات، والوقت المُستغرق في إتمام أي منهما للعمل بالجاهزيّة الكاملة، ولكي يتمّ اختيار الأفضل يُنصح بعمل تسوية أو مقايضة بين المحاسن والمساوئ، ففي نهاية المطاف لا يوجد خادم يُلبي كافة الاحتياجات، ويَكمن الحلّ في ترتيب الأولويات. ترجمة –وبتصرّف– للمقال Apache vs Nginx: Practical Considerations لصاحبه Justin Ellingwood.
-
تقنيات SEO تتضمن عناصر مهمة لا يراها المستخدم، إلا بالبحث عنها في الشيفرة المصدرية (Source Code) الخاصة بالموقع. من مهمَّتك كمطور مواقع معرفتها والعناية بها، وأهم سبع عناصر هي: الكشف عن عنوان IP اختصارًا لـ Internet Protocol، وتقنية إعادة التوجيه (Redirection). سرعة الموقع (Site Speed). إعادات التوجيه 301 / 302. رموز الحالات (HTTP Status Code)، وبروتوكول نقل النص التشعبي (HTTP: HyperText Transfer Protocol). وصول الزاحف (Crawler Access). لغة برمجة الويب JavaScript. أولاً: الكشف عن عنوان IP وإعادة التوجيه هذا العنصر هو الذي يكتشف ويتعرف على مكان الزائر للصفحة، ويحدد المنطقة التي يتصفح منها الموقع، بحيث يكون ذلك معتمدًا على عنوان IP الخاص به، وهنا تبرز أهمية إعادة التوجيه، المبنية على معلومات IP الخاصة بالزائر، حيث تقوم بعرض المحتوى الأنسب له. ولفهم أهمية هذا العنصر، نستعرض المثال التالي: لنفترض أنّ نطاق الموقع هو www.domain.co.uk، خاص بزوار المملكة المتحدة، ومحتوى الموقع بالإنجليزية. لنفترض أنّ زائرًا من فرنسا مهتم بالموقع، والمحتوى الأنسب له هو الفرنسية، فيتم التعرف عليه وعلى عنوان IP الخاص به، وتحويله وإعادة توجيهه إلى العنوان الأنسب، الذي يكون كالتالي: www.domain.fr. بالرغم من أهمية خاصية إعادة التوجيه في المواقع، إلا أنها قد لا تكون دقيقة دائمًا، ودورها الأساسي هو التعرّف على مكان الزائر ولغته وعرض المحتوى الأنسب له. وفقاً للحالة السابقة، ستواجهنا مشكلة مع زواحف محركات البحث، وهي عدم رؤية هذا الجزء الخاص من محتوى الموقع (المحتوى الفرنسي في مثالنا السابق)، لأن الزاحف يرى محتوى رابط الموقع الرئيسي المنتهي بـِ (co.uk) مثلاً، ولا يرى محتوى الموقع المنتهي بـ (fr.)، فهو مخفي وغير مرئي لعناكب البحث، لكونها برامج آلية، مبرمجة وفق خوارزميات تحدد طريقة عملها. الكثير من المطورين، والذين يعملون في تحسين المواقع لمحركات البحث، يعتقدون بأنّ هناك مشكلة في عمل عنوان IP أو في إعادة التوجيه الخاصة بالموقع، والحقيقة هي المثال السابق الذي قمنا بتوضيحه، والتي تؤدي أحياناً إلى عدم أرشفة وفهرسة صفحات الموقع، ومنع محركات البحث من الوصول إليها. لذلك عليكَ كمطوّر تفادي هذه المشكلة والإنتباه لها جيّدًا، كي لا تمنع محركات البحث من رؤية صفحاتٍ معينة من موقعك. ثانياً : سرعة الموقع المواقع الناجحة تكون سريعة دائماً، مثل : ( Amazon / Google / Yahoo / Youtube .. الخ ). أنتَ كمطوّر يجب أن تكون سرعةُ موقعك على رأس قائمة أولوياتك، فالموقع السريع يحتفظ بزوارٍ كثيرين، لأنه يعطيهم الراحة أثناء التصفح، والسرعة في عرض المعلومة المطلوبة والتي يبحثون عنها بشغف. سرعة الموقع تساهم في إطالة مدة بقاء الزائر فيه، وتدفعه إلى اكتشافِ مزيدٍ من المحتوى. أما إذا استغرق تحميل الصفحة الواحدة في الموقع لأكثر من بضع ثوان، قد يدفع المستخدم إلى تركه والخروج منه وعدم الرجوع إليه مرة أخرى. بناءً على ذلك، عليك الاهتمام بسرعة الموقع، لأن Google مهووسة بهذا العامل المهم بالنسبة إليها، وهي تعرف مدى الإهتمام الكبير للمستخدم بالسرعة، وأن زيادة سرعة الموقع مرتبط ارتباطاً وثيقاً بشهرته ونجاحه، وهذا ما تُريده محركات البحث لأرشفته بقوة . ثالثاً : إعادة التوجيه 301/302 لعمليات التحويل وإعادة التوجيه أهمية كبيرة، علينا التعرف على بعض المعلومات الأساسية والمهمة عنها، يُستخدم التحويل عادةً في تهيئة محركات البحث (SEO) للأسباب التالية : عند نقل صفحة ما إلى مكان معين أو إلى الأسفل، يتم توجيه المستخدمين ومحركات البحث إلى صفحة جديدة. عند إنشاء محتوى منسوخ أو مكرر وتريد أن يتم حذفه من فهارس Google، وتوجيه عناكبها إلى المحتوى الأصلي. بشكلٍ عام نستخدم إعادة توجيه 301 من جانب الخادم عندما نحتاج إلى تغيير عنوان URL لصفحة ما بشكلٍ عام، ليصبح كما يظهر في نتائج محركات البحث. وهذه من أفضل الطرق التي تضمن توجيه المستخدمين ومحركات البحث إلى الصفحات الصحيحة. والمعنى العام من رمز الحالة 301، هو أنه تم نقل إحدى الصفحات إلى مكانٍ جديد بشكلٍ دائم. بالنسبة لتحويل 302، فهو له علاقة مباشرة بتهيئة المواقع لمحركات البحث، وأسبابُ استعماله هي: عدم توفر الصفحة المطلوبة بشكل مؤقت. تجربة واختبار عملية الإنتقال إلى نطاق جديد يختلف عن نطاق الموقع الأصلي، والحصول من ذلك على تغذية راجعة من المستخدمين للنطاق الجديد، بدون تدمير النطاق القديم وخسارة ترتيبه. إعادة توجيه 302، تعني أنه تم نقل العنوان القديم إلى عنوان جديد بشكلٍ مؤقت. بناءً على ذلك، لا تقوم Google بحذف العنوان القديم من فهارسها، ولا يتأثر ترتيب الرابط وشعبيته لدى محركات البحث. ما هو دورك كمطوّر؟ وما هي المشاكل التي تتسبب فيها عمليات إعادة التوجيه 301 / 302؟ المستخدم العادي لا يَلحظ عملية إعادة التوجيه، فهو سيحصل على المحتوى بجميع الأحوال. محركات البحث تلاحظ الإختلاف الناجم عن عمليات التحويل، وهذا يؤثر على أرشفة وفهرسة الموقع. عمليات إعادة التوجيه غير الصحيحة قد تؤدي إلى خسارة الموقع لترتيبه، والتأثير بشدة على حركة الزوار وانخفاضها، فعليك الحذر من هذه العمليات والإنتباه لها جيّداً أثناء القيام بها. عند تنفيذ عمليات إعادة التوجيه، عليكَ اتباع الممارسات الجيّدة. تأمل معي المثالي التالي: عملية توجيه صحيحة: الرابط القديم : http://www.old-site.com/product-name-123 الرابط الجديد : http://www.new-site.com/product-name-123 عملية توجيه خاطئة: الرابط القديم : http://www.old-site.com/product-name-123 الرابط الجديد : http://www.new-site.com نستنتج من المثال السابق، أنّ الخطأ الشائع هو إعادة توجيه الصفحة القديمة إلى الصفحة الرئيسية للموقع، أو إلى التصنيف الرئيسي للموضوع الأصلي، وهذا يعتبره الزوار عملية مراوغة أو خداع وتضليل، مما يثير استيائهم وإزعاجهم. أما بالنسبة لمحركات البحث، فما يُزعج الزوار والمستخدمين يزعجها، وهذا قد يُلقي بالموقع في الهاوية. نؤكد أنّ القيام بهذه العملية بشكل خاطئ، يؤدي إلى خسارة حركةِ زوارٍ كبيرة، لأنّ الموقع يخسر ترتيبه العالمي بخسارة أرشفة صفحاته القديمة، والتي تكونُ عادةً روابطها طويلة جداً، فيقوم مشرف الموقع بإعادة التوجيه للرابط وتغييره بشكلٍ كليّ، ليظهر قصيرًا وأكثر احترافيةً وجاذبية، إلا أنه يتبع الممارسة الخاطئة ويقع في فخ عمليات التحويل. ثالثاً : رموز الحالات HTTP status كل عنوان أو صفحة يتم طلبها/زيارتها يأتي معها رمز من رموز حالات بروتوكول HTTP، هذا الرمز يشير إلى حالة الخادم أو إلى طبيعة استجابة الخادوم للطلب، المتصفحات تفهم هذه الرموز بشكل جيد، لكنها غير مرئية للزوار، من أشهر هذه الرموز: 200 Success – معنى هذه الحالة: أنّ الصفحة تم تحميلها بنجاح وبدون مشاكل . أنّ الصفحة تعمل بشكلٍ جيّد بالنسبة للمستخدمين، وأنّه يمكن فهرستها وأرشفتها بالنسبة لمحركات البحث. 301 Permanently – تم شرح هذه الحالة سابقًا بتفصيل، وتعني باختصار: أنه تم نقل الصفحة بشكلٍ دائم . أنه تم توجيه المستخدم للصفحة الجديدة، ومحركات البحث تقوم بتجاوز الرابط الأصلي إلى الرابط الجديد، مما يؤدي إلى حذف الصفحة القديمة من فهارس محرك البحث. 302 Temporarily Moved - هذه الحالة مشابهة للحالة السابقة 301 ، وتختلف عنها في: أن الصفحة تم نقلها مؤقتًا لعنوانٍ آخر. أن المستخدم لا يلاحظ عملية إعادة التوجيه هذه، بخلاف محركات البحث التي لا تتجاوزُ الرابطَ القديم بدون ملاحظة الإختلاف، وتقوم بدورها بإزالته من فهارسها الخاصةِ بها. 404 Page Not Found – تعني هذه الحالة الشائعة: أن الصفحة المطلوبة لا يمكن تحميلها أو أنها غير موجودة. بناءً على ذلك، يتم إيقاف ترتيب وتصنيف هذه الصفحة من قِبَل محركات البحث في حال ظهرت فجأة الحالة (404) للصفحة المطلوبة. 410 Page Permanently Not Found - تعني هذه الحالة عدم توفر الصفحة المطلوب تحميلُها كما أنه لن يتم توفيرها مستقبلا. تعامل محركات البحث هذه الحالة مثل تعامُلها مع الحالة السابقة 404 . 500 Internal Server Error – هذه صفحة خطأ عامة، لا تُعطي المستخدم الكثير من التفاصيل عن سبب حدوث المشكلة، ويجب عليكَ كمطوّر أنْ تحُدّ من هذه المشاكل قدرَ الإمكان، ﻷنها تعني أن هناك خطبا ما مع موقعها أو خادومك، فبالتالي يجب عليك تفحص تطبيق الويب الخاص بك من الأخطاء البرمجية أو إعدادات خادومك من خطأ ما. 503 Service Unavailable – هذه الحالة تعني أنّ الخدمة غير متوفرة حاليًا. على سبيلِ المثال: في حالِ إذا أردتَ تغيير تصميم قالبِ الموقع، بإمكانك إخبار المستخدمين عن طريق هذه الصفحة بعودة الموقعِ للعمل فيما بعد. هذه الحالة مهمة جداً لإعلام محركات البحث بعودة الموقع لعمله لاحقاً، وتوقفه عن العمل مؤقتًا. خامساً : وصول الزاحف تمكين الزاحف الخاص بمحرك البحث، عملية مهملة جدًا مِن قِبَلِ مَنْ يَعملونَ في مجال SEO، ومِن مطوّري المواقع. فَهمُ آليةِ عمل الزاحف، من الممكن أن نوضحها لك بسطرينِ أو أقل، ولكن تطبيقها كعاملٍ في مجال SEO أو كمطوّرٍ يحتاجُ مِنكَ إلى العلمِ الدقيق بذلك، حتى تُعينَ الزاحف على الوصولِ إلى كافة صفحاتِ الموقع الخاص بكْ. كيف تزحف Google لموقعك؟ يعتمد الزاحف بشكلٍ أساسي على ترتيب موقعك في محركات البحث. لماذا تعتمد Google رتبة PageRank عاملاً أساسيًا في الزحف والوصولِ إلى موقعك؟ على الرغم من أن الشركة دائمًا تسعى لأرشفة وفهرسة كل معلومة تُنشر على شبكة الويب، إلا أنها تبقى محدودة الموارد لهدفٍ عظيمٍ كهذا، فاعتمدت Google أهمية الموقع وتصنيفه العالمي معيارًا أساسيًا، تُعطي الزاحف استنادًا له أوامرًا بأولوية الزحف إليه. دوركَ كمطوّر هو في هيكلية وبِنيةِ الموقع السليمة، وأن تتأكد بإمكانية وصول زاحف محرك البحث إلى موقعك، وأن يقضي معظمَ وقته في مسحِ أهمّ الصفحاتِ فيه، وهناك الكثير من الطرق لتحقيق هذا الهدف. الموقع القوي والناجح ناجمٌ عن اتحاد فريقٍ من المتخصصين، مختص SEO ومصمم القالب ومطوّر الموقع. إذا اشترك المختصين السابقة في إنجازِ مشروع موقع ويب، ستكونُ بالتأكيدِ هيكلية الموقع من الصفر وحتى نهاية المشروع متوافقة مع محركات البحث، من هيث البنية والبرمجة والتصميم. وهذا يجعلهُ متميّزًا في التصفح الآمن، السريعِ والمريح، وأرشفة صفحاته بعد دقائقٍ من نشرها على الشبكة، لتظهر في الصفحة الأولى في نتائجِ البحث. إذا لم تتم مراعاة معايير محركات البحث للمواقع الجيّدة منذُ البادية، أي من بداية تصميم وبرمجة الموقع، ستكونُ طرقُ تحسينه محدودة فيما بعد لمحركات البحث، وهناكَ الكثير من الطرق التي سنوضحُ أهمّها كي تُراعيها كمطوّر في مواقعك. ملف Robots.txt هذا هو الملف الأول الذي يطلبه الزاحف عند الوصول إلى الموقع. من خلال هذا الملف، يُحاول الزاحف البحث عن المناطق التي لم يصل إليها بعد، وعن الروابط التي لم يتم رؤيتها في الموقع. بإمكنك منع زواحف محركات البحث من الوصول إلى أجزاء معينة من موقعك، وتقومُ بهذا الإجراء بعد عدم إمكانية حل القضايا المتعلقة ببنية الموقع ، واحذر من القيام بهذا الإجراء عن طريق الخطأ. يُعرف هذا الإجراء بِـ Rel = Canonical. يُستحسن عدم استخدامه في موقعٍ جديد، ولكنه يُعتبرُ الملجأ الوحيد للمواقع الكبيرة، ومشاكِلُها التي تتعلق في الأمور الهندسية والبنائية للموقع. قبل استخدام هذا الوسم، ابحث بقوة عن حلٍ آخر، ولا تدعه أداةً لحلّ هذه المشاكل. لماذا ننصحك بعدم استخدامِ هذا الوسم؟ لأنه ليس قاعدة ثابتة وصارمة بالنسبة لمحركات البحث، أي أنّ استخدامه لا يُمكنُ أن يكونَ صالحًا دائمًا، نظرًا للتغيير المستمر في خوارزميات وسياسات محركات البحث، وبالتالي قد يصبحُ استخدامه بدونِ فائدة. ونؤكد مرةً أخرى على عدم استخدامه إلا في حال تمّ استنفاذ كافة الخيارات الأخرى المتاحة، واجعلهُ خياركَ الأخير. سادساً: لغة برمجة الويب JavaScript هي لغة ويب رائعة، تمكنُكَ من إضافةِ وظائف كثيرة لموقعك، تعزز من تجربة المستخدم وتجعله راضٍ أكثر. علاوةً على ذلك، محركات البحث تُكافح بشدة في تنفيذ javascript، في عملية اكتشاف المحتوى المضمن بين شيفراتها. إرشادات مهمة، عليكَ الأخذ بها عند استخدام إضافة وظائف ثانوية لموقعك. لا تضع محتوىً قيّمًا ضمن شيفرة JavaScript. عليكَ دائمًا بالتأكد من أن محركات البحث تستطيع الوصول إلى محتوى موقعك، وتقرأ كل ما تنتجهُ وتنشرهُ في الموقع. لا تضيع جهدك ووقتك في صناعة المحتوى وتضمينه في شيفراتها، التي تكافح محركات البحث لاكتشاف محتوى موقعك في هذه الحالة. مثال: عندما تضع أسفل منتجٍ ما معلومات مهمة وأساسية عنه لكن المساحة لا تكفي، وتُتيح للمستخدم الإنتقل عبر أيقونة لمزيدٍ من المعلومات عنه، وتفتح الصفحة في تبويبة أو نافذة جديدة، تحسّن بذلك تجربة المستخدمة وتحوز على رضاه. وفي نفس الوقت تصعّب مهمة عمل زواحف محركات البحث في وصولها إلى المحتوى الإضافيّ عن المنتج، والذي يُفترض أن يكونَ في غاية الأهمية بالنسبة للمستهلكِ له، عند عملية البحث عنه على الشبكة العالمية، وخسارة كبيرة لك كصاحب للموقع أو للمنتج أو كلاهُما. يمكن جزئيا التغلّب على هذه المشكلة بالاستعانة بمكتبة jQuery في برمجة الوظائف الإضافية، فهي تمتلك خاصية الجمال والديناميكية في تحسين تجربة المستخدم كما في JavaScript، ومرئية وصديقة لزواحف محركات البحث. لا تضع روابطاً أو محتوىً ضمن JavaScript لإخفاءه عمدًا عن Google. هذا كان تكنيكًا متبعًا من قِبَل مَنْ يعمل في مجال SEO لأسبابٍ متعددة، وهذا يرجع إلى الزمن الذي كانت تتعرف محركات البحث عليها بصعوبة كبيرة. سبب فعلِ ذلك، هو زيادة ترتيب الموقع العالمي بإخفاءٍ الروابطِ فيه، أو لمجرد إخفاءِ محتوىً ما فيه. إلى هنا نصل إلى نهاية الدرس، بعد أن تعرفنا على أهل عناصر SEO من وجهة نظر المطور، نرجو منك أن لا تغفلها وتضعها في حسبانك إن كنت ممن يطورون تطبيق أو خدمة ويب معينة.
-
أصبحت واجهات REST البرمجية أكثر انتشارًا بين المطوّرين، نظرًا لأنها توفّر واجهة بسيطة، موحّدة وواضحة لخدمات الطرف الثالث third-party مثل Twitter، MailChimp وGitHub. ومع ازدياد شهرة واجهة ووردبريس البرمجية (المتوفرة عبر إضافة) فإن الوقت قد حان لنتعلم حول واجهة HTTP البرمجية في ووردبريس، وكيفية عملها واستخداماتها. ما هي واجهة HTTP في ووردبريس؟ لن يكون من المستغرب القول بأنها طريقة لإرسال واستقبال الرسائل بواسطة HTTP – لغة شبكة الويب. حيث يقوم المتصفح بإرسال واستقبال الرسائل طوال الوقت وبهذا الشكل يتم استقبال صفحات الويب. ويمكن من خلال واجهة REST البرمجية، يمكن باستخدام رسائل HTTP القيام بأشياء أكثر كتعديل منشور، حذف حساب مستخدم أو نشر وصفة جديدة على موقعك. لهذا السبب تعتبر واجهة ووردبريس البرمجية مهمة جدًا، فهي تسمح بفصل التطبيق من جهة المستخدم عن النواة البرمجية الخاصة بووردبريس. ولاستخدامها، تحتاج أن تكون معتادًا على إرسال طلبات HTTP واستقبال الأجوبة، وهذا هو أساس عمل واجهة HTTP البرمجية. وهناك العديد من الطرق لإرسال طلبات HTTP، حيث توفّر واجهة HTTP البرمجية طريقة موحّدة باستخدام مجموعة من التوابع المساعدة والتي سنطّلع عليها بعد قليل. طرق HTTP ومصادرها ترتكز HTTP حول الطرق methods (تسمّى أحيانًا بالأفعال verbs) والمصادر resources. تحدّد المصادر العنصر الذي سيتم تنفيذ العملية عليه، وتحدّد الطريقة نوع العملية التي سيتم تنفيذها. ويعتبر العنوان URL هو المصدر الذي يشير إلى الغرض على شبكة الويب، كمنشور على سبيل المثال. وتوجد العديد من الطرق، لكن الأهم فيها هي GET, POST, PUT و DELETE. ولا بد أن لديك الكثير من الخبرة مع GET فهذه الطريقة هي المستخدمة في الحصول على المصادر، فمثلًا عند استعراض مقال في المتصفح يتم إرسال طلب GET إلى عنوان المقال وليكن مثلًا https://premium.wpmudev.org/blog/using-the-wordpress-http-api/. أما طلبات PUT فتستخدم لتعديل المصادر، وتستخدم طلبات POST لإنشاء مصادر جديدة، وتستخدم طلبات DELETE لحذف مصادر موجودة مسبقًا. ولو كان لدى موقع WPMU DEV واجهة REST برمجية، فربما كان من الممكن أن يقوم المدير بإرسال طلب DELETE لحذف المقال على الرابط https://premium.wpmudev.org/blog/wordpress-http-api، وهذا الأمر مفيد جدًا للمواقع الكبيرة التي تملك برامج إدارة على الهواتف الذكية. مثال عن طلب HTTP بسيط للقيام بإرسال طلب GET بسيط على سبيل التجربة، سنقوم باستخدام التابع wp_remote_get() الذي يملك مُعاملين، المُعامل الأول هو رابط المصدر، والمُعامل الثاني هو مصفوفة اختيارية optional من الخيارات التي من الممكن استخدامها لتحديد بعض التفاصيل. $test = wp_remote_get( 'http://google.com' ); echo "<pre>"; var_dump($test); echo "</pre>"; يقوم المثال السابق بجلب الصفحة الرئيسية لموقع جوجل، ومن ثم يتم طباعة محتوى المتغير test الذي يحوي على جواب الطلب الذي أرسله موقع جوجل – حيث يمكن رؤية جميع العناصر التي يحتويها. تحتوي الترويسات headers على المزيد من المعلومات عن كل رسالة. وقد تطلب منك بعض واجهات REST البرمجية أن تقوم بإرسال معلومات محددة في الترويسات عندما ترسل الطلب. يحتوي الجواب response على رمز الحالة status code وعبارة قد تكون معروفة بالنسبة لك كأخطاء 404، أو خطأ في معالجة الطلب 500 أو تحويل من النوع 301 أو 302. يحتوي موقع W3.org على جميع رموز أخطاء HTTP المعرّفة والمشروحة، ويعتبر مصدرًا مفيدًا إن احتجت أن تعرف ما يعني أي خطأ. بإمكانك أيضا الاطّلاع على هذا المقال على أكاديمية حسوب لتعرف المزيد حول هذه الرّموز: رموز الإجابة في HTTP يحتوي الجسم body على الجواب وهو المكان الذي تحتاج أن تنظر إليه بحثًا عن النتيجة المطلوبة. في حالة المثال السابق، فإننا نحصل على وسوم HTML التي تشكّل الصفحة الرئيسية، ولكن عند التعامل مع واجهات REST البرمجية فمن الشائع أن نحصل على نص بصيغة JSON. وعادة ما تطلب الواجهات البرمجية APIs أن يتم إضافة نص محدّد إلى الجسم عند إرسال طلبات أيضًا. يحتوي قسم cookies على أي كعكات تم استلامها مع الرسالة. كما ترى، فإن إرسال طلب باستخدام واجهة HTTP البرمجية أمر بسيط جدًا. ما يجعل العمل مع HTTP معقّد نوعًا ما هو أن واجهات REST البرمجية قد تكون حساسة جدًا لصيغة البيانات المدخلة (وهو أمر جيّد) لذا فإن تجاوزت سطرًا عند دراسة توثيق الواجهة البرمجية قد ينتهي بك الأمر ببرمجية لا تعمل كما ترغب. العمل مع الواجهات البرمجية أعتقد بأنه من الآمن القول بأن معظمكم سيستخدم HTTP للتعامل مع واجهات REST البرمجية في شبكة الويب، وفي هذه الحالة سنحتاج لاستخدام المعامل الثاني لتحديد بعض الأمور، كالاستيثاق وتجنب بعض الأخطاء الشائعة. لنبدأ بمثال بسيط – استعادة البيانات من لوحة Pinterest. تتطلب جميع الواجهات البرمجية الجيّدة تنفيذ عملية استيثاق للتعريف عن المستخدم الذي يرسل الطلب، لكنّنا سنغش قليلًا في هذا المثال باستخدام مولّد رموز الأمان الخاص بـ Pinterest. بعد إكمال الاستيثاق ستحصل على رمز أمان يمكن استخدامه في المثال التالي، حيث سنقوم بإنشاء طلب لجلب وعرض قائمة بمنشورات Pinterest. $request = wp_remote_get( 'https://api.pinterest.com/v1/boards/marticz/home-office/pins/?access_token=<your access token>' ); $pins = json_decode( $request['body'], true ); if( !empty( $pins['data'] ) ) { echo '<ul>'; foreach( $pins['data'] as $pin ) { echo '<li><a href="' . $pin['url'] . '">' . $pin['note']. '</a></li>'; } echo '</ul>'; } لو قمنا بنسخ المثال السابق ولصقه في صفحة content-page.php في قالب Twenty Fifteen لتجربته فإن النتيجة هو الحصول على لائحة بالمنشورات من لوحة Pinterest حول المكاتب الشخصية في المنزل. لا تنس أن تستبدل <your access token> في المثال السابق برمز الأمان الذي حصلت عليه. يقوم السطر الثاني في المثال بفك ترميز جسم الجواب من JSON إلى شكله الأساسي كمصفوفة ونقوم بإنشاء حلقة loop تقوم بطباعة محتوى عنصر المصفوفة $pins['data']. الاستيثاق يقع العديد من الأشخاص في عثرات في هذه المرحلة لأنها تتطلب خطوة إضافية على الأقل وربما بعض الترويسات الإضافية أيضًا. ولننظر إلى واجهة تويتر البرمجية على سبيل المثال، وتحديدًا إلى الاستيثاق الخاص بالتطبيقات، الذي يمكنك استخدامه لاستيثاق تطبيقك مع تويتر. قراءة التوثيق إن أول خطأ قد يتم ارتكابه هو عدم قراءة التوثيق بشكل جيّد. ولو كنت مبرمجًا متمرسًا في واجهات REST البرمجية فيمكنك القفز مباشرة إلى الجزء حول الاستيثاق، ولو فعلت هذا فقد لا تنتبه إلى سطر يقول: وإهمال هذا الشرط سيؤدي إلى فشل حتمًا في الحصول على نتيجة، على الرغم من أن كل شيء آخر مطبّق بشكل كامل، لذا حتى توفّر على نفسك الحاجة لمراجعة شفرة برنامجك، تأكد من قراءة التوثيق بشكل جيّد وكامل. إضافة ترويسات ومعاملات أخرى بعد اتباع التوجيهات في التوثيق حرفيًّا، قمت بإنشاء طلب POST، ينبغي أن يؤدي إلى توليد رمز أمان للوصول من أجلي، ويبدو الكود على الشكل: $key = base64_encode( urlencode( "n8KP16uvGZA6xvFTtb8IAA:i4pmOV0duXJv7TyF5IvyFdh5wDIqfJOovKjs92ei878" ) ); $request = wp_remote_post('https://api.twitter.com/oauth2/token', array( 'headers' => array( 'Authorization' => 'Basic ' . $key, 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' ), 'body' => 'grant_type=client_credentials', 'httpversion' => '1.1' )); $token = json_decode( $request['body'] ); echo "<pre>"; var_dump($token); echo "</pre>"; إن الخطوة الأولى هو ترميز رمز أمان الوصول والكلمة السرّية بصيغة URL encoding. قمت أيضًا بإضافة ترويستين، واحدة ترويسة استيثاق تحوي على بيانات الوصول. أما الترويسة الثانية فهي ترويسة نوع المحتوى content type، والتي يطلب توثيق تويتر إضافتها. إضافة لما سبق، قمت بملء جسم الطلب تمامًا كما ذكرت الملاحظة السابقة حول grant_type=client_credentials وتم إضافة إصدار HTTP كما يطلب توثيق تويتر أيضًا. سيحتوي الجواب بالإضافة للعديد من المعلومات الأخرى على رمز أمان الوصول في جسم الجواب، وسنحتاج لرمز الأمان هذا في جميع الطلبات اللاحقة المرسلة إلى الواجهة البرمجية الخاصة بتويتر. تخزين رمز أمان الوصول إن رمز الأمان صالح لبعض الوقت، ويعتبر طلبه مجدّدًا هدرًا غير ضروري عند تحميل كل صفحة أو عندما يحتاج تطبيقك أن يقوم بعملية ما وسيؤدي إلى استهلاك عدد الطلبات المسموح بسرعة. يمكن في ووردبريس استخدام عابرة transient لتخزين قيمة رمز الأمان ومن ثم استخدام العابرة عند كل طلب لاحق للواجهة البرمجية. $token = get_transient( 'twitter_access_token' ); $token = ( empty( $token ) ) ? get_twitter_access_token() : $token; $request = wp_remote_get('https://api.twitter.com/1.1/followers/ids.json?screen_name=danielpataki&count=5', array( 'headers' => array( 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' ), 'httpversion' => '1.1' )); $token = json_decode( $request['body'] ); سيؤدي إرسال الطلب السابق إلى واجهة تويتر البرمجية إلى عرض 5 من متابعيّ على تويتر (قائمة بسيطة لأرقام حساباتهم Ids). وكما يظهر في المثال السابق، فإنني أقوم بجلب القيمة التي خزّنتها في العابرة فإن لم تكن موجودة سأقوم باستدعاء التابع get_twitter_access_token() للحصول على رمز أمان جديد ومن ثم إضافته إلى العابرة كي أستخدمه في الطلبات اللاحقة. تجدر الإشارة إلى أن هذه الطريقة تهدف فقط إلى إظهار آلية التنفيذ وليست أفضل طريقة للتنفيذ، وكسيناريو أبسط كنت لأقوم بوضع جميع العبارات الشرطية IFs داخل التابع get_twitter_access_token() الذي سيقوم بتنفيذ جميع الشيفرة السابقة ضمنيًا. التوابع المساعدة في واجهة HTTP البرمجية الآن وبعد أن حصلنا على لمحة جيدة حول هدف المقال، دعونا نلق نظرة على التوابع التي ستساعدك في واجهة HTTP البرمجية في ووردبريس. هناك 4 توابع يمكن بواسطتها تنفيذ طلبات: wp_remote_get() wp_remote_post() wp_remote_head() wp_remote_request() ومن الواضح تمامًا وظيفة كل تابع، أما التابع الأخير wp_remote_request() فهو تابع عام يمكنك استخدامه مع أي طريقة HTTP method. أما التوابع الخمسة التالية فتسمح لك بالحصول على جواب على الطلب بسهولة باستخدام توابع قياسية عوضًا عن الخوض في التعامل مع المصفوفات وعناصرها. wp_remote_retrieve_body() wp_remote_retrieve_header() wp_remote_retrieve_headers() wp_remote_retrieve_response_code() wp_remote_retrieve_response_message() أيضًا يبين اسم كل تابع الهدف الوظيفي له بسهولة، وينصح عند الإمكان باستخدام هذه التوابع عوضًا عن التعامل مع المصفوفات يدويًا، حيث ستسمح هذه الطريقة الموحّدة لمطوّرين آخرين بفهم البرمجية بسهولة واستخدام الخطافات hooks إن أصبحت متاحة في المستقبل. الخلاصة كما ترى فإن التعامل مع واجهة REST البرمجية سهل باستخدام واجهة HTTP البرمجية في ووردبريس وبعض توابع ووردبريس كالعبّارات. أنصح بشدّة تجربة هذا الأمر لأن عملية التطوير في ووردبريس تسير بثقة باتجاه العالم المُقاد باستخدام الواجهات البرمجية وعليك أن تقفز إلى الموكب قبل فوات الأوان. إن كان لديك المزيد من الأسئلة حول استخدام واجهة HTTP البرمجية أو لديك بعض الأفكار حول كيفية استخدامها، فلا تتردد بمناقشة الأمر في قسم التعليقات في الأسفل. ترجمة -وبتصرّف- للمقال How to Use the WordPress HTTP API لصاحبه Daniel Pataki.
-
يُعدّ Nginx خادوم ويب مفتوح المصدر يتسّم بالسرعة والاعتمادية، كسب شعبيّته نتيجة حجم الذاكرة القليل الذي يستهلكه، وقابليته الكبيرة للتوسعة، وسهولة إعداده، ودعمه لمعظم البروتوكولات المختلفة. ويعتبر بروتوكول HTTP/2 الجديد نسبيًا أحد البروتوكولات التي يدعمها خادوم Nginx، الأمر الذي تم منذ أقل من عام مضى، وتعتبر الميّزة الرئيسية في HTTP/2 هي سرعة نقله العالية للمحتويات الغنيّة بالمعلومات في مواقع الويب. سيساعد المقال على تثبيت وإعداد خادوم Nginx سريع وآمن مع دعم لبروتوكول HTTP/2. المتطلبات الأولية قبل أن نبدأ، سنحتاج للأمور التالية: نظام تشغيل Ubuntu 14.04، مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر sudo. يمكن مراجعة الإعداد الابتدائي لخادوم أوبونتو 14.04 لمزيد من المعلومات، نطاق موقع، ويمكن شراء واحد من موقع Namecheap أو الحصول على واحد مجانًا من موقع Freenom، تأكّد من أنّ النطاق يشير إلى عنوان نظام التشغيل الذي ستستخدمه عبر الإنترنت، وستساعدك مقالة إعداد اسم مضيف مع DigitalOcean إن احتجت لمساعدة، شهادة SSL رقميّة، ويمكن إنشاء واحدة بشكل يدوي، أو الحصول على واحدة مجانًا من Let’s Encrypt، أو شراء واحدة من مزوّد آخر. هذا كل شيء، فإن كانت لديك جميع المتطلبات المذكورة، فأنت جاهز للبدء. الفرق ما بين HTTP 1.1 و HTTP/2 إن HTTP/2 هو الإصدار الجديد من بروتوكول نقل النصوص الفائقة HTTP، الذي يستخدم على الشبكة العنكبوتية لإيصال محتويات صفحات الويب من الخوادم إلى المتصفّحات، وهو أول تحديث ضخم طرأ على HTTPمنذ حوالي عقدين، حيث تم إطلاق الإصدار HTTP 1.1 عام 1999 حينما كانت الصفحات عبارة عن ملف HTML مستقل مع أنماط CSS ضمنيّة (أي مكتوبة ضمن مستند HTML وليست مستوردة من ملف خارجي). لقد تغيّرت شبكة الإنترنت بشكل متسارع في السنوات الستة عشر الأخيرة، وأصبحنا الآن نواجه صعوبة مع المحدودية التي يفرضها HTTP 1.1، حيث يَحُدّ البروتوكول من سرعة النقل الممكنة لمعظم مواقع الويب الحديثة لأنه يقوم بتحميل أجزاء الصفحة وفق مبدأ الطابور queue (بمعنى أنه يجب أن ينتهي تحميل كل جزء قبل أن يبدأ تحميل الجزء التالي له)، ويحتاج موقع ويب حديث وسطيًّا حوالي 100 طلب ليتم تحميل الصفحة(كل طلب يمثّل صورة، ملف js، ملف css، إلخ). يقوم بروتوكول HTTP/2 بحل هذه المشكلة لأنّه يقوم بتقديم تغييرات جذرية تتمثل في: تحميل جميع الطلبات على التوازي، وليس على التسلسل كما في مبدأ الطابور، ضغط ترويسة HTTP، نقل الصفحات عبر الشبكة بصيغة ثنائية binary، وليس كنصوص text، وهذا أكثر فعالية، قدرة الخادوم الآن على "دفع" البيانات قبل أن يطلبها المستخدم، مما سيحسّن من السرعة للمستخدمين الذين يعانون من بطء في الإرسال. وعلى الرغم من أن بروتوكول HTTP/2 لا يتطلب التشفير، إلا أن مطوّري أشهر متصفّحين، Google Chrome و Mozilla Firefox، صرّحوا بأنه -لدواع أمنيّة- سيتم دعم بروتوكول HTTP/2 في اتصالات HTTPS الآمنة فقط، ولهذا السبب إن قررت تثبيت خواديم تدعم HTTP/2 فيجب عليك الانتقال إلى استخدام HTTPS. الخطوة الأولى: تثبيت الإصدار الأخير من Nginx تم طرح دعم HTTP/2 في إصدار Nginx 1.9.5، ولسوء الحظ فإنّ المستودع الافتراضي في نظام Ubuntu متأخر عن إدراج آخر إصدار ويقوم حاليًّا بتوفير الإصدار 1.4.6. لكن لحسن الحظ فإن مطوّري Nginx لديهم مستودع apt خاص على نظام Ubuntu، حيث بالإمكان الحصول دومًا على آخر إصدار متوفّر. لإضافة المستودع الخاص إلى قائمة مستودعات apt لدينا، نحتاج أولًا للحصول على مفتاح التوقيع الرقمي الخاص بالمستودع، وهذا إجراء أمني يضمن بأن الحزم البرمجية التي سنحصل عليها من هذا المستودع صادرة عن المطوّرين الحقيقين وموقّعة منهم. سنقوم بتنفيذ الأمر التالي في سطر الأوامر: $ wget -qO - http://nginx.org/keys/nginx_signing.key | sudo apt-key add - بعد ذلك، سنقوم بإضافة المستودع إلى قائمة مصادر الحزم البرمجية، بتنفيذ الأمر التالي: $ sudo echo -e "deb http://nginx.org/packages/mainline/ubuntu/ `lsb_release -cs` nginx\ndeb-src http://nginx.org/packages/mainline/ubuntu/ `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list الآن وبعد أن أصبح نظام الحزم (الذي يدعى apt في نظامي Ubuntu و Debian) يعلم عن توفّر المستودع الجديد، سنقوم بتحديث قائمة الحزم البرمجية المتوفّرة وأخيرًا سنقوم بتثبيت الإصدار الأخير من Nginx: $ sudo apt-get update $ sudo apt-get install nginx ويمكن التحقق من رقم الإصدار بتنفيذ الأمر: $ sudo nginx -v حيث ينبغي أن يكون الخرج مشابهًا لـ nginx version: nginx/1.9.x. سنقوم في الخطوات التالية بتغيير الإعدادات الافتراضية في Nginx ليقوم بتخديم موقع الويب الخاص بنا. الخطوة الثانية: تغيير منفذ التنصّت الافتراضي سنقوم أولًا بتغيير رقم المنفذ من 80 إلى 443، وذلك بفتح ملف الإعدادات: $ sudo nano /etc/nginx/conf.d/default.conf ملاحظة: في حال ظهر خطأ يخبرك بأنه لم يتم التعرّف على الأمر nano، فتأكّد من تثبيت محرر النصوص nano وحاول مجدّدًا. ينبغي أن نخبر Nginx برقم المنفذ الذي يجب عليه تلقّي الاتصالات عبره، وهو المنفذ 80 افتراضيًا، المنفذ القياسي في بروتوكول HTTP. سنبحث في ملف الإعدادات عن السطر التالي: listen 80; سنقوم بتغيير المنفذ إلى 443 لأن HTTP/2 لن يعمل مع معظم المستخدمين إذا بقي يقوم بإرسال البيانات عبر المنفذ 80، كما أشرنا سابقًا إلى أنه مدعوم فقط عبر المنفذ 443 على متصفحات Chrome و Firefox.سنستبدل السطر السابق بـ: listen 443 ssl http2; لاحظ أننا أضفنا كلمة ssl و http2 في نهاية السطر، وتخبر هذه المتغيّرات Nginx بأن يستخدم بروتوكول HTTP/2 مع المتصفحات التي تدعم البروتوكول الجديد. الخطوة الثالثة: تغيير اسم الخادوم يأتي اسم الخادوم server_name بعد السطر السابق الذي يحوي على listen، وسنقوم بإعلام Nginx أيّ نطاق سيرتبط مع ملف الإعدادات. سنستبدل الاسم الافتراضي localhost الذي يعني بأن ملف الإعدادات مسؤول عن جميع الطلبات الواردة، وسنضع مكانه اسم النطاق الحقيقي، كـ example.com على سبيل المثال: server_name example.com; سنقوم الآن بحفظ التغييرات بالضغط على CTRL+O ومن ثم نضغط CTRL+X للخروج من محرر nano. الخطوة الرابعة: إضافة المسار إلى شهادات SSL الأمنية سنقوم بإعداد Nginx الآن ليستخدم الشهادات الأمنية اللازمة لـ HTTPS، وإن لم تكن تعلم ما هي الشهادة الأمنية أو لم تكن تملك واحدة فيرجى مراجعة المقالات المذكورة في قسم المتطلبّات الأولية في بداية المقال. لنقم أولًا بإنشاء مجلّد لحفظ الشهادات الأمنية فيه داخل مجلد إعدادات Nginx: $ sudo mkdir /etc/nginx/ssl سنقوم الآن بنسخ ملف الشهادة وملف المفتاح الخاص private key إلى داخل المجلد الجديد، وبعد ذلك سنقوم بتغيير أسماء الملفات لتظهر بوضوح أي نطاق ترتبط معه (تساعد هذه الخطوة في المستقبل على توفير الوقت والجهد إن امتلكت أكثر من نطاق واحد). لا تنسى استبدال example.com باسم النطاق الخاص بك. $ sudo cp /path/to/your/certificate.crt /etc/nginx/ssl/example.com.crt $ sudo cp /path/to/your/private.key /etc/nginx/ssl/example.com.key سنقوم بإضافة سطر جديد الآن إلى ملف الإعدادات ضمن كتلة server لتعريف مسارات الشهادة الرقمية مع مفتاحها الخاص ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; الخطوة الخامسة: تحويل جميع طلبات HTTP إلى HTTPS ينبغي الآن أن نخبر Nginx بأننا نرغب بتوفير المحتوى عبر HTTPS فقط إن استلم طلب HTTP عوضًا عن ذلك. سنقوم في نهاية ملف الإعدادات بإنشاء كتلة server جديدة لتحويل جميع طلبات HTTP إلى HTTPS، ومرة أخرى لا تنس استبدال النطاق باسم النطاق الخاص بك، ستكون الكتلة الجديدة على الشكل التالي: server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; } لاحظ في الكتلة السابقة كيف أنّ Nginx عند استلامه لطلبات HTTP تخص النطاق example.com عبر المنفذ 80، فإنّه سيقوم بتحويل الطلب إلى HTTPS على نفس المسار المطلوب، مستخدمّا التحويل من النمط301 (moved permanently). سيصبح شكل ملف الإعدادات (إن تجاهلنا الأسطر الخاصة بالتعليقات) على النحو التالي: server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name example.com; location / { try_files $uri $uri/ =404; } ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_dhparam /etc/nginx/ssl/dhparam.pem; } server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; } سنقوم الآن بحفظ ملف الإعدادات بالضغط على CTRL+O ومن ثم الخروج من محرر nano بالضغط على CTRL+X. الخطوة السادسة: تحميل ملف الإعدادات الجديد في ذاكرة Nginx لتطبيق التغييرات التي قمنا بها، سنحتاج لإعادة تشغيل خادوم Nginx: $ sudo service nginx restart وللتحقق من أن كل شيء سار على ما يرام، سنقوم بفتح المتصفح واستعراض النطاق الذي أعددناه مع Nginx، فإن كانت الإعدادات صحيحة، يجب أن يتم تحويل الطلب إلى HTTPS بشكل تلقائي، وللتأكد مما إذا تم استخدام البروتوكول الجديد فسنقوم بفتح أدوات المطوّر (في متصفح كروم يمكن فتحها من خلال قائمة View > Developer > Developer Tools)، ومن ثم نعيد تحميل الصفحة من جديد (View > Reload This Page)، ثم من خلال لسان Network، سنضغط بالزر الأيمن للفأرة على سطر رأس الجدول ونختار Protocol. يجب الآن أن يظهر عمود جديد عنوانه Protocol ستتمكن من خلاله من رؤية أن البروتوكول المستخدم هو h2 (الذي يرمز إلى بروتوكول HTTP/2) في حال تم الإعداد بشكل صحيح. إلى هنا سيكون Nginx قد أصبح قادرًا على تخديم المحتوى باستخدام بروتوكول HTTP/2، ولكن تبقى هناك بعض الأمور التي ينبغي إعدادها قبل استخدام الخادوم في بيئة التشغيل. الخطوة السابعة: تحسين Nginx لتقديم أداء أفضل سنقوم الآن بفتح ملف الإعدادات مجدّدًا لضبط إعدادات Nginx لتقديم أفضل أداء وحماية. تفعيل Connection Credentials Caching بالمقارنة مع HTTP، فإن HTTPS يتطلب وقتًا أطول نسبيًا لإنشاء اتصال ما بين الخادوم والمستخدم، ولتقليل الفرق في سرعة تحميل الصفحة، سنقوم بتفعيل ميّزة Connection Credentials Caching وهذا يعني بأنه عوضًا عن إنشاء جلسة عمل جديدة عند طلب كل صفحة، سيقوم الخادوم باستخدام نسخة خبء cache لمعلومات المصادقة. لتفعيل الميّزة، سنقوم بإضافة السطرين التاليين إلى نهاية كتلة http في ملف الإعدادات: ssl_session_cache shared:SSL:5m; ssl_session_timeout 1h; يقوم المتغيّر ssl_session_cache بتحديد حجم الخبء الذي سيحتوي على معلومات الجلسة، حيث يمكن لـ 1MB أن يقوم بتخزين معلومات 4000 جلسة عمل، وبالتالي ستكون القيمة الافتراضية 5MB أكثر من كافية لمعظم الحالات، ولكن إن كنت تتوقع أن يكون هناك حركة مرور كثيفة على الموقع، فيمكنك زيادة القيمة وفقًا لذلك. يحدّد المتغير ssl_session_timeout من الوقت الذي تكون ضمنه جلسة العمل فعّالة داخل الخبء، ولا ينبغي أن تكون هذه القيمة كبيرة (أكثر من ساعة)، وإلى جانب ذلك فإن تخفيضها كثيرًا سيخفض من الفائدة المرجوّة أيضًا. تحسين باقات التشفير Cipher Suites باقات التشفير هي مجموعة من خوارزميات التشفير التي تصف كيف ينبغي أن يتم تشفير البيانات المنقولة. يملك بروتوكول HTTP/2 قائمة كبيرة من خوارزميات التشفير القديمة وغير الآمنة التي يجب تجنّب استخدامها. سنقوم باستخدام مجموعة تشفير معتمدة من قبل جهات عملاقة مثل CloudFlare. لا تسمح هذه المجموعات باستخدام خوارزمية MD5 في التشفير (التي تم إثبات أنها غير آمنة في عام 1996، وبالرغم من ذلك، فما تزال منتشرة حتى يومنا هذا). سنقوم بإضافة السطرين التاليين بعد ssl_session_timeout: ssl_prefer_server_ciphers on; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; تفعيل ميزة (Strict Transport Security (HSTS على الرغم من أنّا قمنا بتحويل جميع طلبات HTTP إلى HTTPS في إعدادات Nginx، فينبغي علينا أيضًا أن نقوم بتفعيل ميّزة Strict Transport Security لتجنّب الحاجة لإخبار Nginx بعملية التحويل بأنفسنا أساسًا. عندما يصادف المتصفح ترويسة HSTS، فلن يحاول الاتصال بالخادوم عبر HTTP التقليدي مجدّدًا قبل مضي فترة من الوقت، ومهما حصل، سيعمل على تبادل البيانات عبر اتصالات HTTPS مشفّرة. تساعد هذه الترويسة على حمايتنا من هجمات تخفيض البروتوكول. كل ما نحتاجه هو إضافة السطر التالي في ملف الإعدادات: add_header Strict-Transport-Security "max-age=15768000" always; يحدّد المتغير max-age القيمة التي يجب على المتصفح خلالها ألا يحاول التواصل مع الخادوم إلا عبر بروتوكول HTTPS، وهذه القيمة ممثّلة بالثواني وبالتالي فإن القيمة 15768000 تساوي 6 أشهر. وبشكل افتراضي فإن هذه الترويسة لن يتم إضافتها إلى الطلبات الموجّهة للنطاقات الفرعية، فإن كنت تملك نطاقات فرعية وترغب أن يتم تطبيق HSTS عليها جميعًا فيجب إضافة المتغير includeSubDomains حينها إلى نهاية السطر على الشكل التالي: add_header Strict-Transport-Security "max-age=15768000; includeSubDomains: always;"; لا تنس حفظ الملف الآن بالضغط على CTRL+O ومن ثم إغلاقه بالضغط على CTRL+X إن كنت تستخدم محرر nano. الخطوة الثامنة: رفع حماية تبادل المفاتيح الأمنية إن الخطوة الأولى في إنشاء اتصال آمن هو تبادل المفاتيح الخاصة بين الخادوم والعميل، وتكمن المشكلة في هذه العملية في أنّه حتى تلك اللحظة فالاتصال غير مشفّر بينهما وبالتالي فالبيانات المتبادلة يمكن التنصّت عليها من طرف ثالث. لهذا السبب، سنحتاج لاستخدام خوارزمية Diffie-Hellman-Merkle في تبادل المفاتيح. يستخدم Nginx بشكل افتراضي مفتاح DHE) Ephemeral Diffie-Hellman) بطول 1024 بت، والذي يمكن فك تشفيره بسهولة نسبيًا، وللحصول على أمان أعلى فينبغي علينا إنشاء مفتاح DHE خاص أكثر أمنًا. للقيام بذلك سنقوم بتنفيذ الأمر التالي في سطر الأوامر: $ sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048 تنبيه: يجب أن يتم إنشاء مُعاملات DH في المجلد الذي قمنا بتخزين الشهادات الأمنية فيه، وفي المقال قمنا بتخزين الشهادات في المسار /etc/nginx/ssl/. إن السبب وراء هذا هو أن Nginx يقوم دومًا بالبحث عن مفتاح DHE الخاص بالمستخدم في مجلد الشهادات الأمنية ويستخدمه إن وُجد. تحدّد القيمة 2048 في الأمر السابق طول المفتاح الذي نرغب بإنشائه، حيث سيكون مفتاح بطول 2048 بت أكثر أمنًا وينصح به من قبل مؤسسة موزيلّا، ولكن إن كنت تسعى خلف أقصى درجة أمان، فيمكنك استخدام مفتاح بطول 4096 بت. ستأخذ عملية إنشاء المفتاح حوالي 5 دقائق، ويمكنك أثناء ذلك الاسترخاء وارتشاف بعض القهوة. لتطبيق التغييرات التي قمنا بها على ملف الإعدادات، لا تنسى أن تقوم بإيقاف وإعادة تشغيل خادوم Nginx: $ sudo service nginx restart الخلاصة أصبح اتصال SSL الخاص بك أكثر أمنًا وقابلًا للاستخدام لنقل المعلومات الحساسة، ولكن إن أردت اختبار قوته الأمنية فقم بزيارة Qualys SSL Lab وبتشغيل اختبار على خادومك، حيث ينبغي أن تحصل على نتيجة A+إن كان كلّ شيء معدّ بشكل صحيح. هذا كلّ شيء، أصبح خادوم Nginx الخاص بك جاهزًا للاستخدام، وكما ترى فإن بروتوكول HTTP/2 هو حل رائع لتحسين سرعات نقل البيانات ومن السهل استخدامه كما أظهرنا في المقال. ترجمة -وبتصرّف- للمقال How To Set Up Nginx with HTTP/2 Support on Ubuntu 14.04 لصاحبه Sergey Zhukaev.
-
يسمح تحويل الطلبات بإرسالها من عنوان URL إلى آخر تلقائيًا، وهي طريقة عملية لإرسال الزوار وعناكب محركات البحث إلى عنوان URL مختلف عن العنوان الأصليّ المطلوب، ويمكّن من الحفاظ على تقييم محركات البحث لعنوان معيّن، كما يساعد في الحفاظ على أيّة زيارات محتملة لمحتوى قديم من خلال تحويلها إلى المحتوى الجديد بعد أن تمّ تحديثه. سنستعرض كيفية إنشاء تحويلات 301 (أو ما يُعرف أيضًا بـ 301 Redirect)مع بعض الطرق التي يُمكن استخدامها للحفاظ على محتوى حديث للموقع من أجل تقييم SEO أعلى، ومثالًا عن استخدامنا تحويل 301 على مدوّنتنا لرفع معدّل الزيارات. ما هي أنماط التحويل المتوفرة؟ يوجد أنماط مختلفة للتحويل تحمل الرموز (301، 302، 307) بالإضافة إلى تحديث الصفحة باستخدام وسم meta. 1. التحويل 301 (301 Redirect) تحويل دائم للطلبات من عنوان لآخر، يسمح بتمرير 90-99% من عصير الروابط (قوّة التقييم) القادمة من محركات البحث لعنوان ما إلى العنوان الجديد، حيث يشير الرقم 301 إلى رمز حالة HTTP، التي تخبر محركات البحث بأنّ الصفحة قد نُقلت. إنّ هذا التحويل هو الأفضل لتحويل الطلبات من رابط لآخر في معظم الحالات. 2. التحويل 302 تحويل مؤقّت لطلبات عنوان ما لعنوان آخر، يقوم بتمرير 0% من عصير الروابط (قوّة التقييم) محرك البحث إلى العنوان الجديد، ويفضّل تجنّب استخدامه في معظم الحالات. 3. التحويل 307 الإصدار البديل عن تحويل 302 المتوفّر في الإصدار 1.1 لبروتوكول HTTP. 4. وسم meta نوع من أنواع التحويل الذي يمكن تنفيذه في المتصفّح لدى العميل مباشرة عوضًا عن تنفيذه على مستوى الخادوم. إنّ من الأفضل بشكل عام استخدام التحويل من النمط 301 عند القيام بتحويل طلبات عنوان لآخر بهدف المحافظة على تقييم محرّكات البحث. لماذا قد نحتاج للتحويل 301 (301 Redirect)؟ يستحسن استخدام التحويل 301 بهدف المحافظة على الزوّار وعلى تقييم محركات البحث لعنوان ما، فإعادة جواب من الخادوم يحمل رمز التحويل 301 هو إشارة واضحة للمتصفّح ومحرّكات البحث بأنّ الصفحة قد انتقلت من هذا العنوان بشكل نهائي. ستقوم محركات البحث بتفسير ذلك بأنّ الصفحة لم تنتقل إلى عنوان جديد فحسب، ولكنّ المحتوى -أو نسخة أحدث منه- يمكن إيجاده على العنوان الجديد، عندها يتم نقل قوّة التقييم من العنوان الأصليّ إلى العنوان الجديد. إنّ استخدام التحويل 301 بالشكل الصحيح له القدرة على إعادة تنظيم أيّ هيكلة سيّئة للموقع، بالإضافة إلى حلّ مشكلة المحتوى القديم ورفع جودة تجربة الزائر، كلّ ذلك مع المحافظة على قوّة التقييم. اكتشفنا في أحد الأشهر الماضية بأنّ إحدى المنشورات القديمة التي تعود لعام 2011 وأخرى لعام 2012، كانت تحصل على معدّل زيارات مرتفع، لذا قرّرنا استخدام هذه التقنيّة على سبيل التجربة، لذا أنشأنا مقالًا جديدًا بتاريخ 2 ديسمبر 2013، وقمنا بتحويل الطلبات من المقالات القديمة إلى المنشور الجديد وخلال ذلك الشهر حتى 31 ديسمبر، حصل المنشور الجديد على أكثر من 13,000 زيارة من محرّكات البحث فقط، تتضمن الزيارات تلك التي تمّ تحويلها من المقالات القديمة إليه. لم يكن الوقت ليكون أفضل من ذلك، فلم يكن محتوى المقال مناسبًا لفترة نهاية العام فحسب بل كان المقال من أفضل المقالات في ذلك الشهر بحسب عدد الزيارات، فقد تمكّنا من تحويل معظم الزيارات من المقالات القديمة إلى المحتوى الجديد مُعْلمين بذلك كلًّا من الزوّار ومحرّكات البحث بأنّ لدينا مقالات ذات محتوى جديد ومناسب. إنشاء التحويل باستخدام الإضافات إضافة Redirection تسمح إضافة Redirection بإدارة التحويل من النمط 301 ومتابعة أي أخطاء 404 تظهر عند طلب محتوى غير موجود، وتعمل الإضافة عبر ووردبريس فقط دون الحاجة للوصول إلى ملف htaccess. أو أيّ من إعدادات خادوم أباتشي. تتمتع الإضافة بميّزة عظيمة هي إحصائيات التحويل التي تسمح لك بمشاهدة عدد المرّات التي تمّ فيها تنفيذ تحويل لعنوان مطلوب، وآخر مرّة تمّ فيها ذلك، ومن كان صاحب الطلب (زائر أم محرّك بحث) وأين كان يوجد العنوان الذي تمّ طلبه قبل التحويل. إضافة SEO Redirection تسمح إضافة SEO Redirection بإعداد تحويل سريع للطلبات باستخدام الأنماط 301, 302 و307، كما يمكنك مراقبة أخطاء 404 التي تشير إلى محتوى غير متوفّر وتسمح بتحويل الطلبات تلك إلى عناوين أخرى، وتتميّز الإضافة بأنّه من السهل جدًّا إنشاء التحويل حيث يكفي إدخال العنوان القديم والجديد الذي ترغب بتحويل الزيارات إليه وأخيرًا نوع التحويل (301, 302, 307) الذي ترغب باستخدامه. إضافة Quick Page/Post Redirection تسمح إضافة Quick Page/Post Redirect بإرسال الزيارات من عنوان لآخر على ذات النطاق أو على موقع آخر، وتتمتع بالكثير من الخيارات المتاحة التي تسمح بإنشاء التحويل ونمطه، استيراد وتصدير لوائح التحويل، خيارات التجاوز override أو حذف كلّ عمليات التحويل التي تمّ إضافتها. إنشاء التحويل باستخدام htaccess. وتبقى هذه الطريقة من أبسط الطرق لإنشاء تحويل 301 من خلال إنشاء ملف htaccess. في الجذر الرئيسي للموقع -إن لم يكن الملف موجودًا مسبقًا- حيث أنّ هذه الطريقة سهلة وسريعة ومناسبة لمحرّكات البحث، لكن تذكّر بأنّ هذه الطريقة تعمل فقط مع خوادم أباتشي Apache. لتحويل زيارات صفحة واحدة: Redirect 301 /oldpage.html http://www.yoursite.com/newpage.html Redirect 301 /oldpage2.html http://www.yoursite.com/folder/ أمّا لتحويل جميع زيارات الموقع: Redirect 301 / http://newsite.com/ وتعدّ هذه الطريقة مناسبة جدًا في حال قمت بحجز نطاق جديد وترغب بتحويل زيارات الموقع القديم إلى الجديد شريطة أن تحافظ على مسارات الروابط النسبيّة كما هي، حيث يؤدي طلب الرابط من الشكل www.oldsite.com/helloworld إلى تحويل الزائر إلى www.newsite.com/helloworld . الخلاصة يفيد تحويل الزيارات من النمط 301 إن كنت تملك مجموعة من المنشورات القديمة والتي ترغب بأن تقوم بتحويل زياراتها إلى محتوى جديد للمحافظة على قوّة التقييم الخاص بها; كما يمكن استخدامه مع محرّكات البحث لإبلاغها بأنك تحافظ على محتوى جديد لموقعك. توفّر الإضافات المتاحة طرقًا سهلة لإنشاء التحويلات لموقعك، ولكن إن رغبت باستخدام الطريقة التقليدية فيمكنك اعتماد التحويل باستخدام ملف htaccess. ترجمة -وبتصرّف- للمقال Creating 301 Redirects With WordPress and How it Boosted Our Traffic لصاحبته Raelene Morey.
-
إنّ التخزين المؤقّت Caching للمحتوى بشكل ذكي هو واحد من أكثر الطرق فعاليّة لتحسين التجربة لزوّار موقعنا، إنّ التخزين المؤقّت Caching، أو تخزين المحتوى بشكل مؤقّت من الطلبات السّابقة، هو جزء من لُب استراتيجيّة توصيل المحتوى المُنفَّذة ضمن ميفاق HTTP protocol، تستطيع المُكوِّنات عبر مسار توصيل المحتوى أن تقوم بالتخزين المؤقّت للعناصر لتسريع الطلبات اللاحقة، والتي تكون خاضعة لسياسات التخزين المؤقّت المُصرَّح عنها بالنسبة للمحتوى. سنناقش في هذا الدّرس كيفيّة اختيار سياسات التخزين المؤقّت لنضمن أن يتمكّن التخزين المؤقّت في جميع أنحاء شبكة الإنترنت من معالجة محتوانا بشكل صحيح، وسنتحدّث عن استخدام ترويسات التخزين المؤقّت، وتوظيف الاستراتيجيات المختلفة للحصول على أفضل مزيج من الأداء والمرونة. ترويسات التخزين المؤقت Caching Headersتعتمد سياسة التخزين المؤقّت على عاملين مختلفين، كيان التخزين المؤقّت والذي يُقرِّر بنفسه أن يقوم بالتخزين المؤقّت للمحتوى المقبول أم لا، فيستطيع أن يُقرِّر أن يُخزِّن بشكل مؤقّت أقل مما هو مسموح له ولا أكثر من ذلك. يتم تحديد مُعظم سلوك التخزين المؤقّت عن طريق سياسة التخزين المؤقّت، والتي تُوضَع من قبل مالك المحتوى. تتمحور هذه السياسات بشكل أساسي حول استخدام ترويسات HTTP مُحدّدة. ومع تحديثات ميفاق HTTP protocol ظهرت بعض الترويسات المختلفة التي تُركِّز على التخزين المؤقّت مع مستويات مختلفة من التعقيد، ولكنّ الترويسات التالية هي التي لا نزال بحاجة إلى الانتباه لها: Expires: إنّ الترويسة Expires واضحة جدًّا، على الرغم من أنّها محدودة المجال، فتقوم بشكل أساسي بتعيين وقت في المستقبل تنتهي فيه صلاحيّة المحتوى، وعند هذه النقطة يجب على أي طلب لهذا المحتوى أن يعود إلى الخادوم الأصل، تُستخدَم هذه الترويسة أفضل ما يُمكن كاحتياط فقط.Cache-Control: وهي البديل الأكثر حداثة للترويسة Expires ومدعومة بشكل جيّد وتقوم بتطبيق تصميم أكثر مرونة، وهي مُفضّلة تقريبًا في كل الحالات على Expires، ولكن لن يضرّنا تعيين قيمة لهما معًا، سنناقش تفاصيل الخيارات التي بإمكاننا تعيينها مع Cache-Control لاحقًا.Etag: تُستخدَم الترويسة Etag في التحقّق من التخزين المؤقّت، حيث يُزوّدنا الخادوم الأصل بترويسة Etag فريدة لأجل العناصر حينما يقوم بتخديم المحتوى في البداية، فعندما يُريد التخزين المؤقّت التحقق من المحتوى الذي يملكه عند انتهاء الصلاحيّة يستطيع إرسال الترويسة Etag التي يملكها من أجل المحتوى إلى الخادوم الأصل والذي إمّا أن يُخبر التخزين المؤقّت بأنّه يملك نفس المحتوى أو يقوم بإرسال المحتوى الجديد (مع ترويسة Etag جديدة).Last-Modified: تُحدِّد هذه الترويسة المرّة الأخيرة التي تمّ فيها تعديل العنصر، ويُمكن استخدامها كجزء من استراتيجيّة التحقّق لضمان محتوى حديث.Content-Length: بالرغم من أنّها لا تُشارِك تحديدًا في التخزين المؤقّت فإنّه من الهام تعيين قيمة لهذه الترويسة عند تعريف سياسات التخزين المؤقّت، حيث ترفض بعض البرمجيّات التخزين المؤقّت للمحتوى إن لم تكن تعلم مُسبقًا حجم هذا المحتوى الذي تحتاج لحجز مساحة له.Vary: يستخدم التخزين المؤقّت بشكل نموذجي المُضيف host المطلوب والمسار إلى الموارد كمفتاح يُخزَّن بواسطته العنصر المطلوب، يُمكِن استخدام الترويسة Vary لنخبر التخزين المؤقّت أن ينتبه إلى ترويسة إضافيّة عندما يُقرّر إذا ما كان الطلب لنفس هذا العنصر، وهي أكثر ما تستخدم لإخبار التخزين الاحتياطي أن تستخدم الترويسة Accept-Encoding كمفتاح أيضًا، بحيث يعلم التخزين المؤقّت كيف يُفرِّق بين المحتوى المضغوط compressed وغير المضغوط.نظرة جانبية على الترويسة Varyتزوّدنا الترويسة Vary بالقدرة على تخزين إصدارات مختلفة من نفس المحتوى على حساب تمييع diluting المُدخلات في التخزين المؤقّت. ففي حالة Accept-Encoding يسمح لنا إعداد الترويسة Vary بالتمييز بشكل قاطع بين المحتوى المضغوط وغير المضغوط، حيث نحتاج لهذا لتخديم هذه العناصر بشكل صحيح للمتصفّحات التي لا تستطيع التعامل مع المحتوى المضغوط، وهو ضروري من أجل توفير سهولة الاستخدام الأساسيّة، ومن إحدى السمات التي تُخبرنا بأنّ الترويسة Accept-Encoding قد تكون مُرشّحًا جيّدًا من أجل الترويسة Vary هي أنّها تمتلك فقط قيمتان أو ثلاث قيم ممكنة. يبدو عنصر مثل User-Agent للوهلة الأولى طريقة جيّدة للتمييز بين متصفّحات الحواسيب ومتصفّحات الهواتف النقّالة لتخديم إصدارات مختلفة لموقعنا، ومع ذلك وبما أنّ السلاسل النصيّة لـ User-Agent ليست معياريّة فستكون النتيجة غالبًا عدّة إصدارات من نفس المحتوى في التخزينات المؤقّتة الوسيطة مع نسبة استخدام تخزين مؤقّت Cache hit ratio ضئيلة، ينبغي استخدام الترويسة Vary باعتدال، خاصّة إن لم نكن نملك القدرة على تقليل تكرار الطلبات في التخزينات المؤقّتة الوسيطة التي نتحكّم بها (والذي قد يكون ممكنًا إن استفدنا من شبكة توصيل محتوى content delivery network على سبيل المثال). كيف تؤثر أعلام الترويسة Cache-Control على التخزين المؤقتأشرنا سابقًا إلى كيفيّة استخدام الترويسة Cache-Control من أجل مواصفات سياسة التخزين المؤقّت الحديثة، يُمكن تعيين عدد من التعليمات المختلفة لهذه السياسة باستخدام هذه الترويسة، مع فصل التعليمات المتعدّدة بواسطة الفواصل. ومن بعض خيارات Cache-Control التي نستطيع استخدامها للنص على سياسة التخزين المؤقّت للمحتوى لدينا نجد: no-cache: تُحدِّد هذه التعليمة أنّه يجب التحقّق من أي محتوى مُخزَّن مؤقّتًا عند كل طلب قبل تخديمه إلى العميل، وتقوم فعليًّا بتحديد المحتوى بأنّه قديم stale فورًا، ولكن تتيح له استخدام تقنيات إعادة التحقّق لتجنّب إعادة تنزيل كامل العنصر مرّة أخرى.no-store: تشير هذه التعليمة إلى أنّه لا يُمكن التخزين المؤقّت للمحتوى بأي طريقة، وهي ملائمة لتعيينها إن كانت الاستجابة تمثّل بيانات حسّاسة.public: تقوم بتحديد المحتوى بأنّه عام ممّا يعني أنّه يمكن التخزين المؤقّت له من قبل المتصفّح أو من قبل أي تخزينات مؤقّتة وسيطة، يتم تحديد الاستجابات بالنسبة للطلبات التي تستخدم استيثاق HTTP بأنّها خاصّة private افتراضيًّا، وتستطيع هذه الترويسة تجاوز ذلك الإعداد.private: تقوم بتحديد المحتوى بأنّه خاص private، والذي يُمكن تخزينه من قبل متصفّح المستخدم ويُمنَع تخزينه بشكل مؤقّت من قبل أي أطراف وسيطة، تستخدم هذه التعليمة غالبًا للبيانات الخاصّة بالمستخدم.max-age: يضبط هذا الإعداد الفترة العظمى التي يُمكن خلالها تخزين المحتوى بشكل مؤقّت قبل أن تجب إعادة التحقّق منه أو إعادة تحميله من الخادوم الأصل، وهو يستبدل الترويسة Expires من أجل المتصفّحات الحديثة وهو الأساس لتحديد حداثة جزء من المحتوى، تُحدَّد قيمة هذا الخيار بالثواني ووقت الحداثة الأعظمي المقبول هو سنة واحدة (31536000 ثانية).s-maxage: وهو مشابه كثيرًا للإعداد max-age بأنّه يشير للفترة الزمنيّة التي يُمكِن خلالها التخزين المؤقّت للمحتوى، ويكمن الفرق في أنّ هذا الخيار يُطبَّق فقط على التخزينات المؤقّتة الوسيطة، يسمح جمعه مع الخيار السابق ببناء سياسة أكثر مرونة.must-revalidate: يُشير هذا الخيار إلى أنّه يجب إطاعة معلومات الحداثة المنصوص عليها من خلال max-age، s-maxage، أو الترويسة Expires بشكل صارم، فلا يُمكِن تخديم المحتوى القديم تحت أي ظروف، ويمنع هذا استخدام المحتوى المُخزَّن مؤقّتًا في حالة انقطاعات الشبكة والسيناريوهات المشابهة لها.proxy-revalidate: يقوم هذا الإعداد بنفس ما يقوم به الإعداد السابق ولكن ينطبق فقط على وسطاء التخزين المؤقّت البيني intermediary proxies، ويبقى متصفّح المستخدم في هذه الحالة قادرًا على تخديم المحتوى القديم في حالة انقطاعات الشبكة، ولكن لا يُمكن استخدام التخزينات المؤقّتة الوسيطة لهذا الغرض.no-transform: يمنع هذا الخيار التخزينات المؤقّتة من تعديل المحتوى الذي تلقّته لأسباب تتعلّق بالأداء تحت أي ظروف، يعني هذا على سبيل المثال أنّ التخزين المؤقّت غير قادر على إرسال إصدارات مضغوطة من محتوى لم يتلقّاه بشكل مضغوط وغير مسموح له بهذا أصلًا.نستطيع الجمع بين كل ما سبق بطرق مختلفة للحصول على سلوك متعدّد للتخزين المؤقّت، بعض القيم التبادليّة هي: no-cache ،no-store، وسلوك التخزين المؤقّت الطبيعي الذي نشير إليه بغياب أحدهماpublic و privateيحل الخيار no-store محل no-cache إن كان كلاهما موجودًا، ومن أجل الاستجابة على الطلبات التي لا تتعلق بالاستيثاق يتم تطبيق الخيار public، ومن أجل الاستجابة على الطلبات التي تحتوي استيثاق يتم تطبيق الخيار private، ويُمكِن تجاوزها بتضمين الخيار المعاكس في الترويسة Cache-Control. تطوير سياسة تخزين مؤقتيُمكِن في العالم المثالي التخزين المؤقّت لكل شيء بقوّة والتواصل مع الخواديم فقط للتحقّق من المحتوى بين حين وآخر، ولكن على الرغم من ذلك لا يحدث هذا في الممارسة العمليّة، لذا ينبغي أن نحاول تعيين سياسات تخزين مؤقّت عاقلة تطمح إلى الموازنة بين تنفيذ تخزين مؤقّت طويل المدى والاستجابة لاحتياجات الموقع المتغيّر. مشاكل شائعةهنالك العديد من الحالات التي لا يُمكِن أو لا ينبغي فيها تنفيذ التخزين المؤقّت نظرًا لكيفيّة إنتاج هذا المحتوى (توليده بشكل مُتغيّر بحسب المستخدم) أو طبيعة هذا المحتوى (معلومات بنكيّة حساسة على سبيل المثال)، ومن المشاكل الأخرى التي تُواجِه العديد من مديري النّظم عند إعداد التخزين المؤقّت هي الحالة التي تكون فيها إصدارات أقدم ومنتشرة من محتوانا ليست قديمة بعد على الرغم من نشر إصدارات أجدد منها. تتم مصادفة هاتين المشكلتين بشكل متكرّر وتمتلكان أثرًا هامًّا على أداء التخزين المؤقّت ودقّة المحتوى الذي نقوم بتخديمه، ومع ذلك نستطيع الحد من هذه المشاكل عن طريق تطوير سياسات تخزين مؤقّت تتوقّع هذه المشاكل. توصيات عامةعلى الرغم من أنّ الحالة هي التي تُملي علينا استراتيجيّة التخزين المؤقّت المُلائِمة، تستطيع التوصيات التالية إرشادنا نحو بعض القرارات المنطقيّة. هناك بعض الخطوات التي نستطيع اتخاذها لزيادة نسبة استخدام التخزين المؤقّت Cache hit ratio قبل الانتقال لاستخدام ترويسات محدّدة، ومن بعض الأفكار نجد: إنشاء أدلّة directories مُخصّصة للصور، ملفات css، والمحتوى المُشترَك: يسمح وضع المحتوى في أدلّة مُخصّصة بالرجوع بسهولة إليها من أي صفحة على موقعنا.استخدام نفس الرابط URL للإشارة إلى نفس العناصر: بما أنّ التخزينات المؤقّتة تستخدم مفتاح مُكوَّن من المُضيف والمسار للمحتوى المطلوب فيجب أن نتأكّد من أن نشير إلى محتوانا بنفس الطريقة على كافّة صفحات موقعنا، وتجعل النصيحة السابقة من هذا أسهل.استخدام الأشكال الشبحية sprites لصور CSS حيثما أمكن ذلك: تُقلِّل الأشكال الشبحية لصور CSS من أجل عناصر مثل الأيقونات والتصفّح navigation من عدد الجولات المطلوبة لتصيير render موقعنا وتسمح لنا بالتخزين المؤقّت لذلك الشكل الشبحي لوقت طويل.استضافة الـ scripts والموارد الخارجيّة بشكل محلّي بقدر الإمكان: إن كُنّا نستخدم scripts خاصة بلغة javascript وموارد خارجيّة أخرى فيجب أن نأخذ بعين الاعتبار استضافة هذه الموارد على خواديمنا الخاصّة، نلاحظ أنّه يجب علينا الانتباه لأي تحديثات جديدة لهذه الموارد لكي نقوم بتحديث نسختنا المحليّة منها.وضع بصمة خاصّة لعناصر التخزين المؤقّت: من المناسب أن نقوم بوضع بصمة خاصّة بالنسبة للمحتوى الثابت مثل ملفّات CSS وJavascript، ويعني هذا إضافة مُعرِّف فريد unique identifier إلى اسم الملف (عادةً تلبيد hash للملف) بحيث إن تمّ تعديل المورد يُمكِن طلب الاسم الجديد للمورد مما يجعل الطلبات تجتاز التخزين المؤقّت بشكل صحيح، توجد العديد من الأدوات التي تساعد في إنشاء بصمات وتعديل المراجع إليها في ملفّات HTML.ومن ناحية اختيار الترويسات الصحيحة للعناصر المختلفة، فيمكن اعتبار ما يلي كمرجع عام: السماح لكافّة التخزينات المؤقتة بتخزين الممتلكات العامّة general assets: ينبغي أن يتم التخزين المؤقّت للمحتوى الثابت وغير المتعلّق بالمستخدم في كافّة النقاط على سلسلة التوصيل، ممّا يسمح للتخزينات المؤقّتة الوسيطة بالاستجابة بالمحتوى للعديد من المستخدمين.السماح للمتصفّحات بالتخزين المؤقّت للممتلكات الخاصّة بالمستخدم: من المقبول والمفيد بالنسبة للمحتوى الخاص بالمستخدم أن نسمح بالتخزين المؤقّت داخل متصفّح المستخدم، وبينما يكون من غير الملائم فعل هذا على التخزينات المؤقّتة الوسيطة يسمح التخزين المؤقّت في المتصفّح بالاستعادة الآنيّة للمحتوى من أجل المستخدمين خلال الزيارات اللاحقة.عمل استثناءات للمحتوى الأساسي الحساس بالنسبة للوقت: إن كنّا نملك محتوى حساس بالنسبة للوقت نقوم بعمل استثناء للقواعد السابقة بحيث لا يتم تخديم المحتوى القديم في الحالات الحرجة، على سبيل المثال إن كان موقعنا يمتلك عربة تسوّق shopping cart فينبغي أن تعكس العناصر الموجودة فيها فورًا، واعتمادًا على طبيعة المحتوى يُمكِن تعيين الخيار no-cache أو no-store في الترويسة Cache-Control لتحقيق هذا.توفير خيارات للتحقّق دومًا: تسمح لنا خيارات التحقّق بتحديث المحتوى القديم بدون أن يتوجّب علينا تنزيل كامل الموارد مرّة أخرى، يسمح تعيين الترويسات Etag وLast-Modified للتخزينات المؤقّتة بأن تتحقّق من محتواها وتعيد تخديمه إن لم يتم تعديله على الخادوم الأصل، مما يؤدي إلى إنقاص الحمل load.تعيين أوقات حداثة freshness times طويلة للمحتوى الداعم: من أجل الاستفادة من التخزين المؤقّت بشكل فعّال فإنّ العناصر المطلوبة كمحتوى داعم لملء الطلب ينبغي عادة أن تملك وقت حداثة طويل، وهو مناسب بشكل عام من أجل لعناصر مثل الصور وملفّات CSS والتي يتم سحبها لتصيير صفحة HTML المطلوبة من قبل المستخدم، يسمح تعيين وقت حداثة طويل مع جمعه بوضع بصمة بأن تقوم التخزينات المؤقّتة بتخزين هذه الموارد لفترات طويلة، فإن تمّ تغيير الممتلكات فستقوم البصمة المُعدّلة بإبطال العنصر المُخزَّن مؤقّتًا وستقوم بتحفيز تنزيل المحتوى الجديد، وحتى ذلك الحين يُمكِن أن يتم تخزين العناصر الداعمة بشكل مؤقّت لوقت طويل في المستقبل.تعيين أوقات حداثة freshness times قصيرة للمحتوى الأب: يجب أن يملك عنصر الاحتواء وقت حداثة قصير نسبيًّا أو حتى لا يتم تخزينه بشكل مؤقّت نهائيًّا وذلك من أجل تطبيق المخطّط السّابق، وهو بشكل نموذجي صفحة HTML التي تستدعي العناصر المساعدة الأخرى، فيتم تنزيل ملفّات HTML بشكل متكرّر ممّا يسمح لها بالاستجابة للتغيرات بسرعة، ومن ثمّ بعدها يُمكِن التخزين المؤقّت للمحتوى الداعم بشدّة.المفتاح الأساسي لتحقيق هذا هو خلق موازنة تُفضِّل التخزين المؤقّت بشدّة حيثما أمكن مع ترك فُرَص لإبطال المُدخلات مُستقبلًا عندما يتم حدوث تغييرات، من المرجّح أن يملك موقعنا تركيبة من: عناصر مُخزَّنة مؤقّتًا بشدّةعناصر مُخزّنة مؤقّتًا مع وقت حداثة قصير والقدرة على إعادة التحقّقعناصر لا ينبغي تخزينها بشكل مؤقّت إطلاقًاوالهدف هو نقل المحتوى إلى الفئة الأولى إن أمكن مع الحفاظ على مستوى مقبول من الدقة. الخاتمةإنّ أخذ الوقت للتأكّد من أنّ موقعنا يملك سياسات تخزين مؤقّت مناسبة في مكانها له تأثير هام عليه، حيث يسمح التخزين المؤقّت بالتقليل من نفقات عرض النطاق bandwidth المترافقة مع تخديم نفس المحتوى بشكل متكرّر، سيكون خادومنا أيضًا قادر على التعامل مع كميّة كبيرة من حركة مرور البيانات traffic باستخدام نفس العتاد، وربّما الأهم من كل ذلك أنّ العملاء سيملكون تجربة أسرع على موقعنا ممّا يقود بهم إلى العودة إليه بشكل متكرّر، وفي حين أنّ التخزين المؤقّت بشكل فعّال ليس حلًّا سحريًّا فإنّ إعداد سياسات تخزين مؤقّت مناسبة يعطينا مكاسب ملموسة بجهد قليل. ترجمة -وبتصرّف- لـ Web Caching Basics: Terminology, HTTP Headers, and Caching Strategies لصاحبه Justin Ellingwood.
-
- caching
- التخزين المؤقت
-
(و 3 أكثر)
موسوم في:
-
عند الاتصال بخادوم ويب أو تطبيق، يتم الردّ على كلّ طلب HTTP يتمّ استقباله من طرف الخادوم برمز حالة HTTP أو “HTTP status codes”. رموز حالة HTTP هي عبارة عن رموز مكوّنة من 3 أرقام يتم تصنيفها إلى 5 أصناف مختلفة. يمكن أن يتمّ التعرّف على صنف رمز الحالة بسرعة عبر الرقم الأوّل منه: 1xx: معلومة 2xx: نجاح 3xx: إعادة توجيه 4xx: خطأ من طرف جهاز العميل 5xx: خطأ من طرف الخادوميركّز هذا الدرس على استكشاف أبرز رموز أخطاء HTTP التي قد تصادفك مثل 4xx و5xx وإصلاحها. من منظور مدير النظام، هناك العديد من الحالات التي قد تجعل خادوم الويب يجيب طلبًا معيّنًا برمز خطأ معيّن، سنقوم بتغطية أكثر الأسباب الشائعة التي تؤدي إلى ذلك بالإضافة إلى حلولها. لمحة عامة عن أخطاء العميل والخادومأخطاء العميل، أو رموز حالة HTTP من 400 إلى 499، هي نتيجة لطلبات HTTP تمّ إرسالها بواسطة جهاز مستخدم (مثل متصفح ويب أو أيّ عميل HTTP آخر), صحيح أنّ هذا النوع من الأخطاء مرتبط بالعميل، إلّا أنّه سيكون من المفيد معرفة رمز الخطأ الذي يصادف المستخدم للتحقق مما إذا كان يمكن إصلاح المشكلة من إعدادات الخادوم. يتم إرجاع أخطاء الخادوم أو بالأحرى رموز حالة HTTP من 500 إلى 599 بواسطة خادوم الويب عندما يكتشف حصول مشكلة، وإلّا فإنّه لن يكون قادرًا على معالجة الطلب. نصائح عامة عن اكتشاف الأخطاء وإصلاحهاعند استخدام متصفّح ويب لاختبار خادوم ويب، قم بتحديث المتصفّح بعد تطبيق التغييرات على الخادوم.تحقق من سجلات الخادوم للمزيد من التفاصيل عن كيفية قيام الخادوم بمعالجة الطلبات. كمثال، تُنتِج خواديم الويب مثل Apache وNginx ملفّين اثنين يدعيان access.log وerror.log يمكن أن يتم فحصهما للحصول على المعلومات منهما.تذكّر أنّ تعريفات رموز حالة HTTP هي جزء من معيار مُضمَّن من قبل التطبيق الذي يخدم الطلبات. هذا يعني أنّ رمز الحالة الذي يتم إرجاعه إليك يعتمد على كيفية معالجة برنامج الخادوم لخطأ معيّن. سيفيدك هذا الدرس عمومًا لتوجيهك في المسار الصحيح بخصوص ذلك.الآن وبعد أن امتلكت فهمًا جيدًا لرموز حالة HTTP، سنلقي نظرةً على الأخطاء الشائعة التي قد تصافدك. 400 Bad Requestرمز الحالة 400، أو خطأ Bad Request، يعني أنّ طلب الـHTTP الذي تمّ إرساله إلى الخادوم كان يحوي دوالًا ومُعامِلات غير صحيحة. إليك بعض الأمثلة التي قد يطرأ فيها خطأ Bad Request والذي رقمه 400: كعكة المستخدم (Cookie) المرتبطة بالموقع تالفة، مسح خبيئة المتصفّح والكعكات قد يحلّ هذه المشكلة. طلب تالف بسبب متصفّح ويب سيء وقديم مثلًا. طلب تالف بسبب خطأٍ بشري مثل عند تشكيل طلبات HTTP بشكلٍ يدوي (مثل استعمال curl بطريقة غير صحيحة).401 Unauthorizedرمز الحالة 401، أو خطأ Unauthorized أو عدم التصريح يعني أنّ المستخدم يحاول الوصول إلى صفحة أو مادّة غير مخوّل له بالوصول إليها أو لم يتم السماح له بذلك بشكلٍ صحيح. يعني هذا أنّه يجب على المستخدم توفير بيانات الدخول ليتمكّن من رؤية البيانات والموارد المحمية. كمثال، إذا حاول مستخدم الوصول إلى صفحة محمية باستيثاق HTTP، كما في درسنا كيفية إعداد استيثاق http مع nginx على 14.04 ubuntu، ففي هذه الحالة، سيتلقّى المستخدم رمز الحالة "401" إلى أن يقوم بتوفير اسم مستخدم وكلمة مرور (تلك الموجودة في ملفّ htpasswd.) لخادوم الويب. 403 Forbiddenرمز الحالة 403، أو خطأ Forbidden أو "محظور"، يعني أنّ المستخدم قام بطلبٍ خاطئ إلّا أنّ الخادوم يرفض تنفيذه على كلّ حال بسبب عدم توفّر الصلاحيات الكافية للوصول إلى الصفحة المطلوبة. إذا كنت تواجه خطأ 403 بشكلٍ غير متوقّع، فهناك بضع أسباب يمكن أن نشرحها هنا. صلاحيات الملفاتتطرأ أخطاء 403 عادةً عندما يكون المستخدم الذي يشغّل عملية خادوم الويب لا يمتلك الصلاحيات الكافية لقراءة الملفّ الذي تمّ طلبه. لإعطاء مثال عن الكشف عن هذا الخطأ وإصلاحه، افترض حصول الوضع التالي: يحاول المستخدم الوصول إلى ملفّ الفهرس الخاصّ بالخادوم من http://example.com/index.htmlعملية تشغيل خادوم الويب مملوكة للمستخدم www-dataيوجد ملفّ الفهرس على الخادوم بالمسار usr/share/nginx/html/index.html/إذا كان المستخدم يحصل على خطأ 403، فتأكّد أنّ المستخدم www-data يمتلك الصلاحيات الكافية لقراءة ذلك الملفّ. يعني هذا عادةً أنّه يجب ضبط صلاحيات "الآخرين" أو الـ"Others" إلى السماح بالقراءة ليتم حلّ المشكلة، هناك عدّة طرق لتنفيذ هذا، ولكنّ هذا الأمر سيعمل في هذه الحالة: sudo chmod o=r /usr/share/nginx/html/index.html htaccess.سببٌ آخر قد يكون وراء خطأ 403 وغالبًا ما يحصل عن غير قصد، هو الاستخدام الخاطئ لملفّ htaccess.، يمكن أن يتمّ استخدام ملفّ htaccess. لمنع الوصول إلى صفحاتٍ أو موارد معيّنة من قبل عناوين IP محددة أو نطاقات، استخدام هذا الملفّ بشكلٍ غير صحيح قد يكون المشكلة مثلًا. إذا كان المستخدم يحصل على خطأ 403 بشكلٍ غير متوقع، فتأكّد من أنّ ملفّ الـhtaccess. الخاصّ بك ليس المسؤول عن ذلك. ملف الفهرس غير موجودإذا كان المستخدم يحاول الوصول إلى مجلّد لا يمتلك بداخله ملفّ فهرس افتراضيًا، ولم يكن خيار السماح بسرد محتويات المجلّدات مفعّلًا، فإنّ خادوم الويب سيُرجع خطأ حظر 403. كمثال، إذا كان المستخدم يحاول الوصول إلى http://example.com/emptydir ولم يكن هناك ملفّ فهرس في المجلّد emptydir على الخادوم، فإنّه سيتم إرجاع رمز حالة 403. إذا كنت تريد تفعيل خيار سرد محتويات المجلّدات في حال عدم وجود ملفّ فهرس بداخلها، فيمكنك القيام بذلك من إعدادات خادوم الويب الخاصّ بك. 404 Not Foundرمز الحالة 404، أو خطأ Not Found، يعني أنّ المستخدم كان قادرًا على التواصل مع الخادوم إلّا أنّه لم يتمكن من إيجاد الملفّ المطلوب أو الصفحة المنشودة. يمكن أن تطرأ أخطاء 404 في الكثير من الحالات. إذا كان المستخدم يتلقّى خطأ 404 بشكلٍ غير متوقّع، فإليك بعض الأسئلة التي يجب أن تسألها للمساعدة في تفحّص المشكلة وإصلاحها: هل الرابط الذي وجّهَ المستخدم إلى خادمك يحتوي على خطأ بالكتابة؟ هل قام المستخدم بكتابة العنوان الخاطئ؟ هل الملفّ موجود في المسار الحالي للخادوم؟ وهل تمّ نقله أو نقل الصفحة المطلوبة إلى مكانٍ آخر أو حذفها من الخادوم؟ هل تمّ ضبط إعدادات الخادوم إلى مسار الجذر الرئيسي المطلوب؟ هل المستخدم الذي يملك العملية المُشغّلة لخادوم الويب يمتلك الصلاحيات اللازمة للوصول إلى المسار الذي يحوي الملفّ بداخله؟ (تلميح: تتطلب المجلّدات صلاحيات القراءة والتنفيذ لتستطيع الوصول إليها). هل يتمّ الوصول إلى الملفّ أو الصفحة عبر وصلة رمزية (symbolic link)؟ إذا كان الأمر كذلك، فتحقق من أن خادوم الويب مضبوط ليتبع الوصلات الرمزية.500 Internal Server Errorرمز الحالة 500، أو 500 Internal Server Error يعني أنّ الخادوم غير قادر على معالجة الطلب لسببٍ مجهول. أحيانًا سيظهر هذا الرمز عندما تكون أخطاء 5xx أكثر عرضةً لتكون هي سبب المشكلة. عادةً ما يكون أبرز سببٍ مسبب لهذا الخطأ هو وجود مشكلة في إعدادات الخادوم (مثل ملفّ htaccess. تالف) أو حزم ناقصة (مثل محاولة تنفيذ سكربت PHP دون وجود حزمة PHP مثبّتة بشكلٍ صحيح على الخادوم). 502 Bad Gatewayرمز الحالة 502، أو 502 Bad Gateway، يعني أنّ الخادوم هو عبارة عن خادوم بوّابة أو وسيط (proxy)، وأنّه لا يتلقّى ردًا صحيحًا من خواديم الواجهة الخلفية (backend servers) التي يجب أن تقوم بمعالجة الطلب. إذا كان الخادوم المطلوب هو عبارة عن خادوم وسيط عكسي (reverse proxy server)، مثل موازِن للحِمل، فإليك بعض الأمور التي يمكنك التحقق منها: أنّ خواديم الواجهة الخلفية (حيث يتم توجيه طلبات HTTP) تعمل بشكلٍ صحيح. أنّ الخادوم العكسي مضبوط بشكلٍ صحيح، مع تحديد الخواديم الصحيحة للواجهة الخلفية. أنّ اتصال الشبكة بين خواديم الواجهة الخلفية وبين خادوم الوسيط العكسي يعمل بشكلٍ جيّد. إذا كان بإمكان الخواديم أن تتواصل عن طريق منافذ أخرى، فتأكّد أنّ الجدار الناري يسمح بمرور التدفّق (Traffic) بينها. إذا كان تطبيق الويب الخاصّ بك مضبوطًا للاستماع إلى socket، فتأكّد أنّ الـsocket موجودة في المسار الحالي وأنّها تمتلك الصلاحيات الكافية.503 Service Unavailableرمز الحالة 503، أو خطأ Service Unavailable، يعني أنّ الخادوم قد تحمّل فوق طاقته أو أنّه تحت الصيانة، يوحي هذا الخطأ أنّ الخدمة يجب أن تعود إلى العمل في وقتٍ ما من الزمن. إذا لم يكن الخادوم تحت الصيانة، يمكن لهذا أن يشير إلى أنّ الخادوم لا يملك الموارد الكافية من المعالج والذاكرة العشوائية لمعالجة جميع الطلبات الواردة، أو أنّ خادوم الويب يحتاج إلى أنّ يتم إعداده ليسمح بالمزيد من المستخدمين والعمليات. 504 Gateway Timeoutرمز الحالة 504، أو خطأ Gateway Timeout، يعني أنّ الخادوم هو عبارة عن خادوم بوّابة أو خادوم وسيط (proxy)، وأنّه لا يتلقّى ردًا من خواديم الواجهة الخلفية في فترة الوقت المسموح بها. يمكن لهذا الخطأ عادةً أن يحصل في الحالات التالية: اتصال الشبكة بين الخواديم ضعيف. خواديم الواجهة الخلفية التي تقوم بتنفيذ الطلب بطيئة جدًا، بسبب الأداء الضعيف. فترة المهلة لخادوم البوابة أو الوسيط قصيرة جدًا.الخاتمةيجب أن تكون قد صرتَ الآن مُدركًا لأبرز رموز أخطاء HTTP وأبرز الحلول المتوفّرة لهذه الأخطاء، يجب أن تمتلك أساسياتٍ جيّدة لاكتشاف الأخطاء وإصلاحها على خواديم الويب الخاصّة بك أو تطبيقاتك. ترجمة -وبتصرف- للمقال How To Troubleshoot Common HTTP Error Codes لصاحبه Mitchell Anicas.
-
يُعد إنجن إكس NginX خادوم ويب Web Server ذو أداء عالي وهو مسؤول عن معالجة العبء الواقع على بعض أكبر المواقع الإلكترونية Web Sites على الإنترنت Internet. وهو جيد خصوصًا في معالجة الكثير من الاتصالات المتزامنة concurrent ويتفوق في تخديم المحتوى الثابت static content. مع أنّ الكثير من المستخدمين يدركون قدرات Nginx، إلا أنه عادةً ما يحتار المستخدمين الجدد ببعض المصطلحات التي يجدونها في ملف إعدادات configuration خادوم Nginx. سنركّز في هذا الدليل على شرح البنية الأساسية لملف إعدادات Nginx بالإضافة لاستعراض بعض المبادئ guidelines في كيفية تصميم ملف الإعدادات. فهم سياقات الإعدادات في Nginxسيُغطي هذا الدليل البنية الأساسية الموجودة في ملف الإعدادات الرئيسي Nginx. قد يختلف مكان هذا الملف وفقًا للطريقة التي اتبعتها عند تثبيت البرمجية Software على الخادوم. إلا أنَّك سوف تجده في العديد من التوزيعات distributions على المسار التالي: /etc/nginx/nginx.confإنّ لم يكن موجودًا فقد تجده على المسار: /usr/local/nginx/conf/nginx.confأو المسار: /usr/local/etc/nginx/nginx.confإنّ أحد أول الأمور التي ينبغي عليك ملاحظتها عندما تنظر إلى ملف الإعدادات الرئيسي هي أنَّه منظَّم في بنيةٍ من ثلاثة أقسام تعرّف بداية ونهاية كلٍ منها بالقوسين } و {. تسمى الأقسام المعرّفة باستخدام القوسين سياقات contexts وفقًا للغة Nginx، وذلك لأنها تحوي على إعداداتٍ مُفَصَّلة وموزعة بين تلك الأقسام وفقًا للمجال الذي يُعنى به كل قسم. يقدم هذا التقسيم بشكل أساسي بنيةً منظّمة وفق بعض الشروط المنطقية التي تقرّر فيما إن كان ينبغي تطبيق الإعدادات التي يحويها القسم أو لا. وباعتبار أنه يمكن للسياقات أن تتداخل فيما بينها فإنNginx يقدم مستوًا من وراثة التعليمات directive inheritance. كقاعدةٍ عامة، إن كانت التعليمة صالحةً في عدّة مجالات scopes متدخلة فإنّ التصريح عنها في سياق أعلى boarder context سيُمرّر لأي سياقٍ أدنى (سياق ابن child context) كقيم افتراضية. يمكن للسياقات الأدنى أن يعيد تعريف override تلك القيم لاحقًا. جدير بالذكر أنّ عملية إعادة التعريف إلى أي مصفوفة-نوع array-type سينتج عنها استبدال القيم السابقة وليس إضافة append القيم الجديدة لها. يمكن أن تستخدم التعليمات Directives ضمن السياقات المصمّمة لها فقط، إذ أنّ Nginx سيُصدر خطأ عند قراءته لملف إعدادات يحوي على تعليمات مصرّح عنها في السياق الخاطئ. يحوي توثيق Nginx على معلومات حول كلّ تعليمة والسياقات التي تكون صالحة ضمنها لذلك يُعد مرجع رائع إن لم تكن متأكدًا من معلوماتك. سنناقش فيما يلي أكثر السياقات شيوعًا والتي قد تصادفها عند استخدامك Nginx. السياقات الأساسيةأول مجموعة سياقات سنشرحها هي السياقات الأساسية core contexts التي يستخدمها Nginx لإنشاء شجرة هرمية hierarchical tree وتوزيع الإعدادات - بحسب مهمّتها - في كتل Blocks منفصلة. تشكّل تلك السياقات البنية الأساسية لإعدادات Nginx. السياق الأساسيإن أكثر سياق عام هو السياق الأساسي Main Context، والذي يدعى أيضًا بالسياق العام Global Context. إذ أنه السياق الوحيد غير المحتوى ضمن كتل السياق القياسية والتي تبدو كما يلي: # السياق الأساسي يوجد هنا، السياقات الأخرى تكون خارجا . . . context { . . . }يمكن القول عن أيّة تعليمة موجودة خارج كل تلك الكتل بأنها تقع في السياق الأساسي. ضع في الحسبان أنه إن كانت إعدادات Nginx مضبوطةً على شكل وحدات modular فستحوي بعض الملفات على تعليماتٍ instructions تبدو وكأنها تقع خارج أقواس السياق إلا أنها ستُضمّن داخله عندما يتم دمج الإعدادات معًا. يمثّل السياق الأساسي أوسع بيئة حاضنة لإعدادات Nginx، وهي مستخدمة لضبط التفاصيل التي تؤثر على كامل التطبيق application في مستوى أساسي. وفي الوقت الذي تؤثر فيه التعليمات الموجودة في هذا القسم على السياقات الأدنى فإن العديد من تلك التعليمات لا توّرث، إذ أنه من غير الممكن إعادة تعريفها في مستوياتٍ أدنى. إن بعض التفاصيل الشائعة والتي تُهيّئ في السياق الرئيسي هي المستخدم user والمجموعة group التي ستُشغّل العمليات العاملة worker processes باسمهما، بالإضافة لعدد العمليات العاملة والملف الذي سيحتفظ بمعرّف العملية الرئيسية PID. يمكن أيضًا أن يُضبط ملف الأخطاء الافتراضي لكامل التطبيق ضمن هذا المستوى (كما يمكن أن يُعاد تعريف الملف ضمن سياقات مخصّصة أكثر). سياق الأحداثإنَّ سياق الأحداث Events Context يقع ضمن السياق الأساسي. وهو يستخدم لضبط الخيارات العامة التي تؤثّر على كيفية معالجة Nginx للاتصالات في مستوى عام. يمكن أن يُعرّف سياق أحداث واحد فقط ضمن إعدادات Nginx. سوف يبدو هذا السياق ضمن ملف الإعدادات كما يلي، خارج أقواس أي سياقٍ آخر: # السياق الأساسي events { # سياق الأحداث . . . }يستخدم Nginx وحدة معالجة اتصال مقادة بالأحداث event-based connection processing model لذلك فإن التعليمات المعرّفة داخل هذا السياق تحدّد كيف ينبغي على العمليات العاملة worker processes معالجة الاتصالات connections. تُستخدم التعليمات الموجودة هنا بشكل أساسي إما في اختيار الطريقة المستخدمة في معالجة الاتصال أو لتغيير كيفية تحقيق implement تلك الطرق methods. عادةً ما تُختار طريقة معالجة الاتصال تلقائيًا بالاعتماد على أكثر الخيارات - التي توفّرها منصّة العمل platform - فاعليةً. بالنسبة لأنظمة لينكس Linux، فعادةً ما تكون طريقة epoll هي الخيار الأفضل. هنالك عناصر أخرى يمكن ضبطها، كعدد الاتصالات التي يمكن لكل عملية عاملة أن تعالجها، وفيما إن كان على العملية أن تأخذ اتصالًا تلو الآخر أو أن تأخذ كل الاتصالات المنتظرة بعد أن يتم إعلامها بوجودها. وأيضًا فيما إن كان على العمليات العاملة أن تتناوب في الرد على الأحداث. سياق HTTPعند إعداد Nginx كخادوم ويب أو خادوم وكيل معكوس reverse proxy، فسيحتفظ سياق HTTP بغالبية الإعدادات. سيحتوي السياق على كل التعليمات والسياقات الأخرى الضرورية لتعريف كيفية معالجة البرنامج لاتصالات HTTP أو HTTPS. يُعد سياق HTTP أخًا لسياق الأحداث - أي أنهما يقعان في نفس المستوى - إذ أن كلاهما يُعد ابنًا للسياق الرئيسي، لذلك ينبغي أن يُدرجا جنبًا إلى جنب بدلًا من أن يتداخلا: # السياق الأساسي events { # سياق الأحداث . . . } http { # سياق HTPP . . . }فيما تختص السياقات الدنيا lower contexts في كيفية معالجات الطلبات، فإن التعليمات في هذا المستوى تتحكم بالقيم الافتراضية لكل الخواديم الافتراضية المعرّفة داخله. هنالك عدد كبير من التعليمات القابلة للضبط configurable ضمن هذا السياق والسياقات المحتواة ضمنه، يعتمد ذلك على طريقة التوريث inheritance التي ترغب أن يتم العمل وفقها. فيما يلي مجموعة من التعليمات التي يمكن أن تصادفها خلال ضبط إعدادات Nginx: تعليمات تتحكم بالمواقع الافتراضية لسجلات الوصول والأخطاء مثل (access_log و error_log).تعليمات تضبط عمليات القراءة والكتابة I/O غير المتزامنة asynchronous من وإلى الملفات مثل (aio و sendfile و directio)،تعليمات تضبط حالات الخادوم عندما تحدث الأخطاء مثل (error_page).تعليمات تضبط عملية الضغط compression مثل (gzip و gzip_disable).عمليات تحسّن fine-tune إعدادات اتصال TCP الحي TCP keep alive مثل (keepalive_disable و keepalive_requests و keepalive_timeout).القواعد rules التي يتبعها Nginx عندما يحاول تحسين optimize الحزم packets واستدعاءات النظام system calls مثل (sendfile و tcp_nodelay و tcp_nopush).تعليمات تضبط جذر المستندات document root وفهرس الملفات index files على مستوى التطبيق application-level مثل (root و index).تعليمات تهيّئ العديد من جداول المقابلة hash tables المستخدمة لتخزين أتماط مختلفة من البيانات مثل (*_hash_bucket_size و *_hash_max_size المستخدمتين مع server_names بالإضافة لـ types و variables).سياق الخادوميُعرّف سياق الخادوم Server Context ضمن سياق HTTP، ويُعد ذلك أوّل مثال لنا عن السياقات المتداخلة. كما أنّه أوّل سياق مرّ معنا يمكن تعريفه عدّة مرات. قد يبدو التنسيق العام لسياق الخادوم مشابهًا لما يأتي، تذكّر أنّ هذا السياق سيقع ضمن سياق HTTP: # السياق الأساسي http: { # سياق HTTP server { # سياق خادوم أول } server { # سياق خادوم ثاني } }يعود سبب السماح بوجود أكثر من تعريف لسياق الخادوم إلى أن كل غرض instance يعرّف خادومًا افتراضيًا لمعالجة طلبات المستخدم client. بإمكانك تعريف كتل الخادوم server blocks بقدر حاجتك، إذ أنّه بإمكان كل منها أن يعالج مجموعة فرعية محدّدة من الاتصالات. وبسبب امكانية وترجيح وجود عدة كتل خواديم، فإن هذا أوّل نوع من السياقات يحتّم على Nginx استخدام خوارزمية algorithm انتقاء لاتخاذ القرارات. إنّ كلّ طلب مستخدم سيُعالَج وفقًا للإعدادات المعرّفة في سياق خادوم وحيد، لذلك فإن على Nginx أن يقرّر أي سياق خادوم هو الأنسب وفقًا لتفاصيل الطلب. إنّ التعليمات التي تقرّر فيما إذا كانت كتلة الخادوم ستُستخدم أم لا هي: تعليمة التنصت listen: تُصمَّم كتلة الخادوم للرد على الطلبات الواردة من مصدر معرّف بثنائية عنوان الإنترنت IP / المنفذ Port. فإن ورد طلب request من مستخدم يطابق ذلك المصدر فمن المحتمل أن يتم اختيار تلك الكتلة لمعالجة الاتصال.تعليمة اسم الخادم server_name: هذه التعليمة هي المكوّن الآخر المستخدم في اختيار كتلة الخادوم التي ستقوم بالمعالجة. إن كان هنالك العديد من كتل الخادوم مزوّدةً بتعليمات تنصت مضبوطة بنفس القيم ويمكنها أن تعالج الطلب، فسيحلّل إنجن إكس ترويسة المُضيف Host header الخاصة بالطلب ويطابقها مع التعليمة.يمكن للتعليمات الموجودة ضمن هذا السياق أن تعيد تعريف العديد من التعليمات المعرّفة في سياق HTTP بما فيها تعليمات التسجيل logging، وجذر المستندات، والضغط، وإلى ما هنالك. وبالإضافة إلى التعليمات المأخوذة من سياق HTTP، فبإمكاننا أيضًا إعداد ملفات لمحاولة الرد على الطلبات عبر تعليمة (try_files)، وإصدار أمر لإعادة التوجيه وإعادة الكتابة (return و rewrite)، وضبط المتحولات عبر تعليمة (set). سياق الموقعالسياق التالي الذي ستتعرف عليه هو سياق الموقع location context وهو سياقٌ ستتعامل معه بشكل متكرّر. تتشارك سياقات الموقع العديد من الصفات مع سياقات الخادوم. فمثلًا، يمكن تعريف أكثر من سياق موقع، ويُستخدم كل منها لمعالجة نوع محدّد من طلبات المستخدم، ويتم اختيار كل موقع بناءًا على مطابقة تعريف الموقع مع طلب المستخدم باستخدام خوارزمية انتقاء. في الوقت الذي تُعرّف فيه التعليمات - التي تحدّد فيما إن كان سيتم اختيار كتلة خادوم - ضمن السياق الخادوم ذاته، فإن المكوّن component الذي يقرّر مدى قدرة الموقع على معالجة الطلب يقع ضمن تعريف الموقع نفسه. تبدو الصيغة العامة كما يلي: location match_modifier location_match { . . . }تقع كتل الموقع ضمن سياقات الخواديم، وعلى عكس كتل الخادوم، يمكن لكتل الموقع أن تتداخل فيما بينها. قد يفيد ذلك في إنشاء سياق موقع أعم ليلتقط مجموعة فرعية محدّدة من الطلبات المتناقلة traffic، لتكمل السياقات الإضافية الداخلية معالجتها بإسهاب أكبر وفقًا لمعايير أدق. # السياق الأساسي server { # سياق الخادوم location /match/criteria { # سياق موقع أول } location /other/criteria { # سياق موقع ثاني location nested_match { # موقع أول } location other_nested { # موقع ثاني } } }بينما يتم اختيار سياقات الخواديم وفقًا لثنائية عنوان IP / المنفذ المطلوبة ولاسم المضيف الموجود ضمن ترويسة المضيف، فإن كتل الموقع تقسّم معالجة الطلب ضمن كتلة الخادوم بالنظر إلى معرّف الموارد الموّحد URI الخاص بالطلب. إن معرّف URI الخاص بالطلب هو جزءٌ من الطلب يأتي بعد اسم النطاق domain name وثنائية عنوان IP / المنفذ. لذلك فإن طلب المستخدم http://www.example.com/blog على المنفذ 80، يستخدم العنوان http www.example.com والمنفذ 80 لتحديد كتلة الخادوم التي سيتم اختيارها. بعد اختيار الخادوم، سيُطابق الجزء /blog (المُمثّل لمعرّف URI الخاص بالطلب) مع المواقع المعرّفة لتحديد السياق الإضافي الذي ينبغي استخدامه ليرد على الطلب. إنّ العديد من التعليمات التي يمكن أن تراها في سياق الموقع متوفّرةٌ أيضًا في مستويات الآباء (المستويات الأعلى) parent levels. فيما يلي مجموعة جديدة من التعليمات المستخدمة ضمن هذا المستوى تسمح لك بالوصول إلى المواقع الواقعة خارج جذر المستندات (تعليمة alias)، وتحديد الموقع كموقع يمكن الوصول له من الداخل فقط (تعليمة internal)، وكوكيل لخواديم أو مواقع أخرى (باستخدام برتوكولات http، fastcgi، scgi، uwsgi) سياقات أخرىمع أنّ الأمثلة السابقة تمثّل السياقات الأساسية التي ستصادفها في Nginx، إلا أنه يوجد سياقات أخرى أيضًا. هنالك عدّة أسباب دعتنا لفصل السياقات التالية، فإما أنها تعتمد على الكثير من الوحدات الاختيارية، أو أنها تستخدم ضمن ظروف خاصة فقط، أو أنها تستخدم لوظائف لن يستخدمها معظم الأشخاص. لكننا لن نناقش كل السياقات المتوفّرة، ولن نخوض بشرح السياقات الآتية بالتفصيل: split_clients أُعد هذا السياق لتقسيم المستخدمين اللذين يستقبلهم الخادوم إلى فئات categories عبر عنونتهم بمتحولات تعتمد على النسبة المئوية. يمكن أن يُستخدم ذلك لاحقًا للقيام باختبار A/B عبر توفير محتويات content مختلفة لمُضيفين hosts مختلفين.perl / perl_set يُهيّئ هذين السياقين معالجات بيرل Perl للموقع الذي تتواجد ضمنه. تستخدم هذه السياقات للمعالجة باستخدام بيرل فقط.map يُستخدم هذا السياق لضبط قيمة متحول بالاعتماد على قيمة متحول آخر. إذ أنه يوفّر جدول مقابلة mapping لقيم المتحوّل الأول حتى يحدّد القيمة التي ينبغي ضبط المتحول الثاني بها.geo يُستخدم هذا السياق - مثل السياق السابق - في تحديد جدول مقابلة. إلا أنّ هذا الجدول يستخدم خصيصًا لتصنيف عناوين IP. يضبط هذا السياق قيمة متحول وفقًا لعنوان IP المتّصل.types يُستخدم هذا السياق أيضًا لجداول المقابلة. إذ أنه يُستخدم لمقابلة أنماط وسائط الإنترنت MIME بامتدادات (لواحق) extensions الملفات التي ينبغي ربطهم بها. يوفّر Nginx ذلك عادةً عبر ملف يُضمّن محتواه داخل ملف الإعدادات nginx.conf.charset_map يمثّل هذا السياق مثالًا آخر عن سياقات المقابلة، إذ أنه يُستخدم لإنشاء جدول مقابلة للتحويل conversion table من مجموعة محارف إلى مجموعة أُخرى. تضمّن كلا المجموعتين في ترويسة هذا السياق، ويضمّن جدول المقابلة في بنيته body.إنّ السياق التالي ليس شائعًا بقدر السياقات التي شرحناها حتى الآن، إلا أنّ التعرّف عليه يبقى مفيدًا. سياق مجموعة الخواديم العليايُستخدم سياق مجموعة الخواديم العليا upstream context لتعريف وإعداد الخواديم العليا upstream. يعرّف هذا السياق بشكل أساسي حوضًا pool معرّفًا باسم يحتوي على مجموعة الخواديم التي يستطيع Nginx أن يعمل كوكيل proxy عنها للطلبات. ستستخدم هذا السياق على الأرجح عندما تُعد وكلاءًا من مختلف الأنواع. يجب وضع سياق مجموعة الخواديم العليا ضمن سياق HTTP، وخارج كلِّ سياقات الخواديم. تبدو الصيغة العامة له كما يلي: # السياق الأساسي http { # سياق HTTP upstream upstream_name { # سياق مجموعة الخواديم العليا server proxy_server1; server proxy_server2; . . . } server { # سياق خادوم } }يمكن فيما بعد أن تتم الإشارة إلى سياق مجموعة الخواديم العليا باسمه ضمن الخادوم أو كتل الموقع لتمرير طلبات ذات نوع محدّد لحوض الخواديم الذي تمّ تعريفه. ستستخدم عندها مجموعة الخواديم خوارزميةً لتحديد الخادوم الذي ينبغي أن يسلم الطلب له، تستخدم خوارزمية راوند روبن round-robin بشكل افتراضي. يسمح هذا السياق لـNginx أن يعمل على موازنة الحمل load balancing عندما يعمل كوكيل للطلبات. سياق البريدبالرغم من أن Nginx يُستخدم عادةً كخادوم ويب أو خادوم وكيل معكوس، إلا أنه يعمل كخادوم وكيل للبريد mail proxy server بأداءٍ عالي جدًا. يسمّى السياق المستخدم لهذا النوع من التعليمات بالبريد mail. يعرّف سياق البريد The mail context ضمن السياق العام، أو السياق الأساسي (خارج سياق HTTP). الوظيفة الأساسية لسياق البريد هي توفير مجال لإعداد وكيل للبريد على الخادوم. يمكن لـNginx أن يعيد توجيه redirect طلبات المصادقة authentication لخادوم مصادقة خارجي authentication server. ويمكنه بعد ذلك أن يوفّر الوصول إلى خواديم البريد العاملة ببرتوكولات POP3 و IMAP لجلب بيانات البريد الفعلية. يمكن لسياق البريد أن يُعد أيضًا للاتصال بخادوم الترحيل العامل ببرتوكول SMTP (SMTP Relayhost) إن دعت الحاجة. عمومًا، قد يبدو شكل سياق البريد مشابهًا لما يلي: # السياق الأساسي events { # سياق الأحداث } mail { # سياق البريد }السياق الشرطييمكن أن يُنشئ السياق الشرطي if لتوفير معالجة شرطية للتعليمات المعرّفة بداخله. وكما هو حال عبارات الشرط if في لغات البرمجة التقليدية، فإن تعليمة if في Nginx ستنفذ التعليمات المتحواة ضمنها إن كان الشرط محقّقًا وأعاد القيمة الصحيحة True. يُقدَّم السياق if في Nginx من قِبل وحدة إعادة الكتابة rewrite module وهي الغاية الأساسية من استخدام هذا السياق. باعتبار أنّ Nginx سيختبر حالات الطلب باستخدام العديد من التعليمات الأخرى المعمولة لهذا الغرض، فلا ينبغي استخدام تعليمة if في أغلب حالات التنفيذ الشرطي. تُعد هذه الملاحظة هامةً لدرجة أنّ مجتمع Nginx أنشأ صفحةً وسمّاها if الشريرة. إنّ المشكلة الأساسية هي أنّ ترتيب المعالجة لدى Nginx قد يؤدي في كثير من الأحيان إلى نتائج غير متوقعة تظهر وكأنها تقلب معنى كتلة if رأسًا على عقب. تُعد تعليمتي إعادة التوجيه return وإعادة الكتابة rewrite التعليمتين الوحيدتين اللتين يعتبر استخدامهما آمنًا داخل هذه السياقات، إذ أنها أُنشئت لأجلهما. ضع في الحسبان أيضًا أنّه عند استخدام سياق if فإنّه يقدّم تعليمة try_files داخل نفس السياق بلا فائدة. غالبًا ما يتم استخدام if لتحديد فيما إنّ كان هنالك حاجة لتعليمة return أو تعلمية rewrite. وستقع غالبًا داخل كتل الموقع، لذلك فستبدو الصيغة العامة مشابهةً لما يلي: # السياق الأساسي http { # سياق HTTP server { # سياق خادوم location location_match { # سياق موقع if (test_condition) { # سياق شرطي if } } } }سياق تحديد الاستثناءاتيُستخدم سياق تحديد الاستثناءات Limit_except Context لتحديد استخدام طرق HTTP Methods محدّدة داخل سياق الموقع. فمثلًا، إن كان ينبغي لمجموعة محدّدة فقط من المستخدمين أن يصلوا إلى محتوى طريقة POST Method، أما البقيّة فينبغي أن يتمكّنوا من قراءة المحتوى، فيمكنك استخدام كتلة limit_except لتعريف تلك المتطلّبات. سيبدو المثال السابق مشابهًا لما يلي: . . . # سياق موقع أو خادوم location /restricted-write { # سياق موقع limit_except GET HEAD { # سياق تحديد الاستثناءات allow 192.168.1.1/24; deny all; } }ستطبق التعليمات الموجودة داخل السياق - والتي يقصد منها تقييد الوصول - عند مصادفة أيٍ من طرق HTTP باستثناء تلك المدرجة ضمن ترويسة السياق. إنّ نتيجة المثال السابق هي أنّه بإمكان أي مستخدم استخدام أفعال GET و HEAD، إلا أنّه يسمح فقط للمستخدمين المتصلين من الشبكة الفرعية subnet ذات العنوان 192.168.1.1/24 باستخدام طرق أخرى. قواعد عامة حول السياقات ينبغي اتباعهاالآن وبعد أن أصبح لديك فكرة عن السياقات الشائعة التي يمكن أن تصادفها أثناء استعراضك لإعدادات إنجن إكس، فبإمكاننا شرح بعض القواعد المُثلى التي يمكن اتباعها عند التعامل مع سياقات Nginx. تطبيق التعليمات في أعلى سياق متوفرإنّ العديد من التعليمات تكون صالحةً داخل أكثر من سياق واحد. فمثلًا، هنالك بضعة تعليمات يمكن وضعها داخل كل من سياقات HTTP والخادوم والموقع. يمنحنا ذلك مرونةً عند ضبط تك التعليمات. ولكن كقاعدة عامة، عادةً ما يكون من الأفضل تعريف التعليمات في أعلى سياق تقبل التعريف ضمنه، وإعادة تعريفها ضمن السياقات الأدنى عند الحاجة. يمكن ذلك بسبب وحدة الوراثة inheritance model التي تحقّقها إنجن إكس. هنالك العديد من الأسباب لاستخدام هذه الاستراتيجية. أولًا، إنّ التعريف ضمن أعلى مستوى يجنّبك تكرار نفس التعريف ضمن السياقات الأخوة. فمثلًا، في المثال التالي يعرّف كل موقع نفس جذر المستندات. http { server { location / { root /var/www/html; . . . } location /another { root /var/www/html; . . . } } }يمكنك نقل الجذر خارج كتلة الخادوم، أو حتى لكتلة HTTP كما يلي: http { root /var/www/html; server { location / { . . . } location /another { . . . } } }أغلب الأحيان، سيكون مستوى الخادوم ملائمًا أكثر، إلا أنّ التصريح declaring في مستوىً أعلى له محاسنه. إنّ ذلك لا يسمح بضبط التعليمة في أماكن أقل فحسب، وإنما سيسمح لك بتمرير القيمة الافتراضية لكل الأبناء، ما يمنع ظهور الحالات التي تصادف فيها خطأً لأنك نسيت تعليمةً ضمن مستوىً أدنى. يمكن أن يكون ذلك مشكلةً كبيرةً في الإعدادات الطويلة. إن التصريح في مستوىً عالي يوفّر لك قيمةً افتراضيةً صحيحة. استخدام عدة سياقات أشقاء عوضا عن المنطق الشرطي If في المعالجةعندما تريد معالجة الطلبات كل بشكل مختلف، اعتمادًا على بعض المعلومات التي يمكنك ايجادها ضمن طلب المستخدم، فعادةً ما يلجئ المستخدمون إلى سياق if ليحاولوا معالجتها شرطيًا. هنالك بعض المشاكل المترافقة مع ذلك كنا قد ذكرناها سابقًا بإيجاز. أول مشكلة هي أنّ تعليمة if عادةً ما تعيد نتائج لا تتوافق مع توقعات مدير النظام administrator. مع أنّ المعالجة ستُؤدي دائمًا إلى نفس النتائج عند توفير نفس المُدخلات، إلا أنّ الطريقة التي يتبعها Nginx في تفسير البيئة يمكن أن تختلف كثيرًا عما هو متوقع ما ام تخضع لاختبارات مكثّفة. السبب الثاني هو أنّ هنالك تعليمات معدّة لهذا الغرض بالتحديد، وهي مستخدمةٌ للعديد من تلك الأغراض. يستخدم Nginx خوارزمية انتقاء - ذات توثيق جيد - لاختيار كتل الخادوم وكتل الموقع. لذلك، يفضّل نقل الإعدادات المختلفة إلى الكتل المخصّصة لها إن كان ذلك ممكنًا، ما يسمح لتلك الخوارزمية بمعالجة منطق عملية الاختيار. فمثلًا، عوضًا عن الاعتماد على إعادة الكتابة rewrites للحصول على طلب المستخدم بالشكل format الذي ترغب بالعمل به، فعليك أن تجرّب إعداد كتلتين للطلب، أحدهما تمثّل الطريقة المرغوب بها، والأخرى تلتقط الطلبات العشوائية وتعيد توجيهها - وقد تعيد كتابتها - للكتلة الصحيحة. عادةً ما تكون النتائج أسهل للقراءة كما أنها تمتلك محاسن كونها ذات أداء عالي. لا تخضع الطلبات الصحيحة لأي معالجة إضافية وفي العديد من الحالات يمكن تجاوز الطلبات غير الصحيحة عبر تعليمة إعادة التوجيه عوضًا عن تعليمة إعادة الكتابة والتي ينبغي أنّ يكون عبء تنفيذها أقل. الخلاصةإلى هنا، ينبغي أن تكون قد حصلت على فهم جيّد لأكثر سياقات Nginx شيوعًا وللتعليمات التي تُنشئ الكتل التي تعرّف تلك السياقات. تحقّق دائمًا من توثيق Nginx للحصول على معلومات حول أي السياقات هو الأنسب لوضع تعليمة ما بداخله ولتقييم الموقع الأكثر فاعلية. إنّ الحرص أثناء إنشاء الإعدادات لن يسهل من عملية الصيانة فحسب، بل أنه سيرفع الأداء أيضًا في أغلب الآحيان. ترجمة -بتصرف- للمقال Understanding the Nginx Configuration File Structure and Configuration Contexts لكاتبه Justin Ellingwood.
-
Nginx (وتلفظ "engine x") هو خادوم ويب حرّ ومفتوح المصدر، يعمل كخادوم بروكسي معكوس reverse proxy للبروتوكولات HTTP ،POP3 ،SMPT ،IMAP، كتبه Igor Sysoe بهدف التركيز على المرونة، الخفة، وقلّة استهلاك الموارد وذلك بالمقارنة مع أباتشي Apache. المتطلبات كشرط مسبق لهذا الدرس سأفترض أنك انتهيت من الإعدادات الأولية على الخادوم الافتراضي الخاص بك VPS إضافةً إلى تثبيت Nginx بنجاح. الخطوة الأولى: تثبيت Apache Utilsنحتاج أولًا إلى الأداة htpasswd بهدف إنشاء وتحديث ملف لتخزين معلومات التوثيق الأساسية للمستخدم (الاسم وكلمة المرور)، htpasswd هي جزء من حزمة apache2-utils والتي يمكنك تركيبها بالأمر التالي: sudo apt-get install apache2-utils الخطوة الثانية: إنشاء مستخدمإنشاء ملف htpasswd. داخل دليل موقع الويب الخاص بك يؤمن بواسطة Nginx. يُنشئ الأمر التالي الملف اللازم ويضيف اسم مُستخدم مع كلمة مرور مُشفّرة له: sudo htpasswd -c /etc/nginx/.htpasswd exampleuser هنا ستطلب منك الأداة اختيار كلمة المرور: New password: Re-type new password: Adding password for user exampleuser وهكذا تكون صيغة ملف htpasswd. مشابهة لهذا: login:password خُذ بعين الاعتبار أن htpasswd يجب أن يكون قابلًا للوصول بواسطة حساب المستخدم الذي يُشغّل Nginx. الخطوة الثالثة: تحديث إعدادات Nginxيقع ملف ضبط Nginx ضمن الدليل /etc/nginx/sites-available/. أضف السطرين التاليين إلى آخره لحماية مسار النطاق الذي ترغب به: auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; يحمل السطر الثاني مكان ملف htpasswd. الخاص بموقعك. على سبيل المثال لنقل بأنّ ملف ضبط nginx لموقعنا هو /etc/nginx/sites-available/website_nginx.conf/؛ افتح الملف بواسطة المحرّر النصيّ الذي تفضّله: sudo vi /etc/nginx/sites-available/website_nginx.conf ثم أضف هذين السطرين إلى المسار التالي: server { listen portnumber; server_name ip_address; location / { root /var/www/mywebsite.com; index index.html index.htm; auth_basic "Restricted"; #For Basic Auth auth_basic_user_file /etc/nginx/.htpasswd; #For Basic Auth } } الخطوة الرابعة: أعد تحميل Nginxيتوجب علينا أخيرًا إعادة تحميل إعدادات Nginx لتأخذ التغييرات الجديدة موضع التنفيذ على موقع الوِب الخاص بنا. بعد ذلك جرّب الدخول إلى النطاق الذي تمّت حمايته بواسطة معلومات التوثيق السابقة: $ sudo /etc/init.d/nginx reload * Reloading nginx configuration... حاول الآن الدخول إلى موقعك أو إلى مسار النطاق المحمي وسيطلب منك المتصفح إدخال اسم المستخدم وكلمة المرور للمتابعة، ولن يكون بإمكانك استعراض المحتوى دون معلومات الولوج الصحيحة. رائع! أصبح لديك الآن نطاق ويب محمي باستخدام توثيق Nginx الأساسي. ترجمة -وبتصرف- للمقال How To Set Up HTTP Authentication With Nginx On Ubuntu 12.10. حقوق الصورة البارزة: Designed by Freepik.
-
تناول الجزء الأوّل من هذا الدّليل الخوارزميّة الّتي يتبعها خادوم ويب Nginx لاختيّار كتلة Server للإجابة على طلب العميل. سنتحدَّث في هذا المقال عن كتل Location وكيف يقرّر Nginx الكتلة الّتي ستُجيب على الطّلب. تحليل كُتَل Locationتوجد لدى Nginx آليّة لتقرير كتلة Location (الموقع) الّتي ستتولّى التّعامل مع الطّلب. تُشبه هذه الخوارزميّة في عملها خوارزميّة اختيّار كتلة Server المشروحة في الجزء الأوّل من هذا الدّليل. 1- صيّاغة Syntax كتلة Locationنبدأ، قبل شرح خوارزميّة اختيّار كتلة Location الّتي ستتولّى الإجابة على الطّلب، بشرح الصّيّاغة الّتي يستخدمها Nginx في تعريفات كتل الموقع. تُستخدَم كُتل Location الّتي تقبع ضمن كتلة Server (أو ضمن كتلة Location أخرى)، لتقرير كيف يُتعامل مع المعرّفات الكليّة للموارد Universal Resource Identifier, URI (الجزء الّذي يأتي بعد اسم النّطاق أو عنوان IP/المنفذ). تأخذ كتلة Location عمومًا الهيئة التّاليّة: location optional_modifier location_match { . . . }تُحدّد تعليمة location_match مالّذي سيُقارن به معرّف المورد الموجود في الطّلب. يُحيل optional_modifier إلى مُغيِّر اختيّاري يؤثّر على الطّريقة الّتي يبحث بها Nginx عن تطابق في كتلة Location. نميّز الحالات التّاليّة، حسب قيمة optional_modifier: لا يوجد متغيّر: إن لم تُذكَر قيمة للمغيِّر الاختيّاريّ فإنّ الموقع سيُحلّل حسب التّطابق المُبدَأ Prefix match. يعني هذا أنّ الموقع سيُقارَن ببداية معرّف المورِد (URI) في الطّلب، بحثًا عن تطابقات.=: إذا استُخدمت علامة التّساوي فإنّ الكُتلة لن تُأخذ في الحسبان إلّا إذا كانت مطابقة تمامًا لمعرّف المورِد في الطّلب.~: في هذه الحالة يُستخدَم تعبير نمطيّ Regular expression يتأثّر بحالة الأحرف (كبيرة Upper case أو صغيرة Lower case).*~: تختلف عن الحالة السّابقة في أنّ التّعبير النّمطيّ لا يتأثر بحالة الأحرف.~^: تُشير هذه القيمة إلى أنّه إن اختيرت هذه الكتلة في بوصفها أفضل تطابق دون الاعتماد على التّعابير النّمطيّة فإنّ هذه الأخيرة (أي التّعابير النّمطيّة) لن تُأخَذ بالحسبان.2- أمثلة توضّح صيّاغة كتلة Locationكتلة Location التّاليّة مثال على التّطابق المُبدَأ. ستُختار هذه الكتلة للإجابة على الطّلبات الّتي تتضمّن معرّفات الموارِد مثل site/page1/index.html/، site/ أو site/index.html/ (كلّها تبدأ ب site/): location /site { . . . }لتوضيح التّطابق التّام نأخذ الكتلة التّاليّة الّتي ستُستخدَم للإجابة على الطّالبات ذات معرّف المورد page1/. لن تُختار هذه كتلة Location هذه للإجابة على طلب بمعرّف مورد page1/index.html/. انتبه إلى أنّه في حال اختيّار هذه الكتلة وكان الطّلب يُنفَّذ باستخدام صفحة فهرس (Index page) فإنّه ستُجرى إعادة توجيه داخليّة Internal redirect إلى كتلة موقع أخرى تكون هيّ المُداول Handler الفعليّ للطّلب: location = /page1 { . . . }في الإعداد أدناه تعبيرٌ نمطيّ يتأثّر بحالة الأحرف. يُمكن أن تُستخدَم كتلة الموقع في هذا المثال للتّعامل مع الطّلبات على tortoise.jpg/ ولكنّها لا يُمكن أن تلبّي الطّلبات على FLOWER.PNG/. location ~ \.(jpe?g|png|gif|ico)$ { . . . }المثال التّالي لا يختلف عن المثال السّابق سوى في المغيّر الاختيّاريّ (~*) حيثُ إنّ التّعبير النّمطي هنا لا يتأثّر بحالة الأحرف؛ لذا يُمكن استخدام الكتلة للإجابة على كلّ من tortoise.jpg/ و FLOWER.PNG/. location ~* \.(jpe?g|png|gif|ico)$ { . . . }المثال الأخير للحالة الّتي تمنع فيها كتلة Location البحث عن تطابق عبر التّعابير النّمطيّة. تُحدّد الكتلة التّالية على أنّها أفضل تطابق لا يعتمد على التّعابير النّمطيّة للطّلبات على costumes/ninja.html/. location ^~ /costumes { . . . }رأينا أنّ المغيّرات تُحدّد كيف يجب أن تُفسَّر كتلة Location؛ إلّا أنّها لا تخبرنا عن ماهيّة الخوارزميّة الّتي يستخدمها Nginx لتقرير كتلة الموقع الّتي سيُرسِل إليها الطّلب، وهو ما سنتعرّض لها في الفقرات التّاليّة. 3- كيف يختار Nginx كتلة Location الّتي ستتعامل مع الطّلبات؟يستخدم Nginx آليّةً لاختيّار كتلة الموقِع الّتي ستُجيب على الطّلبات مُشابهةً لكيفيّة اختيّاره لكتلة الخادوم.فهم الإجراءات الّتي يتبعها Nginx لاختيّار الكتلة المناسبة أساسيّ جدًّا لتكون قادرًا على إعداد Nginx بوثوق ودقّة. يُقارن Nginx بين معرّف المورد في الطّلب وكتلة Location، مع احتساب المغيّرات الّتي ذكرناه في الفقرة السّابقة، من أجل تحديد أنسب كتلة موقع للإجابة على الطّلب؛ وفقًا للخوارزميّة التّاليّة: يبدأ Nginx بالتحقّق من كلّ المواقع الّتي لا تستعمل تعابير نمطيّة؛ فيُقارن كلّ كتلة موقع بمعرّف مورد الطّلب كاملًا. يبحث Nginx أوّلًا عن تطابق كامل. إن وُجدت كتلة Location تستخدم المغيِّر = وتُطابق تمامًا معرّف المورد في الطّلب؛ فإنّ كتلة الخادوم هذه سيقع عليها الاختيّار فورًا. إن لم يعثُر على تطابق كامل (باستخدام المغيّر =)، ينتقل Nginx إلى تقويم السّابقات (Prefixes) غير المُطابقة تمامًا؛ فيبحث عن أطول تطابق في الموقع مع معرّف المورد ثمّ يقوّمه بالطّريقة التّاليّة: إذا كانت كتلة الموقع الّتي يوجد بها أطول تطابق تستخدِم المغيّر ~^ فسيُنهي Nginx فورًا بحثَه ويختار هذه الكتلة للإجابة على الطّلب. إن لم تكُن الكتلة الّتي يوجد بها أطول تطابق تستخدِم المغيّر ~^ فسيحتفظ بها Nginx دون أن يُنهي البحث، بحيث يُمكن له اختيّارها عند الحاجة. ينتقل Nginx، بعد تحديد الكتلة ذات التّطابق الأطول والاحتفاظ بها، إلى تقويم كتل المواقع الّتي تستخدِم التّعابير النّمطيّة، سواء كانت تتأثّر بحالة الأحرف أم لا. يُقوِّم Nginx التّعابير النمطيّة بالتّسلسل، ويختار فورًا أوّل كتلة موقع يُوافق تعبيرها النّمطيّ معرّفَ مورد الطّلب. إن لم يعثُر خادوم الويب على موقع ذي تعبير نمطيّ يُوافق معرّف المورد المطلوب فإنّه يختار الكتلة المُحتفَظ بها سابقًا للإجابة على الطّلب. من المهمّ هنا أن نفهم أنّ Nginx، مبدئيًّا، يُفضّل كتل الموقع الّتي تُطابق الطّلب عبر تعابير نمطيّة؛ إلّا أنّه يبدأ بالبحث عن تطابق في كتل المواقع الّتي لا تستعمل تعابير نمطيّة، وهو ما يسمح لمسؤول خادوم الويب بتجاوز ميل Nginx إلى تفضيل التّعابير النّمطيّة عبر تحديد المغيِّرات = و~^. من المهمّ أيضًا الانتباه إلى أنّ الاختيّار في كتل المواقع الّتي تستخدِم التّطابق المُبدَأ يكون حسب التّطابق الأطول والأكثر تحديدًا غالبًا. في حين أنّ تقويم التّعابير النمطيّة (وبالتّالي الاختيّار) يتوقّف فور الحصور على تطابق وهو ما يعني أنّ ترتيب كتل المواقع الّتي تستخدم التّعابير النّمطيّة له تأثير كبير على الاختيّار. 4- متى يتجاوز تقويم كتلة الموقع إلى مواقع أخرى؟عند اختيّار كتلة Location للإجابة على طلب فإنّ التّعامل معه، ابتداءً من هذه النّقطة، يحدُث بالكامل ضمن إطار الكتلة المُختارة. فقط هذه الكتلة والتّعليمات المتفرّعة عنها هي من يُحدّد كيف يُتعامل مع الطّلب، دون تدخّل من كتل Location من نفس المستوى في البنية الشّجريّة. تسمح هذه القاعدة العامّة بتصميم كتل Location يُمكن التّنبّؤ بعملها. على الرّغم من ذلك، يجب الانتباه إلى وجود حالات تتسبّب تعليمات داخل الكتلة المُختارة في البحث من جديد عن موقع. يُمكن لهذا الاستثناء من القاعدة العامّة “كتلة موقع واحدة فقط” أن يُحدِث تأثيرات على كيفيّة الإجابة على الطّلب، بحيث يُخالف التّوقّعات الّتي كانت عندك أثناء تصميم كتل المواقع. في ما يلي بعض التّعليمات الّتي قد تؤدّي إلى إعادة توجيه من داخل الكتلة المختارة: indextry_filesrewriteserror_pageنعرض باختصار لكلّ واحدة من هذه التّعليمات. تتسبّب تعليمة index دائمًا في إعادة توجيه إن استُخدِمت للتّعامل مع الطّلب. يُستخدَم التّطابق التّام غالبًا لتسريع اختيّار كتلة الموقع عبر إنهاء الخوارزميّة فور حدوث هذا التّطابق. مع ذلك، إن استخدمت التّطابق التّامّ في حال الطّلب على مجلَّد فإنّه توجد إمكانيّة كبيرة لإعادة توجيه الطّلب إلى موقع آخر للإجابة الفعليّة عليه. تُطابق أوّل كتلة في المثال التّالي معرّف المورد exact/، إلّا أنّ تعليمة index الّتي ترثها هذه الكتلة تتسبّب في إعادة توجيه إلى الكتلة الثّانيّة: index index.html; location = /exact { . . . } location / { . . . }إذا احتجت أن يبقى تنفيذ الطّلب داخل الكتلة الأولى، في المثال أعلاه؛ فسيتطلّب ذلك منك استخدام وسيلة أخرى لتلبيّة الطّلب على المجلّد. يُمكنك مثلًا استخدامُ فهرس غير صالح لهذه الكتلة ثمّ تفعيل تعليمة autoindex: location = /exact { index nothing_will_match; autoindex on; } location / { . . . }هذه إحدى الوسائل لمنع index من تبديل السّيّاق، ولكنّها وسيلة غير ناجعة في أغلب الإعدادات. يُستخدَم التّطابق التّامّ في المجلّدات كثيرًا في بعض الأمور مثل إعادة كتابة الطّلب Request rewriting (الّذي ينتُج عنه البحث من جديد عن الموقع). قد تتسبّب تعليمة try_files هي الأخرى في إعادة تقويم عمليّة اختيّار الموقع. تطلُب هذه التّعليمة من Nginx التحقّق من وجود مجموعة مسمّاة من الملفّات أو المجلّدات؛ قد يكون المُعطى الأخير لتعليمة try_files معرّفَ مورد يُعيد Nginx التّوجيه إليه. فلنأخذ الإعداد التّالي مثالًا للشّرح: root /var/www/main; location / { try_files $uri $uri.html $uri/ /fallback/index.html; } location /fallback { root /var/www/another; }سيختار Nginx الكتلة الأولى، في المثال أعلاه، في حال الطّلب على blahblah/. تبحث الكتلة عن ملفّ blahblah في المجلّد var/www/main/، وإن لم تعثُر عليه تبحث عن ملفّ blahblah.html؛ فإن لم تجد هذا الأخير تبحث عن مجلَّد blahblah/ ضمن var/www/main/. إذا فشلت كلّ هذه المحاولات يُعيد Nginx توجيه الطّلب إلى fallback/index.html/ وهو ما يتسبّب في استدعاء كتلة موقع الأخرى، الثّانيّة في المثال. في المحصّلة فإنّ الملفّ var/www/another/fallback/index.html/ سيكون الإجابة على الطّلب. تعليمة rewrite أيضًا قد تتسبّب في تجاوز كتلة الموقع المختارة عبر الخوارزميّة المشروحة أعلاه. يبحث Nginx عند استخدام المعطى الأخير مع تعليمة rewrite أو في حالة عدم ذكر أيّ معطى على الإطلاق، يبحث عن تطابق جديد اعتمادًا على نتيجة rewrite. نُعيد استخدام المثال الأخير مع إضافة تعليمة rewrite للكتلة الأولى؛ يُمكن أن نلاحظ أنّ الطّلب يُمرَّر في بعض الحالات ماباشرةً إلى كتلة Location الثّانيّة دون تنفيذ تعليمة try_files: root /var/www/main; location / { rewrite ^/rewriteme/(.*)$ /$1 last; try_files $uri $uri.html $uri/ /fallback/index.html; } location /fallback { root /var/www/another; }تُجيب كتلة الموقع الأولى ابتداءً في المثال أعلاه على الطّلب rewriteme/hello/؛ ثمّ يأتي الطّلب لتعليمة rewrite الّتي تُعيد كتابته ليُصبح hello/ فيبدأ Nginx البحث من جديد عن موقع للإجابة على الطّلب ويعثُر من جديد على تطابق مع الكتلة الأولى ثمّ تُنفَّذ عليه تعليمة try_files وفقًا للآليّة المشروحة في مثال استخدام تعليمة try_files. أمّا إذا كان الطّلب على rewriteme/fallback/hello/ فستُطابق كتلة الموقع الأولى الطّلب ثمّ تنفَّذ عليه تعليمة rewrite الّتي تعيد كتابته فيصبح fallback/hello/ ممّا ينتُج عنه مطابقة مع كتلة الموقع الثّانيّة وبالتّالي تُجيب الطّلب. تحدُث حالة مُشابهة مع تعليمة return عند إرسال رمز الحالة Status code رقم 301 أو 302. الفرق في هذه الحالة هي أنّ النتيجة عبارة عن طلب جديد كلّيًّا على هيئة إعادة توجيه خارجيّة External redirect مرئيّة. نفس الشيء يُمكن أن يحدُث مع تعليمة rewrite عند استخدام عَلَميْ redirect و permanent. إلّا أنّ هذه الحالات يجب ألا تكون غير متوقّعة، فإعادة التّوجيه الخارجيّة المرئيّة ينتُج عنها دومًا طلب جديد. ملحوظة 1: الفرق بين إعادة التّوجيه الدّاخليّة والخارجيّة هو أنّ الأولى لا تُنهي طلب العميل الحاليّ بل تُحيله إلى مسار آخر ضمن خادوم الويب؛ أمّا الخارجيّة فتُنهي طلب العميل مع إخباره بمعرّف المورد الجديد الّذي يجب عليه إرسال طلب آخر للحصول عليه. ملحوظة 2: رموز الحالة هي أعداد يستخدمها بروتوكول HTTP ليُشعِر بالحالة الّتي انتهى عليها تنفيذ الطّلب. تُقسَّم إجابات HTTP إلى خمس مجموعات: إجابات بمعلومات، إجابات بنجاح الطّلب، إعادات توجيه، أخطاء من جانب العميل و أخطاء من جانب الخادوم. يُمكن أن تؤدّي تعليمة error_page إلى إعادة توجيه داخليّة مشابهة لتلك الّتي تُنشئها تعليمة try_files. تُستخدَم تعليمة error_page لتحديد ما يجب أن يحدُث عند تلقّي رموز حالات معيَّنة. على الأرجح لن تُنفَّذ تعليمة error_page إذا كانت تعليمة try_filesمضبوطة، فهذه الأخيرة تتعامل مع كامل دورة حياة الطّلب. فلنأخذ المثال التّاليّ: root /var/www/main; location / { error_page 404 /another/whoops.html; } location /another { root /var/www; }تستجيب الكتلة الأولى الّتي تقدّم ملفّات من المجلَّد var/www/main/ لجميع الطّلبات، ما عدا تلك الّتي تبدأ بanother/. إن لم يُعثَر على الملفّ المطلوب ضمن المجلَّد المذكور (رمز الحالة 404) فسيُعاد توجيه الطّلب إلى الملفّ another/whoops.html/ ممّا ينتُج عنه البحث عن كتلة موقع تتعامل مع الطّلب الجديد. يرسو البحث على كتلة الموقع الثّانيّة الّتي تُجيب بالملفّ var/www/another/whoops.html/. يُساعد فهمُ الظّروف الّتي تؤثّر على Nginx وتجعله يبحث عن كتلة موقع جديدة تلبّي الطّلب على توقّع سلوك Nginx عند إنشاء طلبات. خاتمةيُسهّل فهمُ الإجراءات الّتي يتبعها Nginx في الاستجابة لطلبات العملاء كثيرًا من عمل مسؤول الموقع، فيمكنك معرفة كتلة الخادوم الّتي سيختارها Nginx للإجابة حسب كلّ طلب على حدة. كما ستكون لديك القدرة على معرفة كتلة الموقع الّتي سيختارها خادوم الويب اعتمادًا على معرّف المورد المذكور في الطّلب. على العموم تُمكنّك معرفة الطّريقة الّتي يختار Nginx وفقها الكتل المختلفة من تتبّع السّيّاقات الّتي يطبّقها Nginx من أجل الإجابة على كلّ طلب. ترجمة بتصرّف لمقال Understanding Nginx Server and Location Block Selection Algorithms.
-
يمكِن لـِ Nginx، أحد أكثر خواديم الويب انتشارًا؛ التّعاملُ بنجاح مع عملاء عدّة يتّصلون بالتّزامن، كما يُمكنه العمل بوصفه خادوم ويب، خادوم بريد أو وسيطًا عكسيًّا Reverse proxy. سنتطرّق في هذا الدّليل إلى بعض كواليس الآليّة الّتي تحدّد كيف يتعامل Nginx مع طلبات العملاء Client requests. يُساعد فهمُ هذه الآليّة في معرفة كيف تعمل إعدادات الكتلة (Block configurations) في خادوم ويب Nginx وخصوصًا كتلتَيْ Server (الخادوم) وLocation (الموقع). كما أنّه يجعل من تعامل Nginx مع طلبات العملاء أكثر قابليّةً للتّوقّع والتخمين. إعدادات كتلة Nginxيقسّم Nginx إعداداتِ تقديم المحتوى إلى كُتل تنتظِم في بنية شجريّة Hierarchical. يبدأ Nginx عندما يتلقّى طلبًا إجراءاتِ تقرير كُتَل الإعداد الّتي يجب استخدامُها للتّعامل مع الطّلب. سنتحدّث في هذا الدّليل عن آليّة التّقرير هذه. يتحدّث الجزء الأوّل من هذا الدّليل عن كتلة Server، أمّا الثّاني فيتناول كتلة Location. تعرّف كتلة Server، وهي مجموعة فرعيّة من إعدادات Nginx، خادومًا افتراضيًّا يتعامل مع طلباتٍ من نوع محدَّد. يعرّف مدراء الخواديم عادةً كتلَ خادوم عدّة ثمّ يضبطونها للتّعامل مع الطّلبات حسب اسم النّطاق Domain name، أو المنفذ Port، أو عنوان IP الذي يأتي عبره الطّلب. تقبع كتلة Location ضمن كتلة من نوع Server (كتلة خادوم)، وتُستخدَم لتعريف الكيفيّة الّتي سيتعامل بها خادوم ويب Nginx مع الطّلبات على موارد الخادوم والمعرّفات الكليّة لهذه الموارد Universal Resource Identifier, URI. يُمكن أن تُقسَّم مساحة المعرّفات الكليّة للموارد URIs بالطّريقة الّتي يراها المدير عن طريق استخدام كتل Location، فنموذج الكتل مرن للغاية. كيف يقرّر Nginx كتلة Server الّتي ستتعامل مع الطّلب؟يحتاج Nginx، ما دام يسمح بتعريف كُتَل Server عدّة تعمل على أنّها خواديم ويب افتراضيّة متفرّقة، يحتاج لوسيلة يعرف بها كتلة Server الّتي ستتولّى تلبيّة الطّلب. يُعرّف خادوم ويب Nginx نظامَ فحص يُستخدَم للعثور على كتلة Server الأكثر مُطابقةً للطّلب. يهتم Nginx أثناء عمليّة الفحص بتعليمتَيْن Directives على مستوى كتلة الخادوم، وهما listen وserver_name. 1- تحليل تعليمة listen بحثًا عن تطابقات ممكنةينظُر Nginx أوّلًا إلى عنوان IP الطّلب ومنفَذه؛ ثمّ يبحث عن تطابق بين هاتين المعلومتيْن مع محتوى تعليمة listen في كلّ كتلة خادوم. يُنشئ Nginx إثر هذه الخطوة قائمةً بكُتل الخواديم الّتي يُمكن أن تلبّي الطّلب. تعرّف تعليمة listen عنوان IP والمنفَذ الّذيْن ستُجيب كتلة الخادوم الطّلبات الآتيّة منهما. إذا لم تتضمّن كتلة الخادوم تعليمة listen فإنّ المعطيات 0.0.0.0:80 تُمنح للتّعليمة بشكل افتراضيّ (أو 0.0.0.0:8080 إذا كان مستخدم عاديّ غير المستخدم الجذر هو من يشغّل خادوم ويب Nginx). تسمح هذه المعطيات لكتلة الخادوم بالإجابة عن طلبات عبر المنفذ 80 على كلّ الواجهات Interfaces؛ إلّا أنّ المعطيات الافتراضيّة لا تمثّل ثقلًا كبيرًا في عمليّة اختيّار الخادوم. يُمكن ضبطُ تعليمة listen: بذكر عنوان IP ومنفَذ.بذكر عنوان IP فقط؛ في هذه الحالة يُستخدم المنفذ الافتراضيّ 80.بذكر منفَذ فقط؛ في هذه الحالة تستجيب لأي طلب يأتي عبر هذا المنفذ على كلّ الواجهات.بتحديد مسار إلى مقبس يونكس Unix socket.سيقتصر تأثير الخيّار الأخير - غالبًا - على الطّلبات الّتي تمرّر بين مجموعة خواديم. يقرّر Nginx كتلة الخادوم الّتي سيُرسل إليها الطّلب اعتمادًا على خصوصيّة تعليمة listen وذلك وفقًا للقواعد التّاليّة: تُكمَّل الأجزاء غير المكتملة من تعليمة listen بالقيّم الافتراضيّة. الأمثلة التّاليّة توضّح كيف تُكمّل تعليمة listen: كتلة خادوم لا توجد بها تعليمة listen ستستعمل القيمة 0.0.0.0:80.كتلة خادوم مضبوطة على العنوان 111.111.111.111 ولا تعرّف منفذًا تستعمل القيمة 111.111.111.111:80.كتلة خادوم مضبوطة على المنفذ 8888 دون عنوان IP، تستخدم القيمة 0.0.0.0:8888.يكوّن Nginx قائمة بكتل الخواديم الّتي تُطابق الطّلب، وبالتحديد عنوان IP والمنفذ. يعني هذا أنّ أيّة كتلة تستخدم عنوان 0.0.0.0 (مطابقة كلّ الواجهات) لن تُختار إن وُجدت كتلة تستخدم عناوين IP تُطابق الطّلب. في جميع الحالات يجب أن تُطابقَ الكتلة المنفذ بالضّبط. إذا وُجدت كتلة واحدة تُطابق الطّلب، ولم توجد أخرى بنفس المستوى من المُطابقة، فستُستخدَم للإجابة على الطّلب؛ أمّا إذا وُجدت عدّة كتل مع نفس المستوى من المطابقة فإنّ Nginx يبدأ بالنّظر في قيمة تعليمة server_name بالنّسبة لكلّ كتلة خادوم. يجب الانتباه إلى أنّ Nginx لن ينظُر في قيمة تعليمة server_name إلّا إذا احتاج للتّفريق بين كتل خواديم لديها تعليمة listen بنفس المستوى من المطابقة للطّلب. على سبيل المثال؛ إذا كان example.com مُستضافًا على المنفذ 80 من 192.168.1.10 فـإنّ كتلة الخادوم الأولى فقط في المثال أدناه، هيّ من سيستجيب للطّلبات الموّجّهة إلى example.com، على الرّغم من أنّ تعليمة server_name في الكتلة الثّانيّة تحوي القيمة example.com. server { listen 192.168.1.10; . . . } server { listen 80; server_name example.com; . . . }أمّا إذا وُجِدت أكثر من كتلة خادوم تُطابق بنفس المستوى من التّحديد الطّلب؛ فإنّ الخطوة التّاليّة هي فحص محتوى تعليمة server_name. 2- تحليل تعليمة server_name للاختيّار بين التّطابقاتالخطوة المواليّة، في حال وجود كتل خواديم عدّة بنفس المستوى من التّحديد توافق الطّلب، هي تحليل تعليمة server_name. يتحقّق Nginx من ترويسة Header في الطّلب تُسمّى Host (المستضيف). تحوي ترويسة Host اسم النّطاق أو عنوان IP الّذي يُريد العميل الوصول إليه. يُحاول Nginx إيجاد كتلة الخادوم الأكثر مطابقةً لترويسة Host من بين كتل الخواديم المتبقيّة بعد تحليل تعليمة listen. يتبع Nginx الوصفة التّاليّة لإيجاد الكتلة المناسبة: يبحث خادوم الويب عن كتلة خادوم تكون قيمة تعليمة server_name مطابقةً تمامًا لترويسة Host الموجودة في الطّلب. إذا عثر على تعليمة server_name يتحقّق فيها الشّرط فإنّ الكتلة المرتبطة بها هي الّتي تُستخدَم. إذا كانت هناك عدّة تعليمات مطابقة فإنّ أوّل كتلة خادوم هيّ الّتي ستُختار. إن لم يعثُر على مطابقة تامّة يبحث Nginx عن كتلة خادوم تبدأ قيمة تعليمة server_name فيها بحرف بَدَل Wildcard (يُشار إليه بعلامة * في بداية الاسم) بحيث توافق التّعليمة ترويسة المستضيف في الطّلب. إذا عثر على تعليمة server_name يتحقّق فيها الشّرط فإنّ الكتلة المرتبطة بها هي الّتي تُستخدَم. أمّا إذا كانت هناك عدّة تعليمات فإنّ التّعليمة ذات التّطابق الأطول (عدد الأحرف) هيّ الّتي ستُختار. إن لم يُعثُر على مُطابقة باستخدام حرف بدل في بداية قيمة التّعليمة فإنّ Nginx يبحث عن تعليمة server_name تنتهي بحرف بدل (يُشار إليه بعلامة * في نهاية الاسم) بحيث توافق التّعليمة ترويسة المستضيف في الطّلب. إذا عثر على تعليمة server_name يتحقّق فيها الشّرط فإنّ الكتلة المرتبطة بها هي الّتي تُستخدَم. أمّا إذا كانت هناك عدّة تعليمات فإنّ التّعليمة ذات التّطابق الأطول (عدد الأحرف) هيّ الّتي ستُختار. إن لم يعثُر Nginx على مُطابقة باستخدام حرف بدل في نهاية قيمة التّعليمة فإنّه يبحث عن كتلة خادوم تعرّف تعليمة server_name عن طريق تعبير نمطيّ Regular expression (يُشار إليه بعلامة ~ قبل الاسم). يستخدِم Nginx أوّل كتلة خادوم يُوافق تعبير تعليمة server_name النّمطيّ فيها ترويسة المستضيف. إن لم يوجد تطابُق باستخدام التّعبير النّمطيّ يختار Nginx كتلة الخادوم الافتراضّية لعنوان IP والمنفَذ المستخدَم. يوجد لكلّ ثنائيّ عنوان IP/منفذ كتلة خادوم مبدئيّة Default تُستخدَم إن لم تؤدِّ الآليّة الموصوفة أعلاه للعثور على كتلة خادوم. كتلة الثّنائيّ عنوان IP/منفذ المبدئيّة هيّ الكتلة الأولى في الإعداد أو تلك الّتي تحوي خيّار default_server ضمن تعليمة listen (يغلِب مفعول خيّار default_server، إذا كان موجودًا، مفعول الكتلة الأولى). لا يُمكن أن يوجد خيّار default_server في أكثر من مرّة بالنّسبة لكلّ عنوان IP/منفذ. نشرح في الفقرة التّاليّة كلّ نقطة من آليّة العمل أعلاه. 3- أمثلةإذا وجدت تعليمة server_name تُطابق تمامًا ترويسة المستضيف فسيقع على الكتلة المرتبطة بها الاختيّار للإجابة على الطّلب. إذا كانت ترويسة Host الموجودة في الطّلب تحوي host1.example.com فإنّ الخادوم الثّاني في المثال أدناه هو الّذي سيقع عليه الاختيّار: server { listen 80; server_name *.example.com; . . . } server { listen 80; server_name host1.example.com; . . . }إن لم يوجد تطابق كامل يبحثُ Nginx عن تعليمة server_name تبدأ بحرف بَدَل ويتحقّق من توافقها مع المستضيف في الطّلب. يختار خادوم الويب أطول قيمة في server_name من بين تلك الّتي تُطابق الطّلب. في المثال التّالي يختار Nginx كتلة الخادوم الثّانيّة إذا كان العميل يطلُب المستضيف www.example.org: server { listen 80; server_name www.example.*; . . . } server { listen 80; server_name *.example.org; . . . } server { listen 80; server_name *.org; . . . }ملحوظة: كلّ من الكتلة الثّانيّة والثّالثة توافق المستضيف في الطّلب (www.example.org)؛ إلّا أنّ قيمة server_name في الكتلة الثّانيّة أطول. تُقرأ قيمة الكتلة الثّانيّة في المثال أعلاه “جميع المستضيفات الّتي تنتهي بexample.org. أمّا الكتلة الثّالثّة فتقرأ قيمة server_name “جميع المستضيفات الّتي تنتهي بorg.. يُمكن ملاحظة أنّ قيمة server_name في كتلة الخادوم الثّانيّة أكثر تحديدًا. إذا لم يجد Nginx كتلة الخادوم المناسبة في قيّم server_name الّتي تبدأ بحرف بدل، فإنّه يبحث في كتل الخادوم الّتي تنتهي قيّم server_name فيها بحرف بدل. مثل ما يحدُث في الحالة السّابقة، يختار خادوم الويب أطول قيمة في server_name من بين تلك الّتي تُطابق الطّلب. إذا كان المستضيف المحدّد في الطّلب هو www.example.com فإنّ Nginx سيختار، في المثال التّالي، كتلة الخادوم الثّالثة. server { listen 80; server_name host1.example.com; . . . } server { listen 80; server_name example.com; . . . } server { listen 80; server_name www.example.*; . . . }ملحوظة: تُقرأ قيمة server_name في كتلة الخادوم الثّالثة في المثال أعلاه “جميع المستضيفات الّتي تبدأ ب.www.example. مجدّدًا، إذا لم يعثُر Nginx على تطابق باستخدام أحرف البدل في نهاية قيمة التّعليمة فإنّه سينتقل إلى محاولة مطابقة قيمة Host في ترويسة الطّلب بقيّم server_name المعرّفة بتعابير نمطيّة ويختار أوّل كتلة خادوم تُطابق فيها قيمة server_name قيمة Host. إذا كانت قيمة Host هي www.example.com فإنّ Nginx سيختار، في المثال التّالي، كتلة الخادوم الثّالقة للإجابة على الطّلب: server { listen 80; server_name example.com; . . . } server { listen 80; server_name ~^(www|host1).*\.example\.com$; . . . } server { listen 80; server_name ~^(subdomain|set|www|host1).*\.example\.com$; . . . }ملحوظة: يُقرأ التّعبير النّمطيّ أعلاه “يبدأ اسم المستضيف بإحدى الكلمات التّاليّة set، www، host1 أو subdomain؛ قد يتبعها حرف أو عدد غير محدّد من الحروف، ثمّ نقطة ثم كلمة example ثمّ نقطة ثمّ com.“. للمزيد حول التّعابير النّمطيّة راجع درس مقدمة في التعابير النمطية Regular Expressions. إذا لم يتمكّن Nginx من العثور على أي تعليمة server_name مُطابقة لقيمة Host عبر الإجراءات السّابقة فإنّه يختار الخادوم المبدئي الموافق للثّنائي عنوان IP/المنفَذ الّذي أتى عليه الطّلب.
-
AJAXAJAX هي اختصار للعبارة "asynchronous JavaScript and XML"، وهي وسيلة لجلب البيانات من الخادوم دون الحاجة لإعادة تحميل الصّفحة، وهي تقوم على استخدام كائن مُتاح في المتصفّح اسمه XMLHttpRequest (أو XHR اختصارًا) لإرسال الطّلب إلى الخادوم ثمّ التّعامل مع البيانات الّتي يُجيب بها الخادوم. تُوفّر jQuery الوظيفة $.ajax (ووظائف أخرى مرافقة مُختصرة) لتسهيل العمل مع طلبات XHR في جميع المتصفّحات. $.ajaxبإمكاننا استخدام الوظيفة $.ajax() المُرفقة مع jQuery بعدّة أساليب: إحداها أن نُمرّر إليها كائنًا يحوي الإعدادات فقط، أو أن نُمرّر الرّابط مع أو بدون كائن الإعدادات. لنُلقِ نظرة على الأسلوب الأول: // أنشئ دالّة الاستدعاء الرّاجع الّتي ستُنفّذ عندما ينجح طلب AJAX var updatePage = function( resp ) { $( '#target').html( resp.people[0].name ); }; // وعندما يفشل var printError = function( req, status, err ) { console.log( 'something went wrong', status, err ); }; // أنشئ كائن الإعدادات الذي يصف الطّلب var ajaxOptions = { url: '/data/people.json', dataType: 'json', success: updatePage, error: printError }; // أرسل الطّلب $.ajax(ajaxOptions);بإمكانك طبعًا أن تُمرّر كائنًا حرفيًّا مباشرةً إلى الوظيفة$.ajax() وأن تستخدم دالّة مجهولة محلّ success وerror، هذا الأسلوب كتابته أسهل، وصيانته في المستقبل أسهل: $.ajax({ url: '/data/people.json', dataType: 'json', success: function( resp ) { $( '#target').html( resp.people[0].name ); }, error: function( req, status, err ) { console.log( 'something went wrong', status, err ); } });كما قلنا، بإمكانك استخدام الوظيفة$.ajax() بأسلوب ثانٍ، وذلك بتمرير الرّابط أوّلًا ثمّ كائن الإعدادات ثانيًا (ليس إلزاميًّا). يُفيدك هذا في حال رغبت في استخدام الإعدادات المبدئيّة للوظيفة أو في حال رغبت في استخدام كائن الإعدادات نفسه لأكثر من رابط: $.ajax( '/data/people.json', { type: 'GET', dataType: 'json', success: function( resp ) { console.log( resp.people ); }, error: function( req, status, err ) { console.log( 'something went wrong', status, err ); } });في المثال السّابق، لا تشترط الوظيفة سوى الرّابط، ولكنّ إضافة كائن الإعدادات تسمح لنا بإخبار jQuery بنوع البيانات الّتي نُرسلها، وأي فعل HTTP نستخدمه (POST، GET، إلخ...)، وما نوع البيانات الّتي نتوقّع استقبالها من الخادوم، وما الّذي يجب فعله إن نجح الطّلب أو فشل... اطّلع على وثائق الوظيفة$.ajax() لقراءة كامل الخيارات الّتي يمكن إضافتها إلى كائن الإعدادات. A في AJAX تعني "لامتزامن"تجري طلبات AJAX بصورة لا متزامنة، وهذا يعني أنّ الوظيفة$.ajax تنتهي قبل انتهاء الطّلب، وقبل أن تُستدعى دّالة success، أيّ أنّ جملة return تُنفّذ قبل أن يصل جواب الطّلب. فالدّالة getSomeData في المثال التّالي ستُعيد قيمة data قبل أن تُعرّف، مما يؤدّي إلى وقوع خطأ: تحذير: نصّ برمجيّ غير سليم var getSomeData = function() { var data; $.ajax({ url: '/data/people.json', dataType: 'json', success: function(resp) { data = resp.people; } }); return data; } $( '#target' ).html( getSomeData().people[0].name );X في AJAX تعني JSON!وضع المصطلح AJAX عام 2005 ليصف طريقة لجلب البيانات من الخادوم دون الحاجة لإعادة تحميل كامل الصّفحة. في ذلك الوقت، كانت الصّيغة الأكثر شيوعًا للبيانات الّتي تُرسلها الخوادم هي XML، أمّا اليوم، فإنّ JSON هي الصّيغة الّتي تعتمدها أكثر التّطبيقات الحديثة. صيغة JSON في أساسها هي سلسلة نصّيّة (string) تُمثّل البيانات، وتبدو مُشابهة كثيرًا لكائن JavaScript عاديّ، ولكنّها لا تستطيع تمثيل كلّ أنواع البيانات الّتي يستطيع كائن JavaScript تمثيلها. فمثلًا: لا يمكن لـJSON تمثيل كائنات التّاريخ (Date) ولا الدّوال (functions). فيما يلي مثال عن نصّ JSON، لاحظ كيف تُحاط كلّ أسماء الخصائص بعلامتي اقتباس مُضاعفتين: { "people" : [ { "name" : "Ben", "url" : "http://benalman.com/", "bio" : "I create groovy websites, useful jQuery plugins, and play a mean funk bass. I'm also Director of Pluginization at @bocoup." }, { "name" : "Rebecca", "url" : "http://rmurphey.com", "bio" : "Senior JS dev at Bocoup" }, { "name" : "Jory", "url" : "http://joryburson.com", "bio" : "super-enthusiastic about open web education @bocoup. lover of media, art, and fake mustaches." } ] }تذكّر أنّ JSON هو تمثيل نصّيّ لكائن، ما يعني أنّه يجب تفسير السّلسلة النّصيّة لتحويلها إلى كائن JavaScript عاديّ قبل التّعامل معها. عندما تعمل مع جواب ورد من الخادوم بصيغة JSON، فإنّ jQuery تتولّى هذه المهمّة عنك. ولكن من المهمّ التمييز بين الكائنات الفعليّة، وطريقة تمثيلها في JSON. ملاحظة: إن أردت إنشاء سلسلة JSON نصّيّة من كائن JavaScript أو تفسير سلسلة JSON نصّيّة لتحويلها إلى كائن JavaScript دون الاستعانة بـjQuery، فإنّ المُتصفّحات الحديثة تُقدّم الوظيفتين JSON.stringify() وJSON.parse()، ويمكن إضافة هذه الخصائص إلى المُتصفّحات القديمة باستخدام المكتبة json2.js. توفّر jQuery أيضًا وظيفة jQuery.parseJSON()، الّتي توافق الوظيفة JSON.parse() في المتصفّحات، إلّا أنّها لا توفّر وظيفة تُقابل JSON.stringify(). وظائف مُختصرةإن كان كلّ ما نريده إرسال طلب بسيط، دون الاهتمام بالتّعامل مع الأخطاء الّتي قد تقع، فإنّ jQuery تُوفّر وظائف مُختصرة تسمح لنا بفعل ذلك. تستقبل كل وظيفة مُختصرة رابطًا وكائن إعدادات غير إلزاميّ، ودالّة تُستدعى عند نجاح الطّلب فقط: $.get( '/data/people.html', function( html ){ $( '#target' ).html( html ); }); $.post( '/data/save', { name: 'Rebecca' }, function( resp ) { console.log( resp ); });إرسال البيانات والعمل مع النّماذجبإمكاننا إرسال بيانات مع طلبنا بتعيين قيمة للخاصة data في كائن الإعدادات، أو تمرير كائن كمُعامل ثانٍ للوظائف المُختصرة. ستُضاف هذه البيانات إلى الرّابط في طلبات GET بصورة "جملة استعلام" (query string)، أمّا في طلبات POST فإنّها ستُرسل كبيانات نموذج. توفّر jQuery وظيفة مُفيدة .serialize() الّتي تستقبل مُدخلات نموذج وتُحوّلها إلى صيغة "جملة استعلام" (مثل field1name=field1value&field2name=field2value...): $( 'form' ).submit(function( event ) { event.preventDefault(); var form = $( this ); $.ajax({ type: 'POST', url: '/data/save', data: form.serialize(), dataType: 'json', success: function( resp ) { console.log( resp ); } }); });jqXHRتُعيد$.ajax() والوظائف المُختصرة المرافقة لها، كائن jqXHR (اختصارًا لـjQuery XML HTTP Request) والّذي يتضمّن وظائف مُفيدةً كثيرة. بإمكاننا إرسال طلب باستخدام $.ajax() ثمّ حفظ كائن jqXHR في مُتغيّر: var req = $.ajax({ url: '/data/people.json', dataType: 'json' });بإمكاننا استخدام هذا العنصر لربط الاستدعاءات الرّاجعة بالطّلب، حتّى بعد أن يكتمل الطّلب. بإمكاننا مثلًا استخدام الوظيفة .then() (ثُمَّ) لإرفاق استدعاءي نجاح الطّلب وفشله، إذ تقبل .then() دالّة أو اثنتين، تستدعى الأولى عند نجاح الطّلب، والثّانية إن فشل: var success = function( resp ) { $( '#target' ).append( '<p>people: ' + resp.people.length + '</p>' ); console.log( resp.people ); }; var err = function( req, status, err ) { $( '#target' ).append( '<p>something went wrong</p>' ); }; req.then( success, err ); req.then(function() { $( '#target' ).append( '<p>it worked</p>' ); });بإمكاننا استدعاء .then() على كائن الطّلب قدر ما نشاء، وستُنفّذ الاستدعاءات الرّاجعة بالتّرتيب ذاته الّتي أرفقت وفقه. إن لم نُرد إرفاق استدعاءي النّجاح والفشل معًا، فبإمكاننا استخدام الوظيفتين .done() و.fail() على كائن الطّلب: req.done( success ); req.fail( err );لو أردنا إرفاق استدعاء راجعٍ يُنفَّذ دومًا، بغض النّظر عن نجاح الطّلب أو فشله، فيمكننا استخدام الوظيفة .always() على كائن الطّلب: req.always(function() { $( '#target' ) .append( '<p>one way or another, it is done now</p>' ); });JSONPيستغرب كثيرٌ من المبتدئين في JavaScript فشل طلبات XHR الّتي يرسلونها إلى نطاق آخر على الإنترنت، فمثلاً: يحاول بعض المُطوّرين جلب بيانات من واجهة برمجيّة من طرف ثالث (third-party API)، ليفاجؤوا بفشل الطّلب باستمرار. السّبب وراء ذلك أنّ المُتصفّحات لا تسمح بإرسال طلبات XHR إلى نطاقات إنترنت أخرى لأسباب أمنيّة، ولكنّ بعض الواجهات البرمجيّة تُعيد البيانات بصيغة JSONP (اختصارًا لـJSON with Padding)، الّتي تسمح للمُطوّرين بجلب البيانات متجاوزين حظر المُتصفّح. الحقيقة أن JSONP ليس طلب AJAX فعليًّا، فهو لا يستخدم طلب XHR الّذي يوفّره المُتصفّح، بل يعمل بإدراج وسم <script> في صفحة الويب، الّذي يحوي بدوره البيانات المطلوبة، مُحاطة بدالّة تُعيد هذه البيانات عند استدعائها. ليس هذه التّفاصيل مهمّة الآن، لأنّ jQuery تسمح لك بطلب JSONP كما لو كان XHR باستخدام الوظيفة $.ajax() بتعيين نوع البيانات dataType إلى 'jsonp' في كائن الإعدادات. $.ajax({ url: '/data/search.jsonp', data: { q: 'a' }, dataType: 'jsonp', success: function( resp ) { $( '#target' ).html( 'Results: ' + resp.results.length ); } });ملاحظة: عادةً ما توفّر الواجهات البرمجيّة خيارًا لتعيين اسم الدّالّة الّتي تُحيط بالبيانات والّتي ستُستدعى في عنوان الرّابط. عادةً ما يكون هذا اسم مُعامل الرّابط callback، وهذا ما تتوقّعه jQuery مبدئيًّا، إلّا أن بإمكانك تغييره بتعيين قيمة للخاصة jsonp في كائن الإعدادات الّذي تُمرّره لـ $.ajax(). بإمكانك أيضًا استخدام الوظيفة المُختصرة $.getJSON() لإرسال طلب JSONP، حيث تستطيع jQuery تمييزه من خلال وجود callback=? أو ما يشبهها في الرّابط: $.getJSON( '/data/search.jsonp?q=a&callback=?', function( resp ) { $( '#target' ).html( 'Results: ' + resp.results.length ); } );مشاركة الموارد عبر الأصول (cross-origin resource sharing أو CORS اختصارًا) هي خيارٌ آخر للسّماح بالطّلبات العابرة للأصول. ولكنّها غير مدعومة في المتصفّحات القديمة، كما أنّها تحتاج تهيئة خاصّة على الخادوم وتعديل ترويسات الطّلبات في XHR لتعمل. الكائنات المُؤجّلة (Deferreds)ليست كائنات jqXHR الّتي تعرّفنا عليها إلا "نكهة" خاصّة ممّا يُعرف "بالكائنات المؤجّلة". تسمح jQuery لك بإنشاء كائنات مؤجّلة بنفسك، والّتي يمكن الاستفادة منها في تسهيل التّعامل مع الأوامر اللامتزامنة، فهي توفّر طريقة للاستجابة لعمليّة تجري بصورة غير متزامنة بعد نجاحها أو فشلها، وتجنّبك الحاجة لكتابة استدعاءات راجعة مُتداخلة فيما بينها. $.Deferredبإمكانك إنشاء كائنٍ مؤجّل باستخدام $.Deferred(). في المثال التّالي نُنفّذ دالة داخل setTimeout، ثمّ "نفي" (resolve) بوعدنا بإعادة القيمة الّتي تُرجعها الدّالة هذه. نُعيد الوعد (promise)، وهو كائن يمكن ربط الاستدعاءات الرّاجعة به، ولكنّه لا يؤثّر في نتيجة الكائن المؤجّل بحدّ ذاته. بإمكاننا "الإخلاف" (reject) بالوعد إذا وقع خطأ ما أثناء عمل الدّالّة: function doSomethingLater( fn, time ) { var dfd = $.Deferred(); setTimeout(function() { dfd.resolve( fn() ); }, time || 0); return dfd.promise(); } var promise = doSomethingLater(function() { console.log( 'This function will be called in 100ms' ); }, 100);.then() و.done() و.fail() و.always()يمكننا ربط دوالّ تتولّى حالات الخطأ والنّجاح بالوعود، تمامًا كما في كائنات jqXHR: function doSomethingLater( fn, time ) { var dfd = $.Deferred(); setTimeout(function() { dfd.resolve( fn() ); }, time || 0); return dfd.promise(); } var success = function( resp ) { $( '#target' ).html( 'it worked' ); }; var err = function( req, status, err ) { $( '#target' ).html( 'it failed' ); }; var dfd = doSomethingLater(function() { /* ... */ }, 100); dfd.then( success, err );.pipe()بإمكاننا استخدام الوظيفة .pipe() للوعود للاستجابة إلى القيمة الّتي تُوفى وذلك بتعديلها ثمّ إعادة كائن مؤجّل جديد. تعمل الوظيفة .then() بدءًا من الإصدارة 1.8 من jQuery كما تعمل الوظيفة .pipe(). function doSomethingLater( fn, time ) { var dfd = $.Deferred(); setTimeout(function() { dfd.resolve( fn() ); }, time || 0); return dfd.promise(); } var dfd = doSomethingLater(function() { return 1; }, 100); dfd .pipe(function(resp) { return resp + ' ' + resp; }) .done(function(upperCaseResp) { $( '#target' ).html( upperCaseResp ); });التّعامل مع العمليّات الّتي قد تكون لامتزامنةأحيانًا تكون لدينا وظيفة قد تعمل بصورة متزامنة أو لا متزامنة وفق ظروف مُعيّنة، فمثلًا: دالّة تقوم بعمليّة لا متزامنة أوّل مرّة تُستدعى فيها، ثمّ تُخزّن القيمة الّتي أنتجتها العمليّة لتُعيدها مباشرةً عند استدعاءها مُستقبلًا. في هذه الحالة يمكننا الاستفادة من $.when() للاستجابة لكلا الحالتين: function maybeAsync( num ) { var dfd = $.Deferred(); // أعِد وعدًا مؤجّلًا عندما num === 1 if ( num === 1 ) { setTimeout(function() { dfd.resolve( num ); }, 100); return dfd.promise(); } // أنهِ مباشرة فيما سوى ذلك، مُعيدًا num return num; } // هذا سيُجرى بصورة غير متزامنة ويعِد بإعادة 1 $.when( maybeAsync( 1 ) ).then(function( resp ) { $( '#target' ).append( '<p>' + resp + '</p>' ); }); // هذا سُيعيد 0 مُباشرةً $.when( maybeAsync( 0 ) ).then(function( resp ) { $( '#target' ).append( '<p>' + resp + '</p>' ); });بإمكانك أيضًا تمرير أكثر من معامل إلى $.when()، الأمر الّذي يسمح لك بدمج عمليّات متزامنة ولا متزامنة معًا ثمّ الحصول على نتائج تنفيذها كلّها كُمعاملات للاستدعاء الرّاجع: function maybeAsync( num ) { var dfd = $.Deferred(); // أعد وعدًا مؤجّلًا عندما num === 1 if ( num === 1 ) { setTimeout(function() { dfd.resolve( num ); }, 100); return dfd.promise(); } // أنهِ مباشرةً فيما سوى ذلك، مُعيدًا num return num; } $.when( maybeAsync( 0 ), maybeAsync( 1 ) ) .then(function( resp1, resp2 ) { var target = $( '#target' ); target.append( '<p>' + resp1 + '</p>' ); target.append( '<p>' + resp2 + '</p>' ); });عندما يكون إحدى مُعاملات $.when() كائن jqXHR، فإنّنا نحصل على مصفوفة من المُعاملات تُمرّر إلى استدعائنا الرّاجع: function maybeAsync( num ) { var dfd = $.Deferred(); // أعد وعدًا مؤجّلًا عندما num === 1 if ( num === 1 ) { setTimeout(function() { dfd.resolve( num ); }, 100); return dfd.promise(); } // أنهِ مباشرةً فيما سوى ذلك، مُعيدًا num return num; } $.when( maybeAsync( 0 ), $.get( '/data/people.json' ) ) .then(function( resp1, resp2 ) { console.log( "Both operations are done", resp1, resp2 ); });مصادر إضافيةتوثيق AJAXكائن jqXHRالكائنات المؤجّلة في jQueryترجمة (بشيء من التصرف) للجزء السادس من سلسلة jQuery Fundamentals لمؤلّفتها Rebecca Murphey.
-
- javascript
- http
-
(و 6 أكثر)
موسوم في: