אחת מנקודות החולשה בעבודה עם התראות דחיפה לאינטרנט היא שהפעלת הודעת דחיפה היא תהליך מורכב מאוד. כדי להפעיל הודעת דחיפה, האפליקציה צריכה לשלוח בקשת POST לשירות דחיפה בהתאם לפרוטוקול של הודעות דחיפה לאינטרנט. כדי להשתמש בהודעות בדחיפה בכל הדפדפנים, צריך להשתמש ב-VAPID (נקרא גם מפתחות של שרת אפליקציה). בעיקרון, צריך להגדיר כותרת עם ערך שמוכיח שהאפליקציה יכולה לשלוח הודעה למשתמש. כדי לשלוח נתונים באמצעות הודעת דחיפה, צריך להצפין את הנתונים ולהוסיף כותרות ספציפיות כדי שהדפדפן יוכל לפענח את ההודעה בצורה נכונה.
הבעיה העיקרית בהפעלת דחיפה היא שאם נתקלים בבעיה, קשה לאבחן אותה. המצב הזה משתפר עם הזמן ועם תמיכה רחבה יותר בדפדפנים, אבל הוא עדיין רחוק מלהיות פשוט. לכן, מומלץ מאוד להשתמש בספרייה לטיפול בהצפנה, בפורמט ובהפעלה של הודעת ה-push.
אם אתם רוצים לדעת מה הספריות עושות, נרחיב על כך בקטע הבא. בשלב הזה, נתמקד בניהול המינויים ובשימוש בספריית Web Push קיימת כדי לשלוח את בקשות ה-push.
בקטע הזה נשתמש בספריית web-push Node. יהיו הבדלים בין שפות אחרות, אבל הן לא יהיו שונות מדי. אנחנו בוחנים את Node כי הוא מבוסס על JavaScript, וצריך להיות הכי נגיש לקוראים.
נעבור על השלבים הבאים:
- שליחת המינוי לקצה העורפי שלנו ושמירתו.
- אחזור מינויים שנשמרו והפעלת הודעת Push.
שמירת מינויים
שמירת הנתונים של PushSubscription
במסד הנתונים ושליחת שאילתות לגביה משתנה בהתאם לשפה בצד השרת ולבחירת מסד הנתונים, אבל כדאי לראות דוגמה לאופן שבו אפשר לעשות זאת.
בדף האינטרנט לדוגמה, ה-PushSubscription
נשלח לקצה העורפי שלנו באמצעות שליחת בקשת POST פשוטה:
function sendSubscriptionToBackEnd(subscription) {
return fetch('/api/save-subscription/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(subscription),
})
.then(function (response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function (responseData) {
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
לשרת Express בהדגמה שלנו יש מאזין בקשות תואם לנקודת הקצה /api/save-subscription/
:
app.post('/api/save-subscription/', function (req, res) {
במסלול הזה אנחנו מאמתים את המינוי רק כדי לוודא שהבקשה תקינה ולא מלאה באשפה:
const isValidSaveRequest = (req, res) => {
// Check the request body has at least an endpoint.
if (!req.body || !req.body.endpoint) {
// Not a valid subscription.
res.status(400);
res.setHeader('Content-Type', 'application/json');
res.send(
JSON.stringify({
error: {
id: 'no-endpoint',
message: 'Subscription must have an endpoint.',
},
}),
);
return false;
}
return true;
};
אם המינוי תקין, אנחנו צריכים לשמור אותו ולהחזיר תגובת JSON מתאימה:
return saveSubscriptionToDatabase(req.body)
.then(function (subscriptionId) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({data: {success: true}}));
})
.catch(function (err) {
res.status(500);
res.setHeader('Content-Type', 'application/json');
res.send(
JSON.stringify({
error: {
id: 'unable-to-save-subscription',
message:
'The subscription was received but we were unable to save it to our database.',
},
}),
);
});
בדמו הזה נעשה שימוש ב-nedb כדי לאחסן את המינויים. זהו מסד נתונים פשוט שמבוסס על קבצים, אבל אפשר להשתמש בכל מסד נתונים אחר. אנחנו משתמשים באפשרות הזו כי היא לא דורשת הגדרה. בסביבת הייצור, מומלץ להשתמש במשהו אמין יותר. (אני בדרך כלל מעדיף להשתמש ב-MySQL הישן והטוב).
function saveSubscriptionToDatabase(subscription) {
return new Promise(function (resolve, reject) {
db.insert(subscription, function (err, newDoc) {
if (err) {
reject(err);
return;
}
resolve(newDoc._id);
});
});
}
שליחת הודעות דחיפה
כשמדובר בשליחת הודעת דחיפה, בסופו של דבר אנחנו זקוקים לאירוע כלשהו כדי להפעיל את התהליך של שליחת ההודעה למשתמשים. גישה נפוצה היא ליצור דף ניהול חשבון ארגוני שמאפשר להגדיר את הודעת ה-push ולהפעיל אותה. עם זאת, אפשר ליצור תוכנית שתופעל באופן מקומי או כל גישה אחרת שמאפשרת לגשת לרשימה של PushSubscription
ולהריץ את הקוד כדי להפעיל את הודעת ה-push.
בדף הדגמה שלנו יש דף 'דמוי אדמין' שמאפשר להפעיל התראה. מכיוון שמדובר רק בהדגמה, הדף הזה הוא דף ציבורי.
אעבור על כל שלב שנדרש כדי להפעיל את ההדגמה. אלה שלבים ראשונים כדי שכולם יוכלו לעקוב אחריכם, כולל כל מי חדש ב-Node.
כשדיברנו על הרשמה של משתמש, דיברנו על הוספה של applicationServerKey
לאפשרויות של subscribe()
. אנחנו נזדקק למפתח הפרטי הזה בקצה העורפי.
בהדגמה, הערכים האלה מתווספים לאפליקציית Node למשל (קוד משעמם לי, אבל חשוב לדעת שאין קסם):
const vapidKeys = {
publicKey:
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
privateKey: 'UUxI4O8-FbRouAevSmBQ6o18hgE4nSG3qwvJTfKc-ls',
};
בשלב הבא צריך להתקין את המודול web-push
בשרת Node:
npm install web-push --save
לאחר מכן, בסקריפט Node שלנו אנחנו דורשים את המודול web-push
כך:
const webpush = require('web-push');
עכשיו אפשר להתחיל להשתמש במודול web-push
. קודם כול צריך לספר למודול web-push
על המפתחות של שרת האפליקציה. (חשוב לזכור שהם נקראים גם מפתחות VAPID כי זהו שם המפרט).
const vapidKeys = {
publicKey:
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
privateKey: 'UUxI4O8-FbRouAevSmBQ6o18hgE4nSG3qwvJTfKc-ls',
};
webpush.setVapidDetails(
'mailto:web-push-book@gauntface.com',
vapidKeys.publicKey,
vapidKeys.privateKey,
);
שימו לב שצירפנו גם מחרוזת מסוג 'mailto:'. המחרוזת הזו צריכה להיות כתובת URL או כתובת אימייל מסוג mailto. למעשה, פרט המידע הזה יישלח לשירות ההתראות באינטרנט כחלק מהבקשה להפעלת התראה. הסיבה לכך היא שאם שירות של התראות דחיפה לאינטרנט יצטרך ליצור קשר עם השולח, יהיה לו מידע מסוים שיעזור לו לעשות זאת.
עכשיו המודול web-push
מוכן לשימוש. השלב הבא הוא להפעיל הודעת דחיפה.
ההדגמה משתמשת בחלונית הניהול לכאורה כדי להפעיל הודעות בדחיפה.
לחיצה על הלחצן 'הפעלת הודעת דחיפה' תיצור בקשת POST אל /api/trigger-push-msg/
, שהוא האות לקצה העורפי שלנו לשלוח הודעות דחיפה. לכן, אנחנו יוצרים את המסלול ב-Express לנקודת הקצה הזו:
app.post('/api/trigger-push-msg/', function (req, res) {
כשהבקשה הזו מתקבלת, אנחנו אוספים את המינויים מהמסד ופועלים להפעלת הודעת דחיפה לכל אחד מהם.
return getSubscriptionsFromDatabase().then(function (subscriptions) {
let promiseChain = Promise.resolve();
for (let i = 0; i < subscriptions.length; i++) {
const subscription = subscriptions[i];
promiseChain = promiseChain.then(() => {
return triggerPushMsg(subscription, dataToSend);
});
}
return promiseChain;
});
לאחר מכן, הפונקציה triggerPushMsg()
יכולה להשתמש בספריית ה-web-push כדי לשלוח הודעה למינוי שסופק.
const triggerPushMsg = function (subscription, dataToSend) {
return webpush.sendNotification(subscription, dataToSend).catch((err) => {
if (err.statusCode === 404 || err.statusCode === 410) {
console.log('Subscription has expired or is no longer valid: ', err);
return deleteSubscriptionFromDatabase(subscription._id);
} else {
throw err;
}
});
};
הקריאה אל webpush.sendNotification()
תחזיר הבטחה. אם ההודעה נשלחה בהצלחה, ההתחייבות תבוטל ולא נצטרך לעשות שום דבר. אם ההתחייבות תידחה, תצטרכו לבדוק את השגיאה כדי לדעת אם הערך של PushSubscription
עדיין תקף.
כדי לקבוע את סוג השגיאה משירות דחיפה, עדיף לבדוק את קוד הסטטוס. הודעות השגיאה משתנות בין שירותי ה-push, וחלקן מועילות יותר מאחרות.
בדוגמה הזו, הבדיקה היא על קודי הסטטוס 404
ו-410
, שהם קודי הסטטוס של HTTP עבור 'לא נמצא' ו'נעלם'. אם נקבל אחת מההודעות האלה, המשמעות היא שתוקף המינוי פג או שהוא לא תקף יותר. בתרחישים כאלה, אנחנו צריכים להסיר את המינויים ממסד הנתונים שלנו.
במקרה של שגיאה אחרת, פשוט throw err
, וכך ההבטחה שתוחזר על ידי triggerPushMsg()
תידחה.
נתייחס לחלק מקודי הסטטוס האחרים בקטע הבא, כשנבחן את פרוטוקול ה-Web Push בפירוט רב יותר.
אחרי שמבצעים לולאה על המינויים, צריך להחזיר תשובה בפורמט JSON.
.then(() => {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ data: { success: true } }));
})
.catch(function(err) {
res.status(500);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({
error: {
id: 'unable-to-send-messages',
message: `We were unable to send messages to all subscriptions : ` +
`'${err.message}'`
}
}));
});
עברנו על שלבי ההטמעה העיקריים:
- יוצרים ממשק API לשליחת מינויים מדף האינטרנט שלנו לקצה העורפי שלנו, כדי שהוא יוכל לשמור אותם במסד נתונים.
- יוצרים ממשק API שיפעיל שליחה של הודעות Push (במקרה הזה, ממשק API שנקרא מחלונית הניהול לכאורה).
- מאחזרים את כל המינויים מהקצה העורפי ושולחים הודעה לכל מינוי באמצעות אחת מספריות ה-web-push.
ללא קשר לקצה העורפי (Node, PHP, Python וכו'), השלבים להטמעת Push יהיו זהים.
בשלב הבא, נסביר מה בדיוק הספריות האלה של דחיפה לאינטרנט עושות בשבילנו.
לאן ממשיכים
- סקירה כללית בנושא התראות מאפליקציית אינטרנט
- איך פועלת התכונה 'התראות דחיפה'
- הרשמה של משתמש
- חוויית המשתמש של ההרשאות
- שליחת הודעות באמצעות ספריות Web Push
- פרוטוקול דחיפה באינטרנט
- טיפול באירועי Push
- הצגת התראה
- אופן הפעולה של ההתראות
- דפוסי התראות נפוצים
- שאלות נפוצות בנושא התראות בדחיפה
- בעיות נפוצות ודיווח על באגים