בונים מקצר קישורים משלכם - הפרויקט הקטן שמלמד כמעט הכל על בקאנד¶
מקצר קישורים, כמו bit.ly, נראה כמו פרויקט קטן וחמוד - מכניסים קישור ארוך, מקבלים קישור קצר. אבל מתחת לפני השטח הפשוטים האלה מסתתרים כמעט כל הנושאים המרכזיים בפיתוח צד שרת - מסדי נתונים, ניתוב, הפקת מזהים ייחודיים, וטיפול נכון ב-HTTP. זו הסיבה שהוא פרויקט כל כך שווה לבנות בעצמכם, לא כדי להתחרות ב-bit.ly, אלא כדי להבין את הכלים שמאחוריו.
הרעיון הבסיסי¶
המשתמש שולח קישור ארוך, למשל https://amittech.dev/צד-שרת/מבוא-ל-API-ומתי-להשתמש-בו, והשירות מחזיר לו קישור קצר כמו https://short.ly/aB3xQ. כשמישהו נכנס לקישור הקצר, השרת מפנה (redirect) אותו לכתובת המקורית. זה נשמע פשוט, אבל כל שלב כאן דורש החלטה מחשבתית.
תכנון מסד הנתונים¶
הליבה של הפרויקט היא טבלה אחת פשוטה שממפה קוד קצר לכתובת מקורית:
| שדה | תיאור |
|---|---|
| id | מזהה ראשי |
| short_code | הקוד הקצר, למשל aB3xQ |
| original_url | הכתובת המלאה |
| created_at | מתי נוצר הקישור |
| clicks | מספר כניסות (אופציונלי) |
הנקודה החשובה כאן היא ש-short_code צריך להיות ייחודי (unique) במסד הנתונים - אי אפשר שיהיו שני קישורים שונים עם אותו קוד קצר, כי אז השרת לא יידע לאיזה מהם להפנות. זו דוגמה טובה להבין למה אילוצי unique במסד נתונים הם לא פרט טכני שולי, אלא הגנה על שלמות הנתונים.
איך יוצרים את הקוד הקצר¶
יש כמה גישות, וכדאי להכיר את ההבדל ביניהן.
מזהה רץ מקודד ב-Base62. אם למסד הנתונים יש id רץ (1, 2, 3...), אפשר להמיר אותו למחרוזת קצרה בעזרת קידוד base62 - שילוב של ספרות ואותיות גדולות וקטנות (62 תווים אפשריים). id מספר 125 יכול להפוך למשהו כמו cB. היתרון - קצר ופשוט. החיסרון - קל לנחש קישורים אחרים רק בעזרת שינוי המספר.
מחרוזת אקראית. הדרך הנפוצה יותר בפועל - מייצרים מחרוזת אקראית באורך קבוע, למשל 6 תווים, ובודקים שהיא לא קיימת כבר במסד הנתונים:
function generateCode(length = 6) {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
}
הגישה הזו יותר בטוחה, כי אי אפשר לנחש קישור אחר רק על ידי שינוי מספר, אבל מחייבת אתכם לטפל במקרה הנדיר של התנגשות - שני קישורים שיצא להם באקראי אותו קוד.
הנתיב שיוצר קישור¶
app.post("/shorten", async (req, res) => {
const { url } = req.body;
if (!url) return res.status(400).json({ error: "Missing url" });
const code = generateCode();
await db.links.insert({ short_code: code, original_url: url });
res.json({ shortUrl: `https://short.ly/${code}` });
});
הנתיב שמבצע את ה-redirect¶
זה הלב האמיתי של השירות:
app.get("/:code", async (req, res) => {
const link = await db.links.findOne({ short_code: req.params.code });
if (!link) return res.status(404).send("Link not found");
await db.links.update({ short_code: req.params.code }, { $inc: { clicks: 1 } });
res.redirect(link.original_url);
});
הפונקציה res.redirect שולחת לדפדפן סטטוס 302 (או 301, תלוי בבחירה) עם כתובת חדשה, והדפדפן עצמו עושה את הקפיצה. שווה להבין את ההבדל בין 301 (הפניה קבועה, שהדפדפן זוכר) לבין 302 (הפניה זמנית) - בפרויקט לימודי זה פחות קריטי, אבל זו הבנה שתשרת אתכם גם מחוץ לפרויקט הזה.
תוספת - מעקב קליקים¶
השדה clicks שראיתם למעלה הוא לא רק מספר סתמי - הוא תוספת קטנה שהופכת את הפרויקט למרשים משמעותית. עם עוד קצת עבודה אפשר להוסיף גם תאריך כניסה אחרון, ואפילו טבלה נפרדת שמתעדת כל כניסה בנפרד, מה שמאפשר בהמשך לבנות דשבורד סטטיסטיקות. זה בדיוק סוג הפיצ'ר שמראה בראיון עבודה שאתם חושבים מעבר לדרישה הבסיסית.
למה הפרויקט הזה שווה יותר ממה שנראה¶
מקצר קישורים נוגע כמעט בכל נושא מרכזי בבקאנד - עיצוב סכמת מסד נתונים, טיפול בבקשות HTTP, הפקת מזהים ייחודיים, וטיפול במקרי קצה כמו התנגשויות או קישורים שלא קיימים. זו הסיבה שהוא פרויקט פורטפוליו כל כך טוב - הוא קטן מספיק כדי לסיים אותו בסוף שבוע, אבל עמוק מספיק כדי ללמד המון.
אם אתם רוצים ללמוד לבנות פרויקטים כאלה בצורה מסודרת, כולל תכנון מסד נתונים נכון וטיפול בבקשות ברמה מקצועית, זה בדיוק מה שאנחנו מלמדים בקורס צד שרת המלא.
נתקעתם בדרך? יש קהילה שלמה שמחכה לעזור בדיסקורד שלנו.