لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 02/06/22 في كل الموقع
-
أرجو حل هذه المسائل الاتيه : 1- write a C program that allow user to enter the value of base and height of triangle and then calculate the area of triangle by the following equation: area = 0.5*base*height and then that print the area? 2-write a C program that allow user to enter the radius of circle then calculate and print the area of circle by using the equation: area=PI*raduis2 , where PI constant and its value=3.14 وشكرآ1 نقطة
-
طوال الوقت في جانغو Django، أرى أنه يتم إستخدام الصنف DoesNotExist في حالة عدم وجود نتائج، ولكن في بعض الأحيان قد يتم إستخدام الصنف ObjectDoesNotExist الموجود في django.core.exceptions بدلًا منه. متى أستخدام الصنف ObjectDoesNotExist بدلًا DoesNotExist؟ ومتى أقوم بالعكس؟1 نقطة
-
اريد ان استفسر بخصوص دورة النانو ديجري ب udacity هل تنصحوني بها وهل هناك من جربها وهل تستحق قيمتها ؟ ولماذا هي ؟ لماذا لا اتعلم من اليوتيوب او المنصات الاخرى كحسوب مثلا....1 نقطة
-
1 نقطة
-
السلام عليكم هل عندما نبرمج بعض البرامج علي الحاسوب وتكون هذه البرامج تحتاج الي الانترنت هل يكون هناك اكواد لذالك1 نقطة
-
يبدو و كأنك تتحدث عن api , صحيح , كل لغة برمجة لديها تعامل متكامل مع apis و هناك مكتبات تتواصل مع api لجلب البيانات التي تكون على هيئة json و من ثم تقوم بعرضها في البرنامج و إذا كنت تستخدم Flutter في برمجة برنامج سطح المكتب هناك عدة برامج يمكنك التواصل مع api من خلالها مثل HTTP , DIO مثل الكود التالي var headers = { 'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9' }; var request = http.Request('GET', Uri.parse('api/user')); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { print(await response.stream.bytesToString()); } else { print(response.reasonPhrase); } , و إذا كنت تستخدم #c يمكنك استخدام RestSharp كما في الكود التالي var client = new RestClient("user"); client.Timeout = -1; var request = new RestRequest(Method.GET); request.AddHeader("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9"); IRestResponse response = client.Execute(request); Console.WriteLine(response.Content); و البيانات المرجعة من هذه apis يمكنك عرضها في برنامج كيفما تشاء.1 نقطة
-
لقد وجدت هذا الكود التالي في أحد المشاريع المفتوحة المصدر، الكود التالي مهمته إحتساب الوقت الذي يستغرقه كل طلب: @app.before_request def before_request(): g.start = time.time() @app.teardown_request def teardown_request(exception=None): diff_time = time.time() - g.start print(diff_time) لكنني لا أعرف ما هو الكائن g الموجود في الكود، ما هي مهمة هذا الكائن وفيما يستخدم؟1 نقطة
-
شرح الشفرة: app.before_request: تقوم بتسجيل الدالة ليتم تشغيلها عند بداية كل طلب (request) في مثالك قامت بتسجيل الدالة before_request. app.teardown_request: تقوم بتسجيل الدالة ليتم تشغيلها عند نهاية كل طلب (request) في مثالك قامت بتسجيل الدالة teardown_request. g هو كائن يوفره Flask. هو عبارة عن كائن شامل تحفظ فيه أي بيانات تريدها أثناء سياق طلب واحد. في المثال الذي طرحته قُمت بالاحتفاظ بوقت البداية g.start = time.time() والذي قُمت باستخدامه لاحقاً في الدالة teardown_request لحساب الفرق بين وقت البداية والنهاية diff_time = time.time() - g.start ملاحظة: g كائن يعيش بين app.before_request و بين app.teardown_request اي في سياق التطبيق (the application context) يعني هذا أن g يختلف من طلب لآخر.1 نقطة
-
السلام عليكم .. عند انشائي ل api اقوم بكتابة npm init لكن هل في client side ايضا اقوم بنفس الامر ؟1 نقطة
-
يجب أن تحدد ما تحاول القيام به، برنامجك قد يحتاج لجلب بعض البيانات من خادم ما أو لجلب ملفات (صور - فيديو - نصوص)، بحسب لغة البرمجة التي تعمل عليها والمشكلة التي تحاول حلها قد تجد شيفرات جاهزة أو شبيهة تستطيع إعادة استخدامها ضمن مشروعك1 نقطة
-
في مشروع جانغو Django لدي نموذجين Models. ولكل نموذج من النموذجين تابع manager خاص يُعيد مجموعة مختلفة من الكائنات، بناءً على خاصية في الكائن. هل هناك أي طريقة للحصول على مجموعة استعلام QuerySet (أو مجرد قائمة كائنات list of objects) تكون عبارة عن اتحاد QuerySets التي يتم إرجاعها بواسطة كل تابع manager معًا؟ أبحث عن شبء مثل جملة UNION في SQL لكي يتم دمج نتيجة أكثر من إستعلام معًا.1 نقطة
-
الطرق المختلفة لدمج مجموعتي بحث (QuerySet): مجموعتا البحث من نفس النموذج Model: توجد عدة طرق لدمج مجموعتي بحث من نفس النموذج باستخدام رمز الأنبوب (Pipe) | : # q1, q2 and q3 لنفرض لدينا مجموعات البحث التالية # للدمج بين كل المجموعات نستخدم combined_result= q1 | q2 | q3 باستخدام itertools: توفر itertools طريقة تسلسلية تسمح لك بسهولة الجمع بين مجموعتين أو أكثر من مجموعات البحث من نفس النماذج أو نماذج مختلفة. from itertools import chain combined_list = list(chain(q1,q2)) مجموعتا البحث من نماذج مختلفة: باستخدام الدالة union: تقوم هذه الدالة باستخدام UNION الخاص ب SQL لدمج مجموعتين أو أكثر : qs1.union(qs2, qs3)1 نقطة
-
هل عندما نبرمج شى يكون الكتابه بلاكواد ام استطيع الكتابه بالغه العربيه شكرا1 نقطة
-
لكتابة برنامج ما ستحتاج للغة برمجة عالية المستوى، أي تشبه إلى حد ما اللغات المحكية، أغلب لغات البرمجة تكون باللغة الانكليزية لأنها الأوسع انتشارا، هناك عدة لغات برمجة عربية تستخدم مفردات عربية ضمنها: لغة ألف لغة جيم لغة الأسس البرمجية لغة إبداع لغة عموريا حاليًا إذا رغبت الدخول في مجال البرمجة فالطلب يكون على لغات البرمجة الإنكليزية لانتشارها وانتشار الدعم الواسع لها من مكتبات وتوثيقات1 نقطة
-
نعم هذا ما اريده بالاضافة الى انني اريد اظهار صفحة الخطأ في حال قام المستخدم بالذهاب الى صفحة غير متواجدة1 نقطة
-
صفحات GitHub مخصصة للمواقع الثابتة فقط — المواقع التي تم إنشاؤها باستخدام HTML و CSS و JS. لا يدعم المواقع التي تم إنشاؤها باستخدام Python أو .NET أو PHP أو لغات أخرى من جانب الخادم. ستحتاج إلى العثور على مضيف ويب بديل إذا كنت بحاجة إلى استضافة موقع مكتوب بإحدى هذه اللغات أو كنت بحاجة إلى مضيف قاعدة بيانات. من أشهر مواقع الاستظافة المجانية والتي تدعم لغة بايثون نجد: موقع pythonanywhere. موقع heroku.1 نقطة
-
توجد طريقتين للوصول إلى ما ترغب به: الطريقة الأولى: استخدم {{request.path}} داخل القالب (Template)، ستقوم بإرجاع الرابط (URL) الخاص بالصفحة التي أنت فيها ، ثم قم بالتحقق من أنه يساوي القيمة التي أنت تريدها باستخدام أداة الشرط IF على الشكل التالي: <a href="/signin" class="{% if request.path == '/signin' %} active {% endif %}">Signin</a> <a href="/signup" class="{% if request.path == '/signup' %} active {% endif %}">Signup</a> <a href="/" class="{% if request.path == '/' %} active {% endif %}">Home</a> الطريقة الثانية: قُم بإنشاء متغيرات داخل دوال كل رابط، وهذه المتغيرات قم بارسالها للقالب عند عرضه. def signup_view(request): .... #قم بإنشاء المتغير #signup_page #وإرساله إلى القالب return render(request, "signup_template.html", {"sigup_page": True}) def signin_view(request): .... return render(request, "signup_template.html", {"signin_page": True}) def home_view(request): .... return render(request, "signup_template.html", {"home_page": True}) بعدها استخدم المتغيرات في القالب: <a href="/signin" class="{% if signin_page %} active {% endif %}">Signin</a> <a href="/signup" class="{% if signup_page %} active {% endif %}">Signup</a> <a href="/" class="{% if home_page %} active {% endif %}">Home</a>1 نقطة
-
ما الذي تقصده بـ "رفع التطبيق إلى سطح المكتب"؟ هل تقصد عمل build للمشروع للحصول على ملف exe لتشغيل البرنامج؟ أم تقصد نشر البرنامج على أحد المتاجر مثل Microsoft Store؟ أرجو منك توضيح السؤال بشكل أكبر.1 نقطة
-
يسمح تقييد معدل التراسل Rate limiting بإدارة حركة مرور البيانات في الشبكة، ويحد من عدد المرات التي يكرر فيها المستخدم عملية ما خلال مدة معينة، مثل استخدام واجهة برمجة التطبيقات API. تُعد الخدمات التي لا تحتوي على إجراءات أمان لتقيد من معدل التراسل معدل التراسل عرضة لزيادة التحميل وإعاقة العمل السليم للتطبيق. سنتعلم في هذا المقال كيفية إنشاء خادم Node.js قادر على التحقق من عنوان IP الخاص بالطلب وحساب معدل هذه الطلبات من خلال مقارنة العلامات الزمنية للطلبات لكل مستخدم، فإذا تجاوز عنوان IP الحد المعين الذي اخترناه في تطبيقنا، فسوف نتصل بواجهة برمجة تطبيقات Cloudflare API ونضيف عنوان IP إلى القائمة، بعدها سننشئ قاعدة جدار حماية Cloudflare Firewall تحظر جميع الطلبات الواردة من عناوين IP الموجودة في تلك القائمة. إذًا سننشئ مشروع Node.js على منصة تطبيقات DigitalOcean التي تدعي App Platform والتي تحمي النطاقات المسجلة والمضافة إلى حسابك في Cloudflare بتقيد معدل التراسل. ستحتاج خلال هذا المقال إلى: حساب Cloudflare، ويفي الحساب المجاني Free plan من Cloudflare بالغرض. احرص اختيار الحساب المجاني عند إنشاء حساب جديد. نطاق مسجل ومضاف إلى حسابك في Cloudflare. يمكنك الإطلاع على كيف نخفف من هجمات DDoS ضد موقعنا باستخدام CloudFlare مع Cloudflare، وننصح بقراءة هذا المقال للتعرف على أساسيات نظام أسماء النطاقات DNS ومكوناته. خادم Express مع بيئة Node.js، اتبع الخطوات في المقال التالي لإعداد خادم Express. حساب على GitHub ونسخة مثبتة من برنامج gitعلى جهازك، يُعد ذلك ضروريًا لأننا سنرسل الشيفرة من GitHub على منصة App Platform من DigitalOcean. حساب على موقع DigitalOcean. إعداد المشروع والنشر على منصة App Platform سنوسع خادم Express الأساسي الذي أنشأناه في مقال دليل استخدام Node.js وإطار العمل Express للمبتدئين، في هذه الخطوة، ونرسل الشيفرة إلى مستودع GitHub Repository، ثم ننشر التطبيق على منصة App Platform. افتح مجلد مشروع خادم Express بواسطة إحدى محررات النصوص البرمجية، ثم أنشئ ملفًا جديدًا في المجلد الرئيسي للمشروع باسم getignore.، وأضف الأسطر التالية: node_modules/ .env لاحظ أن السطر الأول في ملف getignore. يوجه git لعدم تتبع المجلد node_modules، ويتيح ذلك عدم زيادة حجم المستودع، إذ يُولَد المجلد node-modules عند الحاجة باستخدام الأمر npm install، أما السطر الثاني فيمنع تتبع ملف متغيرات البيئة، وسوف ننشئ الملف env. في الخطوات التالية. انتقل إلى ملف server.js في محرر النصوص البرمجية وعدل الأسطر التالية: ... app.listen(process.env.PORT || 3000, () => { console.log(`Example app is listening on port ${process.env.PORT || 3000}`); }); يتيح الاستخدام الشرطي للمتغير PORT تشغيل الخادم ديناميكيًا على المنفذ المعين PORT في متغير البيئة process.env أو استخدام المنفذ 3000 كمنفذ احتياطي. لاحظ أن السلسلة الموجودة في التابع console.log ليست محاطة بعلامة اقتباس عادية وإنما بعلامة اقتباس مائلة (`) ، إذ يتيح ذلك استخدام القوالب النصية template literals التي تسمح باستخدام التعابير expressions ضمن السلاسل. شَغّل التطبيق من واجهة الطرفية Terminal باستخدام الأمر التالي: node server.js لاحظ أن واجهة المتصفح ستعرض الرسالة التالية: "Successful response" أي أنه نجحت الاستجابة، وسيظهر الخرج التالي في واجهة الطرفية: Example app is listening on port 3000 سننشر الآن التطبيق على منصة App platform بعد أن تأكدنا من عمل خادم Express بنجاح. أولاً ، هيئ git في المجلد الرئيسي للمشروع وأرسل الشيفرة إلى حسابك في GitHub، ثم انتقل إلى لوحة التحكم Dashboard في منصة App Platform في المتصفح وانقر على زر إنشاء التطبيق Create App. ثم اضغط على خيار GitHub وتوثيق مع GitHub، ثم اختر مستودع مشروعك من القائمة المنسدلة. راجع الإعدادات، ثم سمي التطبيق، وبما أننا سنعمل على مرحلة تطوير التطبيق في هذا المقال يُفضل أن نختار الخطة الأساسية Basic Plan، ثم اضغط على زر تشغيل التطبيق Launch App. انتقل بعد ذلك إلى صفحة الإعدادات Settings واضغط على قسم النطاقات Domains ثم أضف النطاق الخاص بك الموجه بواسطة Cloudflare في حقل اسم النطاق الرئيسي أو الفرعي Domain or Subdomain Name، ثم اضغط على خيار إدارة النطاق الخاص بك You manage your domain وانسخ سجل CNAME لتضيفه إلى حساب DNS الخاص بنطاقك في Cloudflare. افتح لوحة تحكم النطاق في Cloudflare في علامة تبويب جديدة، ثم اضغط على تبويبة DNS، واضغط بعدها على زر إضافة سجل Add Record واختر CNAME عند خيار النوع Type، اكتب الرمز @ ثم الصق سجل CNAME الذي نسخته سابقًا من منصة App Platform. اضغط على زر الحفظ Save ثم انتقل إلى صفحة الإعدادات Settings في لوحة تحكم App platform واضغط بعدها على قسم النطاقات Domains، ثم اضغط على زر إضافة نطاق Add Domain. اضغط على علامة تبويب عمليات النشر Deployments لمشاهدة تفاصيل التطبيقات المنشورة. يمكنك الضغط على نطاقك your_domain لاستعراضه في المتصفح، حالما ينتهي النشر. لاحظ أن واجهة المتصفح ستعرض الرسالة التالية: نجحت الاستجابة "successful response". ستحصل على الرسالة التالية عند الانتقال إلى علامة تبويب سجلات التشغيل الحالية Runtime Logs في لوحة تحكم App Platform: Example app is listening on port 8080 لاحظ أن المنفذ 8080 هو المنفذ الافتراضي في App Platform، يمكنك تغييره من الإعدادات قبل النشر. الآن، سنتعلم كيفية تحديد ذاكرة التخزين المؤقت cache لحساب الطلبات الواردة إلى مُقيِّد معدل التراسل Rate limiter. تخزين عنوان IP المستخدم وحساب عدد الطلبات في الثانية سنخزن في هذه الخطوة عنوان IP المستخدم في ذاكرة تخزين مؤقتة cache مع مجموعة من الطوابع الزمنية timestamps لمراقبة عدد الطلبات في الثانية من عنوان IP لكل مستخدم. تُخزن ذاكرة التخزين المؤقت البيانات التي يستخدمها تطبيق ما بشكل متكرر، ويُحتفظ عادةً بالبيانات الموجودة في ذاكرة التخزين المؤقت في أجهزة الوصول السريع مثل ذاكرة الوصول العشوائي RAM، فالغرض الأساسي منها هو تسريع استرداد البيانات عن طريق تقليل الحاجة إلى استردادها من وسائط التخزين الأبطأ. سنحتاج إلى ثلاثة حزم من برنامج مدير الحزم npm وهي node-cache وis-ip و request-ip. فتلتقط الحزمة request-ip عنوان IP المستخدم الذي يطلب الخادم، أما الحزمة node-cache فتنشئ ذاكرة تخزين مؤقتة تستخدم لتتبع طلبات المستخدم، وتستخدم الحزمة is-ip للتحقق فيما إذا كان عنوان IP هو عنوان IPv6. ثبت الحزم node-cache وis-ip و request-ip في الطرفية باستخدام مدير الحزم npm عن طريق الأمر التالي: npm i node-cache is-ip request-ip افتح ملف server.js بواسطة إحدى محررات النصوص البرمجية وأضف الأسطر التالية بعد سطر const express = require('express');: ... const requestIP = require('request-ip'); const nodeCache = require('node-cache'); const isIp = require('is-ip'); ... يحضّر السطر الأول وحدة requestIP من حزمة request-ip التي ثبتها سابقًا، فتقوم هذه الوحدة بإلتقاط عنوان IP المستخدم الذي يطلب الخادم. أما السطر الثاني فيحضّر وحدة nodeCache من حزمة node-cache، التي تنشئ ذاكرة تخزين مؤقتة تستخدم لتتبع طلبات المستخدم في الثانية. ويحضّر السطر الثالث وحدة isIp من الحزمة is-ip، ويتحقق فيما إذا كان عنوان IP من الإصدار السادس IPv6 الذي سوف تصوغه وفق ترميز CIDR المعتمد في Cloudflare. عَرِّف المتغيرات الثابتة في ملف server.js: ... const TIME_FRAME_IN_S = 10; const TIME_FRAME_IN_MS = TIME_FRAME_IN_S * 1000; const MS_TO_S = 1 / 1000; const RPS_LIMIT = 2; يحدد المتغير الثابت TIME_FRAME_IN_S الفترة التي يحسب خلالها تطبيقك متوسط الطوابع الزمنية للمستخدم، ويجدر بالذكر أن زيادة الفترة الزمنية سيؤدي إلى زيادة حجم الذاكرة المؤقتة، وبالتالي سيؤدي إلى استهلاك حجم أكبر من الذاكرة. ويحدد المتغير الثابت TIME_FRAME_IN_MS الفترة التي يحسب خلالها تطبيقك متوسط الطوابع الزمنية للمستخدم، ولكن بالميللي ثانية، وسنستخدم معامل التحويل MS_TO_S لتحويل الزمن من صيغة الميللي ثانية إلى صيغة الثواني. يحدد المتغير RPS_LIMIT حد العتبة الذي سيؤدي إلى تشغيل مقيد معدل التراسل، ويغير قيمة العتبة وفقًا لمتطلبات التطبيق، وقد أسندنا له القيمة 2 والتي تعتبر قيمة معتدلة، في المتغير RPS_LIMIT أثناء مرحلة التطوير. يمكنك باستخدام إطار العمل Express كتابة دوال وسيطة middleware لها وصول إلى جميع طلبات HTTP الواردة إلى خادمك. استدعِ التابع ()app.use لتعريف دالة وسيطة، ومررها ضمنه، باتباع هذه الطريقة أنشئ دالة وسيطة باسم ipMiddleware: ... const ipMiddleware = async function (req, res, next) { let clientIP = requestIP.getClientIp(req); if (isIp.v6(clientIP)) { clientIP = clientIP.split(':').splice(0, 4).join(':') + '::/64'; } next(); }; app.use(ipMiddleware); ... لاحظ أن الدالة ()getClientIP تستخدم الكائن req من الدالة الوسيطة كمعامل. نستدعي الدالة ()v6. مع الوحدة is-ip، وتعطي نتيجة صحيحة true إذا كان الوسيط الممرر إليها عنوان IPv6. يجب عليك صياغة عناوين IPv6 وفق قناع شبكة 64/ حسب ترميز CIDR، كالآتي: aaaa:bbbb:cccc:dddd::/64 ينشئ التابع (':')split. مصفوفة من السلسلة التي تحتوي على عناوين IP ويفصلهم بواسطة المحرف:. يرجع التابع (splice(0,4. أول أربعة وسطاء في المصفوفة. أما التابع (':')join. فيرجع سلسلة من المصفوفة مع المحرف :. يوجه التابع ()next الدالة الوسيطة للانتقال إلى الدالة الوسيطة التالية، إن وجدت، ونلاحظ في مثالنا أنها تنقل الطلب إلى المسار / من طلب GET. احرص على تضمين ذلك في التابع، وإلا فلن ينتقل الطلب من الدالة الوسيطة. هيئ نسخة instance من الوحدة node-cache عن طريق إضافة المتغير التالي بعد الثوابت: ... const IPCache = new nodeCache({ stdTTL: TIME_FRAME_IN_S, deleteOnExpire: false, checkperiod: TIME_FRAME_IN_S }); ... يمكننا إعادة تعريف المعاملات overriding الأساسية الخاصة بوحدة nodecache وتبديلها إلى خصائص محددة custom properties باستخدام المتغير الثابت IPCache: stdTTL: يعبر عن الفاصل الزمني بالثواني الذي يُحذَف بعده زوج مفتاح-قيمة key-value من عناصر ذاكرة التخزين المؤقت. TTL تعني وقت الحياة Time To Live، وهي مقياس للوقت الذي تنتهي بعده ذاكرة التخزين المؤقت. deleteOnExpire: اضبطه على falseحيث أننا سنكتب تابع استدعاء فيما بعد ليتعامل مع الحدث expired. *checkperiod يعبر عن الفاصل الزمني بالثواني الذي يُشغَل بعده فحص تلقائي للعناصر منتهية الصلاحية. تكون القيمة الإفتراضية 600، لكن فحص انتهاء الصلاحية في تطبيقك سيحدث في وقت أقصر، لأن القيمة المحددة أصغر. يمكنك الإطلاع على توثيق node-cache للحصول على مزيد من المعلومات عن المعاملات الإفتراضية لحزمة node-cache. سيساعدك المخطط التالي على تصور كيفية تخزين ذاكرة التخزين المؤقت للبيانات: سننشئ الآن زوج مفتاح-قيمة لعنوان IP الجديد ونضيفه للزوج القديم في حال وجود عنوان IP في الذاكرة المؤقتة. تكون القيمة عبارة عن مصفوفة من العلامات الزمنية timestamps المقابلة لكل طلب وارد إلى تطبيقك. أنشئ الدالة ()updateCache بعد المتغير الثابت IPCache لإضافة علامات زمنية للطوابع في الذاكرة المؤقتة: ... const updateCache = (ip) => { let IPArray = IPCache.get(ip) || []; IPArray.push(new Date()); IPCache.set(ip, IPArray, (IPCache.getTtl(ip) - Date.now()) * MS_TO_S || TIME_FRAME_IN_S); }; ... لاحظ أن السطر الأول في الدالة يحضر مجموعة العلامات الزمنية لعنوان IP المحدد أو يهيئ مصفوفة فارغة إذا كان فارغًا. نقوم في السطر التالي بإضافة العلامة الزمنية الحالية التي التقطت بواسطة الدالة ()new Date إلى المصفوفة. تأخذ الدالة ()set. ثلاثة وسطاء هي : key و value وTTL، فيعيد الوسيط الأخير تعريف قيمة TTL القياسية عن طريق استبدال قيمة stdTTL في المتغير IPCache، ويستخدم TTL الحالية إذا كان عنوان IP موجودًا في الذاكرة المؤقتة، عدا عن ذلك تُحَدد قيمة TTL من المتغير TIME_FRAME_IN_S. تُحسَب قيمة TTL لزوج مفتاح-قيمة الحالي عن طريق طرح قيمة العلامة الزمنية الحالية من العلامة الزمنية لانتهاء الصلاحية، وتُحَول النتيجة إلى ثواني ثم تُمَرر إلى حقل الوسيط الثالث في الدالة ()set.. تقبل الدالة ()getTtl. مفتاحًا وعنوان IP كوسطاء وترجع زمن TTL للزوج مفتاح-قيمة كعلامة زمنية، وفي حال عدم وجود عنوان IP في الذاكرة المؤقتة، تُرجِع undefined وتستخدم القيمة الاحتياطية في المتغير TIME_FRAME_IN_S. أضف الأسطر التالية في الدالة الوسيطة ipMiddleware بعد تعليمة if (isIp.v6(clientIP)) لحساب عدد الطلبات في الثانية من عنوان IP الذي يطلب التطبيق: ... updateCache(clientIP); const IPArray = IPCache.get(clientIP); if (IPArray.length > 1) { const rps = IPArray.length / ((IPArray[IPArray.length - 1] - IPArray[0]) * MS_TO_S); if (rps > RPS_LIMIT) { console.log('You are hitting limit', clientIP); } } ... يضيف السطر الأول الطابع الزمني للطلب الوارد من عنوان IP إلى ذاكرة التخزين المؤقت عن طريق استدعاء دالة ()updateCache، ويجمع السطر الثاني مجموعة العلامات الزمنية لعنوان IP. إذا كان عدد العناصر في مصفوفة العلامات الزمنية أكبر من واحد (إذ يحتاج حساب الطلبات في الثانية إلى علامتين زمنيتين على الأقل)، وعدد الطلبات في الثانية هو أكبر من قيمة العتبة التي حددناها في الثوابت، إذا سوف يطبع عنوان IP في لوحة التحكم console. يحسب المتغير rps عدد الطلبات في الثانية عن طريق تقسيم عدد الطلبات على فارق الفاصل الزمني، ثم يحول النتيجة إلى الثانية. بما أننا اسندنا القيمة false إلى الخاصية deleteOnExpire في المتغير IPCache، علينا الآن التعامل يدويُا مع الحدث expired، فتوفر وحدة node-cache دالة استدعاء تُشَغل الحدث expired. أضف الأسطر التالية بعد المتغير IPCache: ... IPCache.on('expired', (key, value) => { if (new Date() - value[value.length - 1] > TIME_FRAME_IN_MS) { IPCache.del(key); } }); ... تقبل دالة رد النداء()on. مفتاح key وقيمة value العنصر منتهي الصلاحية كوسطاء، وتكون value عبارة عن مصفوفة علامات زمنية للطلبات مخزنة في الذاكرة المؤقتة. يتحقق السطر المحدد الثاني من العنصر الأخير في مصفوفة القيم بمقارنته مع المتغيرTIME_FRAME_IN_S، إذ يطرح آخر عنصر في مصفوفة القيم value من الدالة new Date() (الوقت الحالي)، فإذا كانت النتيجة أصغر من قيمة المتغير TIME_FRAME_IN_S تأخذ الدالة .del() المفتاحkey كوسيط وتحذف العنصر منتهي الصلاحية من ذاكرة التخزين المؤقت. ... else { const updatedValue = value.filter(function (element) { return new Date() - element < TIME_FRAME_IN_MS; }); IPCache.set(key, updatedValue, TIME_FRAME_IN_S - (new Date() - updatedValue[0]) * MS_TO_S); } ... يوفر تابع المصفوفات المحلي filter() في جافاسكريبت دالة استدعاء لترشيح العناصر الموجودة في مصفوفة العلامات الزمنية. يتحقق السطر الثالث من الشيفرة السابقة من نتيجة طرح العناصر من الدالة new Date() إذا كانت أصغر من المتغير TIME_FRAME_IN_S ويخزن النتيجة في المتغير updatedValue ثم تضاف العناصر التي تمت تصفيتها إلى المتغير updatedValue. يؤدي ذلك إلى تحديث ذاكرة التخزين المؤقت بالعناصر التي تمت تصفيتها في المتغير updatedValue وزمن TTL الجديد. تحفز قيم TTL التي تطابق العنصر الأول من المتغير updatedValue تشغيل دالة .on('expired')عندما تحذف الذاكرة المؤقتة العنصر التالي. وتحسب قيمة زمن TTL الجديد عن طريق حساب الفرق بين المتغير TIME_FRAME_IN_S والوقت منتهي الصلاحية منذ أول علامة زمنية للطلب في المتغير updatedValue. شَغّل التطبيق من واجهة الطرفية: node server.js انتقل إلى العنوان localhost:3000 في متصفح الويب، ولاحظ أن المتصفح سوف يعرض الرسالة: "Successful response"، ثم جرب حَدِث الصفحة عدة مرات حتى تتجاوز قيمة المتغير RPS_LIMIT ولاحظ النتيجة التي ستعرضها الطرفية: Example app is listening on port 3000 You are hitting limit ::1 ملاحظة: يظهر عنوان localhost IP على الشكل ::1، لكن ذلك سيتغير، إذ يلتقط تطبيقك العنوان العام Public IP للمستخدم عند نشره خارج الخادم المحلي localhost. أصبح بإمكان تطبيقك تتبع طلبات المستخدم وتخزين العلامات الزمنية في ذاكرة التخزين المؤقت. سنتعلم في الخطوة التالية كيفية استخدام واجهة برمجة تطبيقات Cloudflare لإعداد جدار الحماية Firewall. إعداد جدار حماية Cloudflare سنتعلم في هذه الخطوة كيفية إعداد جدار حماية Cloudflare لإيقاف عناوين IP عند الوصول إلى الحد المعين، وكيفية إنشاء متغيرات البيئة environment variables، واستدعاء واجهة برمجة تطبيقات Cloudflare. سجل الدخول في لوحة تحكم Cloudflare، ثم اذهب إلى الصفحة الرئيسية لحسابك ومنها اضغط على علامة تبويب الإعدادات Configurations، ثم قوائم Lists. أنشئ قائمة جديدة باسم your_list. افتح لوحة تحكم النطاق الخاص بك your_domain من الصفحة الرئيسية Home، ثم اضغط على علامة تبويب الجدار الناري Firewall واضغط على قواعد الجدار الناري Firewall Rules ثم على إنشاء قاعدة جديدة Create a Firewall rule وسَمِها باسم تختاره مثل your_rule_name مجازًا. اختر عنوان المصدر IP Source Address من القائمة المنسدلة، واختر is in list عند خيار المُشغِل Operator، و your_list عند خيار القيمة Value، ثم اضغط على حجب Block من القائمة المنسدلة للخيار Choose an action، واضغط بعدها على زر نشر Deploy. أنشئ ملفًا بصيغة env. في المجلد الرئيسي للمشروع وأضف عليه الأسطر التالية حتى نتمكن من استدعاء واجهة تطبيقات Cloudflare من تطبيقنا: ACCOUNT_MAIL=your_cloudflare_login_mail API_KEY=your_api_key ACCOUNT_ID=your_account_id LIST_ID=your_list_id انتقل إلى قسم الملف الشخصي My Profile في لوحة تحكم Cloudflare، ثم اضغط على علامة تبويب وحدات واجهة التطبيقات API Tokens للحصول على قيمة API_KEY، ثم اضغط على عرض View في قسم Global API Key واكتب كلمة المرور الخاصة بك. انتقل إلى علامة تبويب الإعدادات Configuration ثم إلى قسم القوائم Lists، واضغط على زر تعديل Edit بجانب القائمة your_list التي أنشأتها. يمكنك الحصول على معرف الحساب ACCOUNT_IDومعرف القائمة LIST_ID من عنوان URL من المتصفح الذي يكون على الصيغة التالية: https://dash.cloudflare.com/your_account_id/configurations/lists/your_list_id تنبيه: احرص على أن يكون محتوى الملف env. سريًا وليس متاحًا للجميع، وذلك عن طريق إضافته ضمن ملف gitignore. الذي أنشأناه في الخطوة الأولى. ثبت حزمة axios و dotenv في الطرفية بواسطة مدير الحزم: npm i axios dotenv أضف الأسطر التالية بعد سطر المتغير nodeCache: ... const axios = require('axios'); require('dotenv').config(); ... يحضر السطر الأول وحدة axios من حزمة axios المثبتة، وسنستخدم هذه الوحدة لإجراء استدعاءات إلى واجهة برمجة تطبيقات Cloudflare. يُعِد السطر الثاني وحدة dotenv ويفَعّل المتغير العام process.env الذي سيعرف قيم ملف env. في ملف server.js. أضف الأسطر البرمجية التالية إلى تعليمة If الشرطية التالية if (rps > RPS_LIMIT) فوق السطر:console.log('You are hitting limit', clientIP) حتى تتمكن من استدعاء واجهة برمجة تطبيقات Cloudflare: ... const url = `https://api.cloudflare.com/client/v4/accounts/${process.env.ACCOUNT_ID}/rules/lists/${process.env.LIST_ID}/items`; const body = [{ ip: clientIP, comment: 'your_comment' }]; const headers = { 'X-Auth-Email': process.env.ACCOUNT_MAIL, 'X-Auth-Key': process.env.API_KEY, 'Content-Type': 'application/json', }; try { await axios.post(url, body, { headers }); } catch (error) { console.log(error); } ... أصبح بإمكاننا الآن الاتصال بواجهة برمجة تطبيقات Cloudflare عن طريق العنوان URL لإضافة عنصر، وفي حالتنا سنضيف عنوان IP إلى القائمة your_list، إذ تظهر واجهة برمجة تطبيقات Cloudflare المتغيران ACCOUNT_MAIL و API_KEY في ترويسة الطلب على الشكل X-Auth-Email و X-Auth-Key. أما جسم الطلب فيتألف من عنوان IP الذي سيضاف إلى القائمة وتعليق comment له القيمة your_comment. ضع في الحسبان أنه يمكنك استبدال التعليق comment بالتعليق الذي يحلو لك لتمييز القيمة المدخلة. يوضع الطلب POST المستدعى على الشكل ()axios.post ضمن الكتلة البرمجية try-catch لمعالجة الأخطاء، إن وجدت، فتحتاج الدالة axios.post إلى الوسطاء التالية: url، body، headers لإنشاء الطلب. يجب عليك تغيير قيمة المتغير clientIP عند تجريب الطلبات إلى عنوان IP تجريبي مثل: 198.51.100.0/24 لأن Cloudflare لايقبل عنوان الخادم المحلي localhost: ... let clientIP = '198.51.100.0/24'; ... شغل التطبيق من واجهة الطرفية: node server.js انتقل إلى العنوان localhost:3000 في المتصفح وستلاحظ ظهور الرسالة: "Successful response". حَدِث الصفحة عدة مرات حتى تتجاوز قيمة المتغير RPS_LIMIT ولاحظ النتيجة التي ستعرضها الطرفية: Example app is listening on port 3000 You are hitting limit ::1 انتقل الآن إلى صفحة لوحة تحكم Cloudflare ثم إلى صفحة القوائم your_list حيث سيظهر عنوان IP الذي أضفناه في القائمة your_list، ثم ستظهر صفحة الجدار الناري بعد إرسال التغييرات إلى GitHub. انشر تطبيقك بعد حفظ التعديلات وارفع الشيفرة على GitHub، وبنا أننا فعّلنا خيار النشر التلقائي auto-deploy سيرسل الكود تلقائيًا من GitHub إلى منصة App Platform لنشره. ستحتاج إلى إضافة ملف env. إلى منصة App Platform في قسم متغيرات بيئة التطبيق App-Level Environment Variables من تبويبة الإعدادات Settings. أضف زوج مفتاح-قيمة إلى ملف env. كي يستطيع تطبيقك الوصول إلى محتوياته من App Platform. انتقل إلى نطاقك في المتصفح بعد انتهاء النشر وحَدِث الصفحة باستمرار حتى تصل إلى الحد RPS_LIMIT، عندها سيظهر المستعرض صفحة الجدار الناري من Cloudflare: ستحصل على الرسالة التالية عند الانتقال إلى علامة تبويب سجلات التشغيل الحالية Runtime Logs في لوحة تحكم App Platform: You are hitting limit your_public_ip يمكنك التأكد من أن الجدار الناري يحظر عنوان IP المحدد في القائمة your_list فقط، عن طريق الدخول إلى نطاقك your_domain من جهاز أخر أو عبر اتصال VPN، ويمكنك حذف عنوان IP من لوحة تحكم Cloudflare. قد يتطلب الحصول على رد من الجدار الناري بضع ثوان بسبب الرد المخزن سابقُا في المتصفح. مبارك! لقد أعددت جدار Cloudflare الناري لحظر عناوين IP عندما يصل المستخدمون إلى حد معدل التراسل عن طريق استدعاء واجهة برمجة تطبيقات Cloudflare. ختامًا تعلمنا في هذا المقال كيفية إنشاء مشروع Node.js ونشره على منصة App Platform من DigitalOcean وتوجيهه للاتصال بنطاقك Cloudflare، وطبقنا إجراء حماية للنطاق من زيادة حد معدل التراسل عن طريق إعداد الجدار الناري في Cloudflare. يمكنك، فيما بعد، تعديل قاعدة الجدار الناري لإظهار تحدٍ JS Challenge أو رمز تحقق كابتشا CAPTCHA بدلاً من حظر المستخدم، اطلع على مستندات Cloudflare لمزيد من التفاصيل حول ذلك. وللحصول على المساعدة والدعم يمكنك إضافة سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة- وبتصرف للمقال How To Build a Rate Limiter With Node.js on App Platform لصاحبه Abel Mathew اقرأ أيضًا بناء تطبيق Node.js باستخدام Docker دمج قاعدة البيانات MongoDB في تطبيقك Node إدارة المستخدمين في تطبيق Node.js باستعمال قواعد بيانات MongoDB ومكتبة Mongoose حفظ بيانات تطبيقات Node.js في قاعدة بيانات MongoDB اختبار الواجهة الخلفية لتطبيقات Node.js عبر مكتبة Jest1 نقطة
-
يمكنك أن تستعمل التابع execute من الكائن engine، على النحو التالي: rows = db.engine.execute("SELECT * FROM userss") كما يمكنك تمرير بعض العوامل والقيم لتفادي ثغرة SQL Injection : result = db.session.execute('SELECT * FROM users WHERE age > :val', {'val': 18}) ويمكنك عمل commit في حالة أردت أن تقوم بتنفيذ جملة تعدل على قاعدة البيانات عليك أن تستخدم التابع execution_options: rows = db.engine.execute("<sql>").execution_options(autocommit=True)) أو يمكنك أن تقوم بإستخدام التابع text: from sqlalchemy import text sql = text('select name from users') result = db.engine.execute(sql) names = [row[0] for row in result] print(names) يمكنك الحصول على مزيد من المعلومات عن SQLAlchemy من خلال هذه المقالة:1 نقطة
-
يوفر فلاسك Flask إمكانية معرفة عنوان IP الخاص بالمستخدم من خلال إستخدام الكائن request، حيث يحتوي على الخاصية remote_addr والتي تشير إلى عنوان IP الخاص بالمستخدم: from flask import Flask, request @app.route('/') def foo(): ip = request.remote_addr return f"your IP is {ip}" إذا قام أي مستخدم بزيارة المسار / سوف يحصل على عنوان IP الخاص به: your IP is 104.16.154.36 وإذا قمت بتشغيل التطبيق من خلال خادم محلي localhost أو إذا كنت تستعمل proxy لتشغيل التطبيق مثل إستخدام nginx سوف تحصل على النتيجة التالية: your IP is 127.0.0.1 لذلك يمكنك إستعمال الكود التالي للحصول على عنوان المستخدم نفسه حتى وإن كنت تستعمل proxy: from flask import Flask, request @app.route('/') def foo(): if request.environ.get('HTTP_X_FORWARDED_FOR') is None: ip = request.environ['REMOTE_ADDR'] else: ip = request.environ['HTTP_X_FORWARDED_FOR'] # if behind a proxy return f"your IP is {ip}"1 نقطة
-
عند زيارتك لأي موقع على الإنترنت فأنت تستعمل منفذ معين (مثل 80 أو 443) وهذه هي المنافذ الإفتراضية لـ http و https ولذلك يقوم المتصفح بإخفاء هذا الجزء، فعلى سبيل المثال عندما تدخل إلى موقع أكاديمية حسوب فأنت تستعمل الرابط التالي: https://academy.hsoub.com ولكن يقوم المتصفح بإضافة منفذ 443 (لأن الموقع يستعمل https)، وبالتالي فيمكنك أن تدخل إلى أكاديمية حسوب عبر الرابط التالي أيضًا: https://academy.hsoub.com:443 وبالتالي فيمكنك أن تقوم بتغير المنفذ الخاص بمشروعك لكي يستخدم المنفذ 80 (أو 443 إذا كنت تستعمل شهادة SSL)، على النحو التالي: app.run(host='0.0.0.0', port=80) أو إذا كنت تستعمل الأمر flask: flask run --host=0.0.0.0 --port=80 بهذا الشكل يمكنك أن تقوم بتشغيل المشروع من خلال http://localhost مباشرة.1 نقطة
-
يمكنك أن تستعمل التابع flask.redirect حيث يقوم هذا التابع بإستقبال الرابط الذي تريد توجيه المستخدم إليه كمعامل أساسي: from flask import Flask,redirect app = Flask(__name__) @app.route('/go') def go(): return redirect("http://www.google.com") كما يستقبل هذا التابع رقم الطلب (redirect status code) كمعامل ثاني باسم code: @app.route('/go') def go(): return redirect("http://www.google.com", code=302) يمكنك الإطلاع على هذه الإجابة هنا لمعرفة الفرق بين أرقام الحالة الخاصة بإعادة التوجية: ما إن أردت أن يتم إعادة توجيه المستخدم إلى مسار معين داخل الموقع، فيمكنك أن تستخدم التابع url_for للحصول على الرابط الكامل لمسار معين، ثم يمكنك أن تستعمل الرابط الذي تم إنشائه هذا في التابع redirect مرة أخرى: from flask import Flask, redirect, url_for @app.route('/go') def go(): return redirect(url_for('foo')) # سيتم توليد مسار localhost:5000/foo @app.route('/foo') def foo(): return 'Hello Foo!' كما يمكنك الإطلاع على هذه المقالة هنا والتي سوف تساعدك في إنشاء موقع لإختصار الروابط بإستخدام فلاسك Flask:1 نقطة
-
نشرح في هذا الفيديو عن نظام إدارة الحزم وفوائد استخدامه. ولماذا نحن بحاجة إلى مثل هذه الأنظمة. نشرح في هذا الدرس كيفية استخدام سطر الأوامر لتنزيل حزم باستخدام مدير الحزم npm. ستتعرف أيضًا على الملف package.json وما هي الفائدة منه. وكذلك الأمر بالنسبة لمجلد node_modules وكيف يمكنك تضمين مكتبة من داخل هذا المجلد في مشروعك.1 نقطة