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

קייט ג'פריס
קייט ג'פריס
קייס בסקית
קייס בסקית

בשיעור הזה תלמדו איך לבנות שרת התראות בדחיפה. בסוף ה-Codelab יהיה שרת ש:

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

ה-Codelab הזה נועד לעזור לכם ללמוד באמצעות תרגול, ולא מדבר על מושגים רבים. כדאי לעיין במאמר איך פועלות התראות? כדי לקבל מידע על מושגים בנושא התראות.

קוד הלקוח ב-Codelab הזה כבר הושלם. צריך להטמיע את השרת רק ב-Codelab הזה. במאמר Codelab: Build a Push notification client מוסבר איך מטמיעים לקוח התראות Push.

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

תאימות דפדפן

ידוע ש-Codelab הזה פועל עם השילובים הבאים של מערכת הפעלה ודפדפנים:

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

ידוע ש-Codelab הזה לא פועל עם מערכות ההפעלה הבאות (או השילובים של מערכת ההפעלה והדפדפנים):

  • macOS: Brave, Edge, Safari
  • iOS

מקבץ אפליקציות

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

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

הגדרה

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

עורך הקוד שמופיע מימין להוראות האלו ייקרא ממשק המשתמש של Glitch בכל ה-Codelab הזה.

  1. לוחצים על רמיקס לעריכה כדי שיהיה אפשר לערוך את הפרויקט.

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

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

  1. פותחים את המסוף של Glitch על ידי לחיצה על כלים ולאחר מכן על טרמינל.
  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. סוגרים את המסוף של תקלה.
  1. פתיחת public/index.js.
  2. מחליפים את VAPID_PUBLIC_KEY_VALUE_HERE בערך של המפתח הציבורי.

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

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

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

  1. כדי לראות תצוגה מקדימה של האתר, מקישים על View App ואז על Fullscreen מסך מלא.
  1. לוחצים על Register service worker בכרטיסיית האפליקציה. בתיבת הסטטוס אמורה להופיע הודעה דומה לזו:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. בכרטיסיית האפליקציה לוחצים על הרשמה לדחיפה. סביר להניח שהדפדפן או מערכת ההפעלה ישאלו אתכם אם אתם רוצים לאפשר לאתר לשלוח התראות. לוחצים על Allow (או כל ביטוי מקביל דומה לזה שמוגדר בדפדפן או במערכת ההפעלה). בתיבת הסטטוס אמורה להופיע הודעה שדומה לזו:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. חוזרים לקוד בלחיצה על הצגת מקור בממשק המשתמש של תקלה.
  2. פותחים את יומני גליץ'. לשם כך לוחצים על כלים ואז על יומנים. אמורים להופיע /add-subscription ואחריהם נתונים מסוימים. /add-subscription היא כתובת ה-URL שהלקוח שולח אליה בקשת POST כשהוא רוצה להירשם לקבלת התראות. הנתונים הבאים הם פרטי המינוי של הלקוח שצריך לשמור.
  3. פתיחת server.js.
  4. מעדכנים את הלוגיקה של ה-handler של המסלול /add-subscription באמצעות הקוד הבא:
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. לוחצים על ביטול ההרשמה ל-push.
  3. מעיינים שוב ביומנים של גליץ'. אתם אמורים לראות את /remove-subscription ולאחר מכן פרטי המינוי של הלקוח.
  4. מעדכנים את הלוגיקה של ה-handler של המסלול /remove-subscription באמצעות הקוד הבא:
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);
});

שליחת התראות

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

  1. מעדכנים את הלוגיקה של ה-handler של המסלול /notify-me באמצעות הקוד הבא:
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. מעדכנים את הלוגיקה של ה-handler של המסלול /notify-all באמצעות הקוד הבא:
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 (שליחת התראה לכולם). אתם אמורים לקבל את אותה התראה בכל המכשירים שנרשמתם אליהם (כלומר, המזהה בגוף ההתראה צריך להיות זהה).

השלבים הבאים