البرمجة

إنشاء خادم Node.js بـHTTP

إنشاء خادم ويب في Node.js باستخدام الوحدة HTTP

في العصر الرقمي الحديث، أصبحت تطبيقات الويب وخدمات الإنترنت العمود الفقري للتواصل والمعلومات والأعمال. ومن بين أدوات تطوير هذه الخدمات، تعتبر منصة Node.js واحدة من أكثر البيئات شعبية بين المطورين لإنشاء تطبيقات خفيفة الوزن وسريعة الاستجابة. من أبرز ميزاتها أنها تعتمد على محرك JavaScript V8 التابع لشركة Google، وتتيح تنفيذ التعليمات البرمجية بلغة JavaScript على جانب الخادم. واحدة من أبسط الطرق لإنشاء خادم ويب في Node.js هي عبر الوحدة المدمجة http. هذه الوحدة تتيح إنشاء خوادم HTTP بدون الحاجة إلى مكتبات خارجية، مما يجعلها نقطة بداية مثالية لتعلّم بناء الخوادم.

يهدف هذا المقال إلى شرح كيفية إنشاء خادم ويب باستخدام وحدة HTTP في Node.js بطريقة موسعة ومفصلة تغطي الجوانب النظرية والعملية، مع توضيح مفاهيم هامة مثل الطلب والاستجابة، التعامل مع المسارات، إدارة البيانات، واستراتيجيات تحسين الأداء.


ما هو Node.js؟

Node.js هو بيئة تشغيل مفتوحة المصدر تعتمد على JavaScript، وتُستخدم لتطوير تطبيقات الشبكة. تميزت هذه البيئة بكونها غير متزامنة وتعتمد على نموذج الحدث (Event-driven) مما يتيح أداءً عالياً واستهلاكاً منخفضاً للموارد. هذا يجعلها مثالية لتطبيقات تحتاج إلى التعامل مع عدد كبير من الاتصالات في وقت واحد، مثل تطبيقات الدردشة، واجهات برمجة التطبيقات (APIs)، وخوادم البث.


الوحدة HTTP في Node.js

الوحدة http هي وحدة مدمجة ضمن حزمة Node.js الأساسية، وتُستخدم لإنشاء خوادم تعتمد على بروتوكول HTTP. يمكن من خلالها إنشاء الخادم، الاستماع للطلبات، وإرسال الاستجابات بطريقة مرنة ومباشرة. لا تحتاج هذه الوحدة إلى التثبيت عبر npm لأنها تأتي مدمجة تلقائيًا في بيئة Node.js.


إنشاء خادم ويب بسيط

الخطوة الأولى لبناء خادم باستخدام الوحدة HTTP هي استيراد الوحدة، ثم استخدام الوظيفة createServer التي تستقبل دالة (Callback) تقوم بالتعامل مع الطلبات والاستجابات.

javascript
const http = require('http'); const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('مرحبًا بك في خادم Node.js!'); }); server.listen(3000, () => { console.log('الخادم يعمل على http://localhost:3000'); });

تحليل الكود:

  • require('http'): استيراد الوحدة HTTP.

  • createServer(): تنشئ خادمًا جديدًا وتُمرر له دالة تقوم بمعالجة الطلب والاستجابة.

  • res.statusCode: تحديد حالة الاستجابة (200 تعني نجاح).

  • res.setHeader: تعيين نوع المحتوى.

  • res.end: إرسال البيانات وإغلاق الاستجابة.

  • server.listen: الاستماع على منفذ معين (3000 في هذا المثال).


التعامل مع المسارات (Routing)

أحد أهم الوظائف في خادم الويب هو التفاعل مع المسارات المختلفة التي يطلبها المستخدم. يمكن تنفيذ ذلك يدويًا عبر التحقق من الخاصية req.url.

javascript
const http = require('http'); const server = http.createServer((req, res) => { if (req.url === '/') { res.writeHead(200, {'Content-Type': 'text/html'}); res.end('

الصفحة الرئيسية

'
); } else if (req.url === '/about') { res.writeHead(200, {'Content-Type': 'text/html'}); res.end('

حول الموقع

'
); } else { res.writeHead(404, {'Content-Type': 'text/html'}); res.end('

404 - الصفحة غير موجودة

'
); } }); server.listen(3000, () => { console.log('الخادم يعمل على http://localhost:3000'); });

هذا المثال يُظهر كيفية التحقق من قيمة req.url لتحديد الصفحة التي يرغب المستخدم في الوصول إليها وإرجاع محتوى مناسب لها.


التعامل مع طرق HTTP (GET, POST, وغيرها)

عند إنشاء تطبيقات ويب، لا يكفي فقط التحقق من المسارات بل يجب أيضًا التمييز بين أنواع الطلبات مثل GET و POST.

javascript
const http = require('http'); const server = http.createServer((req, res) => { if (req.url === '/data' && req.method === 'GET') { res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify({message: 'بيانات GET تم استقبالها'})); } else if (req.url === '/data' && req.method === 'POST') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify({received: body})); }); } else { res.writeHead(404); res.end(); } }); server.listen(3000);

في هذا المثال، الخادم يميز بين الطلبات من نوع GET و POST ويقوم بمعالجة بيانات الطلب POST باستخدام الحدث data و end.


استخدام الجداول لعرض أنواع طرق HTTP ومعانيها

الطريقة الوصف
GET طلب بيانات من الخادم دون التأثير على حالته
POST إرسال بيانات إلى الخادم لإنشاء مورد جديد أو إجراء عملية
PUT تعديل مورد موجود أو إنشاؤه إذا لم يكن موجودًا
DELETE حذف مورد معين من الخادم
PATCH تحديث جزئي لمورد موجود على الخادم
OPTIONS طلب معلومات عن خيارات الاتصال المتاحة للمورد المحدد على الخادم

قراءة الملفات من النظام وإرسالها كاستجابة

يمكن استخدام وحدة fs لقراءة ملفات HTML أو JSON أو صور وإرسالها إلى المستخدم.

javascript
const http = require('http'); const fs = require('fs'); const server = http.createServer((req, res) => { if (req.url === '/') { fs.readFile('index.html', (err, data) => { if (err) { res.writeHead(500); res.end('خطأ في الخادم'); } else { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(data); } }); } }); server.listen(3000);

التعامل مع رؤوس الطلب والاستجابة (Headers)

الرؤوس (Headers) تلعب دورًا كبيرًا في تحديد نوع المحتوى، الترميز، الإذن، وغيرها. على سبيل المثال، لتحديد محتوى JSON:

javascript
res.writeHead(200, {'Content-Type': 'application/json'});

ويمكن قراءة رؤوس الطلب باستخدام req.headers.

javascript
console.log(req.headers['user-agent']);

التعامل مع المعلمات في عنوان URL

يمكن تحليل عنوان URL للحصول على المعلمات باستخدام وحدة url المدمجة:

javascript
const url = require('url'); const server = http.createServer((req, res) => { const parsedUrl = url.parse(req.url, true); const name = parsedUrl.query.name; res.writeHead(200, {'Content-Type': 'text/plain'}); res.end(`مرحبًا ${name}`); });

الأداء والتحسين

مع أن الوحدة http تتيح إمكانيات كبيرة، إلا أنها لا توفر جميع الميزات المتقدمة مثل التوجيه الديناميكي، تحليل الجسم (body parsing)، والتعامل مع ملفات الاستاتيك. لتحسين الأداء والكفاءة، يُنصح في المشاريع الكبيرة باستخدام أطر عمل مثل Express.js، لكنها غير ضرورية في المشاريع البسيطة أو عند التعلم.

كما يجب الانتباه إلى استخدام التخزين المؤقت (Caching)، ضغط الاستجابات (GZIP)، وتقنيات منع الحجب (CORS) لضمان أداء جيد وتجربة مستخدم محسنة.


مقارنة بين الوحدة HTTP و Express.js

العنصر وحدة HTTP Express.js
التوجيه (Routing) يدوي ومحدود متقدم وسهل الاستخدام
التحليل التلقائي للجسم غير متاح مباشرة متاح عبر Middleware مثل body-parser
التعامل مع ملفات ثابتة يجب البرمجة يدويًا موجود جاهز عبر express.static
الأداء أسرع قليلاً في التطبيقات البسيطة أبطأ قليلاً لكن أكثر مرونة
المرونة منخفضة عالية

حالات استخدام واقعية

من التطبيقات التي تستخدم خوادم مبنية على Node.js باستخدام الوحدة HTTP:

  • تطبيقات الـ APIs المصغرة (Microservices)

  • واجهات برمجة التطبيقات للذكاء الاصطناعي أو إنترنت الأشياء

  • الخوادم المؤقتة للاختبار

  • بيئات التعليم والتدريب


الخلاصة التقنية

إنشاء خادم ويب باستخدام الوحدة http في Node.js يُعد خطوة أساسية لكل من يرغب في التعمق في تطوير تطبيقات الويب باستخدام JavaScript على جانب الخادم. مع أن الوحدة أساسية وبسيطة، إلا أنها تقدم تحكمًا كاملاً في كيفية التعامل مع الطلبات والاستجابات، مما يُتيح تعلمًا عميقًا لمبادئ الشبكات ونقل البيانات. وبالرغم من أنها قد تكون أقل كفاءة في إدارة المشاريع الكبيرة مقارنة بإطارات مثل Express.js، فإن فهم بنيتها يُعد قاعدة متينة لأي مطور محترف.


المراجع: