الرئيسيةمن أناالدوراتالمدونةسوق الأوامرالمناهج والباقاتالشركاء

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • سوق الأوامر
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
How To Make It

اعمل URL Shortener بـ Node.js: من رابط طويل لكود قصير في 60 سطر

مبتدئ19 يوليو 20266 دقائق قراءة
اعمل URL Shortener بـ Node.js: من رابط طويل لكود قصير في 60 سطر

هذا المقال لمستوى مبتدئ (مع لمسات للمتوسط). لو عارف تكتب دالة في JavaScript وتشغّل أمر في الطرفية، انت جاهز تمشي مع كل سطر هنا خطوة بخطوة.

تقدر تبني خدمة تختصر الروابط زي bit.ly بنفسك في أقل من 60 سطر Node.js، وتفهم بالظبط اللي بيحصل ورا كل رابط قصير بتضغط عليه. في نهاية المقال هيبقى عندك سيرفر شغّال بياخد رابط طويل ويرجّعلك كود من 6 حروف، ولما حد يفتح الكود ده بيوصّله للرابط الأصلي ويعدّ النقرات.

بناء مختصر روابط من الصفر بـ Node.js

المشكلة باختصار

الروابط الطويلة وحشة. رابط منتج فيه 90 حرف مع ?ref= وutm_source مش بيتكتب في رسالة، وبيتقطع في تويتر، وصعب حد يقوله لحد. مختصر الروابط بيحل ده بفكرة بسيطة: يخزّن الرابط الطويل، ويديك مفتاح قصير يرجّعك له. الجميل إن المنطق ورا الموضوع أبسط بكتير مما تتخيّل.

الفكرة بمثال بسيط قبل الكود

تخيّل إنك اتنقلت من بيتك القديم. رحت مكتب البريد وقلتلهم: "أي جواب يوصل على العنوان القديم، حوّلوه على عنواني الجديد". من ساعتها أي حد يبعتلك على العنوان القديم، البريد بيحوّله تلقائيًا من غير ما المُرسِل يعرف عنوانك الجديد أصلًا.

ده بالظبط اللي بيعمله رد اسمه 301 Redirect. علميًا: الـ 301 كود حالة في بروتوكول HTTP معناه "المورد اتنقل بشكل دائم". السيرفر بيرد بالكود ده ومعاه ترويسة Location فيها العنوان الجديد، فالمتصفح يطلب العنوان الجديد لوحده. والأهم: المتصفحات بتخزّن الـ 301 في الكاش، فالضغطة الجاية على نفس الرابط ممكن متوصلش لسيرفرك خالص.

فاضل حاجة واحدة: إزاي نولّد الكود القصير نفسه؟ تخيّله زي لوحة العربية. بدل ما تحفظ رقم الشاسيه الطويل، الدولة بتديك لوحة قصيرة تشاور على العربية. إحنا هنعمل نفس الحاجة: كل رابط بياخد رقم تسلسلي (1، 2، 3...)، وإحنا بنحوّل الرقم ده لأقصر نص ممكن بطريقة اسمها Base62.

علميًا: Base62 بيمثّل الرقم باستخدام 62 رمز (الأرقام 0-9، والحروف الصغيرة a-z، والكبيرة A-Z). كل حرف بتضيفه بيضرب السعة في 62. يعني 6 حروف بس بتديك 62^6 = 56.8 مليار رابط مختلف. ده أكتر من كفاية لأي مشروع عربي عادي.

الخطوات: من صفر لسيرفر شغّال

  1. جهّز المشروع. افتح مجلد فاضي وشغّل الأوامر دي. النتيجة المتوقّعة: مجلد فيه package.json والمكتبتين.
Bash
mkdir short && cd short
npm init -y
npm install express better-sqlite3
  1. افتح قاعدة البيانات واعمل الجدول. إحنا هنستخدم SQLite لأنه ملف واحد على القرص، بدون سيرفر منفصل. النتيجة: جدول links جاهز لتخزين الروابط.
JavaScript
const express = require('express');
const Database = require('better-sqlite3');

const app = express();
app.use(express.json());

const db = new Database('links.db');
db.exec(`CREATE TABLE IF NOT EXISTS links (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  long_url TEXT NOT NULL,
  clicks INTEGER DEFAULT 0,
  created_at TEXT DEFAULT (datetime('now'))
)`);
  1. اكتب دالتين للتحويل بين الرقم والكود. الأولى بتحوّل الرقم لكود Base62، والتانية بترجّعه. النتيجة: toBase62(1000000) بيرجّع '4c92'.
JavaScript
const ALPHABET =
  '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

function toBase62(n) {
  if (n === 0) return '0';
  let s = '';
  while (n > 0) {
    s = ALPHABET[n % 62] + s;
    n = Math.floor(n / 62);
  }
  return s;
}

function fromBase62(s) {
  return [...s].reduce((acc, c) => acc * 62 + ALPHABET.indexOf(c), 0);
}
  1. اعمل نقطة إنشاء الرابط القصير. بتاخد رابط طويل، تتحقق إنه صالح، تخزّنه، وترجّع الكود. النتيجة: طلب POST بيرجّعلك { "short": "http://localhost:3000/1", "code": "1" }.
JavaScript
app.post('/shorten', (req, res) => {
  const { url } = req.body;
  if (!/^https?:\/\//.test(url || '')) {
    return res.status(400).json({ error: 'رابط غير صالح' });
  }
  const info = db.prepare('INSERT INTO links (long_url) VALUES (?)').run(url);
  const code = toBase62(info.lastInsertRowid);
  res.json({ short: `http://localhost:3000/${code}`, code });
});
  1. اعمل نقطة إعادة التوجيه. دي قلب الخدمة: بتاخد الكود، تحوّله لرقم، تجيب الرابط، تزوّد النقرات، وتعمل 301. النتيجة: فتح الرابط القصير بيوصّلك للأصلي فورًا.
JavaScript
app.get('/:code', (req, res) => {
  const id = fromBase62(req.params.code);
  const row = db.prepare('SELECT long_url FROM links WHERE id = ?').get(id);
  if (!row) return res.status(404).send('الرابط غير موجود');
  db.prepare('UPDATE links SET clicks = clicks + 1 WHERE id = ?').run(id);
  res.redirect(301, row.long_url);
});

app.listen(3000, () => console.log('http://localhost:3000'));

خلّي بالك من نقطة مهمة في الكود ده: إحنا بنجيب الرابط بـ WHERE id = ? على المفتاح الأساسي. ده بيخلّي البحث في خانة مفهرسة، فبياخد أقل من مللي ثانية حتى لو عندك عشرات الآلاف من الروابط، مش بيمر على كل صف.

مخطط تسلسلي يوضح دورة حياة إعادة توجيه 301 بين المتصفح وخادم مختصر الروابط وقاعدة البيانات عند فتح رابط قصير

التحقق من أنه يعمل

شغّل السيرفر بـ node app.js، وبعدين جرّب من طرفية تانية:

Bash
# أنشئ رابط قصير
curl -X POST http://localhost:3000/shorten \
  -H "Content-Type: application/json" \
  -d '{"url":"https://ahmedhaies.com/some/very/long/path?ref=blog"}'

# الرد المتوقّع
# {"short":"http://localhost:3000/1","code":"1"}

# افتح الرابط القصير وشوف الـ 301 والـ Location
curl -i http://localhost:3000/1

لو شفت في رد الأمر الأخير سطر HTTP/1.1 301 Moved Permanently وسطر Location: فيه رابطك الطويل، يبقى كل حاجة شغّالة. افتح الكود في المتصفح هيوديك على الصفحة الأصلية على طول.

الـ trade-offs اللي لازم تعرفها

كل قرار هنا معاه ثمن، وده اللي بيفرق المشروع التعليمي عن الجاهز للإنتاج:

  • 301 مقابل 302. الـ 301 بيتخزّن في كاش المتصفح، فبتكسب سرعة وتقليل حِمل على سيرفرك. بتخسر إن عدّاد النقرات مش هيزيد بعد أول ضغطة (المتصفح مش بيرجعلك)، وكمان مش هتقدر تغيّر وجهة الرابط بعدين بسهولة لأنها اتخزّنت. لو محتاج إحصائيات دقيقة أو مرونة في تغيير الوجهة، استخدم res.redirect(302, ...) واقبل إن كل ضغطة هتضرب سيرفرك.
  • الكود التسلسلي مكشوف. بما إن الكود جاي من رقم بيزيد 1، 2، 3، أي حد يقدر يخمّن الأكواد ويسحب كل روابطك بالترتيب. بتكسب أكواد قصيرة ومرتبة، بتخسر الخصوصية. لو ده مهم، ولّد كود عشوائي أو ابدأ العدّاد من رقم كبير.
  • SQLite متزامن (synchronous). better-sqlite3 سريع وبسيط جدًا على سيرفر واحد، بس هو بيقفل أثناء الكتابة. الافتراض هنا إن حِملك أقل من بضعة آلاف طلب في الثانية على عقدة واحدة. فوق كده فكّر في PostgreSQL و connection pool.

متى لا تستخدم هذه الطريقة

متبنيش مختصر روابط بنفسك لو محتاجه على نطاق ضخم متعدد المناطق، أو محتاج لوحة تحليلات جاهزة، أو مميزات فرق ومشاركة. في الحالات دي خدمات زي Bitly أو Dub أو Rebrandly هتوفّرلك شهور شغل. الطريقة دي مثالية للتعلّم، وللأدوات الداخلية، ولما تحب تملك بياناتك بالكامل على دومين بتاعك، وده بالظبط اللي بيبحث عنه ناس كتير.

الخطوة التالية

غيّر سطر واحد بس: خلّي res.redirect(301, ...) يبقى res.redirect(302, ...)، وبعدين افتح نفس الرابط القصير 3 مرات وشوف عمود clicks في قاعدة البيانات بيزيد ولا لأ. الفرق اللي هتشوفه بين الحالتين هيثبّتلك فكرة الكاش والـ 301 بشكل عملي أكتر من أي شرح.

مصادر

  • MDN Web Docs — 301 Moved Permanently (شرح كود 301 وسلوك الكاش).
  • RFC 9110 — HTTP Semantics: Redirection 3xx (تعريف 301 و302 رسميًا).
  • Express — توثيق res.redirect.
  • better-sqlite3 — توثيق الـ API (الاستعلامات المتزامنة و prepared statements).
  • Node.js — توثيق وحدة http.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة