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

Kate Jeffreys
Kate Jeffreys

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

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

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

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

הקוד המלא מופיע במאמר 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 UI במהלך ה-Codelab הזה.

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

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

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

  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 בערך של המפתח הציבורי.

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

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

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

  1. כדי לראות תצוגה מקדימה של האתר, לוחצים על View App (הצגת האפליקציה) ואז על Fullscreen מסך מלא (מסך מלא).
  1. לוחצים על רישום קובץ השירות בכרטיסייה של האפליקציה. בתיבת הסטטוס אמורה להופיע הודעה דומה לזו:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. בכרטיסיית האפליקציה, לוחצים על הרשמה ל-Push. סביר להניח שהדפדפן או מערכת ההפעלה ישאלו אתכם אם אתם רוצים לאפשר לאתר לשלוח התראות. לוחצים על Allow (או על כל ביטוי מקביל אחר שבו משתמשים בדפדפן או במערכת ההפעלה). בתיבת הסטטוס אמורה להופיע הודעה דומה לזו:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. כדי לחזור לקוד, לוחצים על הצגת מקור בממשק המשתמש של Glitch.
  2. כדי לפתוח את יומני Glitch: לוחצים על Tools (כלים) ואז על Logs (יומנים). האפשרות /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, השרת לא שולח את הודעות ה-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. לוחצים על ביטול ההרשמה ל-Push ואז לוחצים שוב על הרשמה ל-Push. לשם כך יש צורך רק כי, כפי שצוין קודם, Glitch מפעיל מחדש את הפרויקט בכל פעם שעורכים את הקוד, והפרויקט מוגדר למחיקה של מסד הנתונים בעת ההפעלה.
  3. לוחצים על אני רוצה לקבל תזכורת. אמורה להופיע התראה. הכותרת צריכה להיות Hello, Notifications! וגוף ההודעה צריך להיות ID: <ID>, כאשר <ID> הוא מספר אקראי.
  4. פותחים את האפליקציה בדפדפנים או במכשירים אחרים ומנסים להירשם אליהם לקבלת התראות. לאחר מכן לוחצים על הלחצן התראות לכל. אותה התראה אמורה להופיע בכל המכשירים שנרשמתם אליהם (כלומר, המזהה בגוף ההתראה צריך להיות זהה).

השלבים הבאים

  • כדאי לקרוא את המאמר סקירה כללית של התראות כדי לקבל הבנה עמוקה יותר לגבי אופן הפעולה של ההתראות.
  • כדאי לקרוא את המאמר Codelab: בניית לקוח התראות כדי ללמוד איך לפתח לקוח שמבקש הרשאה לשליחת התראות, רושם את המכשיר לקבלת התראות ומשתמש ב-Service Worker כדי לקבל הודעות Push ולהציג את ההודעות כהתראות.