वेब पुश लाइब्रेरी से मैसेज भेजना

वेब पर पुश नोटिफ़िकेशन का इस्तेमाल करने में सबसे बड़ी समस्या यह है कि पुश मैसेज को ट्रिगर करना बहुत मुश्किल होता है. पुश मैसेज को ट्रिगर करने के लिए, ऐप्लिकेशन को वेब पुश प्रोटोकॉल का पालन करते हुए, पुश सेवा के लिए एक पोस्ट अनुरोध करना होगा. सभी ब्राउज़र पर पुश का इस्तेमाल करने के लिए, आपको VAPID (जिसे ऐप्लिकेशन सर्वर कुंजियां भी कहा जाता है) का इस्तेमाल करना होगा. इसके लिए, आपको एक हेडर सेट करना होगा. इस हेडर में ऐसी वैल्यू होनी चाहिए जिससे यह साबित हो सके कि आपका ऐप्लिकेशन किसी उपयोगकर्ता को मैसेज भेज सकता है. पुश मैसेज के साथ डेटा भेजने के लिए, डेटा को एन्क्रिप्ट करना होगा. साथ ही, कुछ खास हेडर जोड़ने होंगे, ताकि ब्राउज़र मैसेज को सही तरीके से डिक्रिप्ट कर सके.

पुश को ट्रिगर करने से जुड़ी मुख्य समस्या यह है कि अगर आपको कोई समस्या आती है, तो उस समस्या का पता लगाना मुश्किल हो जाता है. समय के साथ और ज़्यादा ब्राउज़र के साथ काम करने की सुविधा मिलने से, इस प्रोसेस में सुधार हो रहा है. हालांकि, यह आसान नहीं है. इसलिए, हमारा सुझाव है कि आप अपने पुश मैसेज को एन्क्रिप्ट करने, फ़ॉर्मैट करने, और ट्रिगर करने के लिए, लाइब्रेरी का इस्तेमाल करें.

अगर आपको लाइब्रेरी के काम करने के तरीके के बारे में जानना है, तो हम अगले सेक्शन में इस बारे में बताएंगे. फ़िलहाल, हम सदस्यताओं को मैनेज करने और पुश अनुरोध करने के लिए, मौजूदा वेब पुश लाइब्रेरी का इस्तेमाल करने पर ध्यान देंगे.

इस सेक्शन में, हम वेब-पुश Node लाइब्रेरी का इस्तेमाल करेंगे. अन्य भाषाओं में अंतर होगा, लेकिन ये बहुत अलग नहीं होंगी. हम Node का इस्तेमाल कर रहे हैं, क्योंकि यह JavaScript है और इसे पाठक आसानी से ऐक्सेस कर सकते हैं.

हम यह तरीका अपनाएंगे:

  1. हमारे बैकएंड को सदस्यता भेजें और उसे सेव करें.
  2. सेव की गई सदस्यताएं वापस पाएं और पुश मैसेज ट्रिगर करें.

सदस्यताएं सेव करना

डेटाबेस से 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);
   
});
 
});
}

पुश मैसेज भेजना

पुश मैसेज भेजने के लिए, हमें उपयोगकर्ताओं को मैसेज भेजने की प्रोसेस को ट्रिगर करने के लिए, किसी इवेंट की ज़रूरत होती है. एक सामान्य तरीका यह है कि आप एडमिन पेज बनाएं. इसकी मदद से, पुश मैसेज को कॉन्फ़िगर और ट्रिगर किया जा सकता है. हालांकि, लोकल तौर पर चलाने के लिए कोई प्रोग्राम बनाया जा सकता है. इसके अलावा, PushSubscription की सूची को ऐक्सेस करने और पुश मैसेज को ट्रिगर करने के लिए कोड चलाने का कोई दूसरा तरीका भी अपनाया जा सकता है.

हमारे डेमो में एक "एडमिन जैसा" पेज है, जिसकी मदद से पुश ट्रिगर किया जा सकता है. यह सिर्फ़ एक डेमो है, इसलिए यह एक सार्वजनिक पेज है.

हम डेमो को काम करने के लिए, हर चरण के बारे में बताएंगे. ये शुरुआती चरण होंगे, ताकि सभी लोग इनका पालन कर सकें. इनमें वे लोग भी शामिल हैं जो Node के बारे में नहीं जानते.

जब हमने किसी उपयोगकर्ता को सदस्य बनाने के बारे में बात की थी, तब हमने subscribe() विकल्पों में applicationServerKey जोड़ने के बारे में बताया था. बैकएंड पर, हमें इस निजी कुंजी की ज़रूरत होगी.

डेमो में, इन वैल्यू को हमारे Node ऐप्लिकेशन में इस तरह जोड़ा गया है (मुझे पता है कि यह कोड बोरिंग है, लेकिन आपको बताना है कि इसमें कोई जादू नहीं है):

const vapidKeys = {
  publicKey
:
   
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
  privateKey
: 'UUxI4O8-FbRouAevSmBQ6o18hgE4nSG3qwvJTfKc-ls',
};

इसके बाद, हमें अपने नोड सर्वर के लिए web-push मॉड्यूल इंस्टॉल करना होगा:

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:" स्ट्रिंग भी शामिल की है. यह स्ट्रिंग, यूआरएल या mailto वाला ईमेल पता होनी चाहिए. यह जानकारी, पुश ट्रिगर करने के अनुरोध के हिस्से के तौर पर, वेब पुश सेवा को भेजी जाएगी. ऐसा इसलिए किया जाता है, ताकि अगर किसी वेब पुश सेवा को ईमेल भेजने वाले व्यक्ति से संपर्क करना हो, तो उसके पास कुछ जानकारी हो.

इसके बाद, web-push मॉड्यूल इस्तेमाल के लिए तैयार हो जाता है. अगला चरण, पुश मैसेज को ट्रिगर करना है.

डेमो में, पुश मैसेज ट्रिगर करने के लिए, एडमिन पैनल के तौर पर इस्तेमाल किए जाने वाले पैनल का इस्तेमाल किया गया है.

एडमिन पेज का स्क्रीनशॉट.

"पुश मैसेज ट्रिगर करें" बटन पर क्लिक करने से, /api/trigger-push-msg/ पर एक पोस्ट अनुरोध भेजा जाएगा. यह हमारे बैकएंड के लिए पुश मैसेज भेजने का सिग्नल है. इसलिए, हम इस एंडपॉइंट के लिए एक्सप्रेस में रास्ता बनाते हैं:

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(), दी गई सदस्यता पर मैसेज भेजने के लिए वेब-पुश लाइब्रेरी का इस्तेमाल कर सकता है.

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 अब भी मान्य है या नहीं.

पुश सेवा से हुई गड़बड़ी का टाइप जानने के लिए, स्टेटस कोड देखना सबसे सही होता है. गड़बड़ी के मैसेज, पुश सेवाओं के हिसाब से अलग-अलग होते हैं. साथ ही, कुछ मैसेज दूसरों की तुलना में ज़्यादा मददगार होते हैं.

इस उदाहरण में, यह स्टेटस कोड 404 और 410 की जांच करता है. ये 'नहीं मिला' और 'हटाया गया' के लिए एचटीटीपी स्टेटस कोड हैं. अगर हमें इनमें से कोई एक मैसेज मिलता है, तो इसका मतलब है कि सदस्यता की समयसीमा खत्म हो गई है या वह अब मान्य नहीं है. इन स्थितियों में, हमें अपने डेटाबेस से सदस्यताओं को हटाना होगा.

किसी दूसरी गड़बड़ी के मामले में, हम सिर्फ़ throw err करते हैं. इससे, triggerPushMsg() से मिलने वाला प्रॉमिस अस्वीकार हो जाएगा.

हम अगले सेक्शन में, वेब पुश प्रोटोकॉल के बारे में ज़्यादा जानकारी देते समय, कुछ अन्य स्टेटस कोड के बारे में भी बताएंगे.

सदस्यताओं को लूप करने के बाद, हमें 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}'`
   
}
}));
});

हमने इस सुविधा को लागू करने के मुख्य चरणों के बारे में बताया है:

  1. हमारे वेब पेज से सदस्यताओं को हमारे बैक-एंड पर भेजने के लिए एपीआई बनाएं, ताकि वे उन्हें डेटाबेस में सेव कर सकें.
  2. पुश मैसेज भेजने के लिए एपीआई बनाएं. इस मामले में, एपीआई को झूठे एडमिन पैनल से कॉल किया जाता है.
  3. हमारे बैकएंड से सभी सदस्यताओं को वापस पाएं और वेब-पुश लाइब्रेरी में से किसी एक की मदद से, हर सदस्यता को एक मैसेज भेजें.

आपका बैकएंड चाहे Node, PHP, Python वगैरह कुछ भी हो, पुश को लागू करने का तरीका एक ही रहेगा.

अगला सवाल यह है कि ये वेब-पुश लाइब्रेरी हमारे लिए क्या कर रही हैं?

आगे क्या करना है

कोड लैब