Codelab: יצירת שרת התראות

Kate Jeffreys
Kate Jeffreys

בשיעור ה-Codelab הזה תלמדו איך ליצור שרת התראות דחיפה, שלב אחר שלב. בסוף הקודלאב יהיה לכם שרת:

  • מעקב אחרי מינויים להתראות דחיפה (כלומר, השרת יוצר רשומה חדשה במסד הנתונים כשלקוח מאשר קבלת התראות דחיפה, ומחק רשומה קיימת במסד הנתונים כשלקוח מבטל את ההסכמה)
  • שליחת הודעת Push ללקוח יחיד
  • שליחת הודעת Push לכל הלקוחות שנרשמו

סדנת הקוד הזו מתמקדת בלמידה מעשית, ולא מתייחסת הרבה למושגים. במאמר איך פועלות התראות מוסבר על המושגים הקשורים להתראות.

קוד הלקוח של סדנת הקוד הזו כבר הושלם. בקודלאב הזה נטמיע רק את השרת. במדריך Codelab: פיתוח לקוח להתראות מוסבר איך להטמיע לקוח של התראות.

ב-push-notifications-server-codelab-complete (מקור) תוכלו לראות את הקוד המלא.

תאימות דפדפן

ידוע שהקודלאב הזה פועל עם השילובים הבאים של מערכת הפעלה ודפדפן:

  • Windows: ‏ Chrome, ‏ Edge
  • macOS: ‏ Chrome, ‏ Firefox
  • Android: ‏ Chrome, ‏ Firefox

ידוע שהקודלאב הזה לא פועל עם מערכות ההפעלה הבאות (או עם שילובים של מערכת הפעלה ודפדפן):

  • macOS: ‏ Brave, ‏ Edge, ‏ Safari
  • iOS

סטאק האפליקציות

  • השרת מבוסס על Express.js.
  • ספריית Node.js‏ web-push מטפלת בכל הלוגיקה של התראות ה-push.
  • נתוני המינוי נכתבים בקובץ JSON באמצעות lowdb.

אתם לא חייבים להשתמש באף אחת מהטכנולוגיות האלה כדי להטמיע התראות דחיפה. בחרנו בטכנולוגיות האלה כי הן מספקות חוויית codelab מהימנה.

הגדרה

קבלת עותק של הקוד שניתן לעריכה

עורך הקוד שמופיע משמאל להוראות האלה יקרא Glitch UI במהלך הקודלאב הזה.

  1. לוחצים על Remix to Edit כדי לאפשר עריכה של הפרויקט.

מגדירים אימות

כדי להפעיל התראות דחיפה, צריך להגדיר את השרת והלקוח באמצעות מפתחות אימות. הסיבה לכך מפורטת במאמר חתימה על בקשות לפרוטוקול של התראות דחיפה באינטרנט.

  1. כדי לפתוח את הטרמינל של Glitch, לוחצים על Tools ואז על Terminal.
  2. מריצים את הפקודה npx web-push generate-vapid-keys בטרמינל. מעתיקים את הערכים של המפתח הפרטי והמפתח הציבורי.
  3. פותחים את .env ומעדכנים את VAPID_PUBLIC_KEY ואת VAPID_PRIVATE_KEY. מגדירים את VAPID_SUBJECT לערך mailto:test@test.test. כל הערכים האלה צריכים להיות מוקפים במירכאות כפולות. אחרי ביצוע העדכונים, קובץ .env אמור להיראות כך:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. סוגרים את הטרמינל של Glitch.
  1. פתיחת public/index.js.
  2. מחליפים את VAPID_PUBLIC_KEY_VALUE_HERE בערך של המפתח הציבורי.

ניהול מינויים

הלקוח מטפל ברוב תהליך המינוי. הפעולות העיקריות שהשרת צריך לבצע הן לשמור מינויים חדשים להתראות בדחיפה ולמחוק מינויים ישנים. ההרשמות האלה מאפשרות לכם לשלוח הודעות ללקוחות בעתיד. למידע נוסף על תהליך ההרשמה, ראו הרשמה של הלקוח להתראות Push.

שמירת פרטי המינוי החדש

  1. כדי לראות תצוגה מקדימה של האתר, מקישים על הצגת האפליקציה. לאחר מכן מקישים על מסך מלא מסך מלא.
  1. לוחצים על Register service worker בכרטיסייה של האפליקציה. בתיבה של הסטטוס אמורה להופיע הודעה דומה לזו:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. בכרטיסייה של האפליקציה, לוחצים על Subscribe to push (הרשמה לעדכוני Push). סביר להניח שהדפדפן או מערכת ההפעלה שלכם יציג לכם שאלה אם אתם רוצים לאפשר לאתר לשלוח לכם התראות. לוחצים על אישור (או על הביטוי המקביל שמופיע בדפדפן או במערכת ההפעלה). בתיבה 'סטטוס' אמורה להופיע הודעה דומה לזו:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. כדי לחזור לקוד, לוחצים על View Source (הצגת המקור) בממשק המשתמש של Glitch.
  2. כדי לפתוח את יומני Glitch, לוחצים על כלים ואז על יומנים. אמורה להופיע הערך /add-subscription ואחריו נתונים מסוימים. /add-subscription היא כתובת ה-URL שאליה הלקוח שולח בקשת POST כשהוא רוצה להירשם לקבלת התראות דחיפה. הנתונים הבאים הם פרטי המינוי של הלקוח שצריך לשמור.
  3. פתיחת server.js.
  4. מעדכנים את הלוגיקה של /add-subscription route handler באמצעות הקוד הבא:
app.post('/add-subscription', (request, response) => {
  console.log('/add-subscription');
  console.log(request.body);
  console.log(`Subscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .push(request.body)
    .write();
  response.sendStatus(200);
});

מחיקת פרטי מינויים ישנים

  1. חוזרים לכרטיסיית האפליקציה.
  2. לוחצים על ביטול ההרשמה לקבלת התראות.
  3. בודקים שוב את יומני הבאגים. הכתובת /remove-subscription צריכה להופיע לצד פרטי המינוי של הלקוח.
  4. מעדכנים את הלוגיקה של /remove-subscription route handler באמצעות הקוד הבא:
app.post('/remove-subscription', (request, response) => {
  console.log('/remove-subscription');
  console.log(request.body);
  console.log(`Unsubscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .remove({endpoint: request.body.endpoint})
    .write();
  response.sendStatus(200);
});

שליחת התראות

כפי שמוסבר בקטע שליחת הודעת דחיפה, השרת לא שולח את הודעות הדחיפה ישירות ללקוחות. במקום זאת, הוא מסתמך על שירות דחיפה כדי לעשות זאת. בעיקרון, השרת רק מתחיל את התהליך של שליחת הודעות בדחיפה ללקוחות על ידי שליחת בקשות לשירותי אינטרנט (בקשות לפרוטוקול דחיפה באינטרנט) לשירות אינטרנט (שירות הדחיפה) שבבעלות ספק הדפדפן שבו המשתמש משתמש.

  1. מעדכנים את הלוגיקה של /notify-me route handler באמצעות הקוד הבא:
app.post('/notify-me', (request, response) => {
  console.log('/notify-me');
  console.log(request.body);
  console.log(`Notifying ${request.body.endpoint}`);
  const subscription = 
      db.get('subscriptions').find({endpoint: request.body.endpoint}).value();
  sendNotifications([subscription]);
  response.sendStatus(200);
});
  1. מעדכנים את הפונקציה sendNotifications() באמצעות הקוד הבא:
function sendNotifications(subscriptions) {
  // TODO
  // Create the notification content.
  const notification = JSON.stringify({
    title: "Hello, Notifications!",
    options: {
      body: `ID: ${Math.floor(Math.random() * 100)}`
    }
  });
  // Customize how the push service should attempt to deliver the push message.
  // And provide authentication information.
  const options = {
    TTL: 10000,
    vapidDetails: vapidDetails
  };
  // Send a push message to each client specified in the subscriptions array.
  subscriptions.forEach(subscription => {
    const endpoint = subscription.endpoint;
    const id = endpoint.substr((endpoint.length - 8), endpoint.length);
    webpush.sendNotification(subscription, notification, options)
      .then(result => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Result: ${result.statusCode}`);
      })
      .catch(error => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Error: ${error} `);
      });
  });
}
  1. מעדכנים את הלוגיקה של /notify-all route handler באמצעות הקוד הבא:
app.post('/notify-all', (request, response) => {
  console.log('/notify-all');
  response.sendStatus(200);
  console.log('Notifying all subscribers');
  const subscriptions =
      db.get('subscriptions').cloneDeep().value();
  if (subscriptions.length > 0) {
    sendNotifications(subscriptions);
    response.sendStatus(200);
  } else {
    response.sendStatus(409);
  }
});
  1. חוזרים לכרטיסיית האפליקציה.
  2. לוחצים על ביטול ההרשמה לקבלת התראות ואז לוחצים שוב על הרשמה לקבלת התראות. צריך לעשות זאת כי, כפי שצוין קודם, Glitch מפעיל מחדש את הפרויקט בכל פעם שעורכים את הקוד, והפרויקט מוגדר למחוק את מסד הנתונים בזמן ההפעלה.
  3. לוחצים על אני רוצה לקבל התראות. אמורה להגיע התראה. השם צריך להיות Hello, Notifications! והתוכן צריך להיות ID: <ID>, כאשר <ID> הוא מספר אקראי.
  4. פותחים את האפליקציה בדפדפנים או במכשירים אחרים ומנסים להירשם לקבלת התראות בדפדפנים או במכשירים האלה, ואז לוחצים על הלחצן Notify all. אתם אמורים לקבל את אותה התראה בכל המכשירים שנרשמו לעדכונים (כלומר, המזהה בגוף ההתראה צריך להיות זהה).

השלבים הבאים