Use data from Push in Web Push Notifications - javascript

I am trying to setup a demo for Web Push Notifications using Service Workers. In the service worker, sw.js, I have the following code.
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = 'icon.png';
var tag = 'simple-push-demo-notification-tag';
console.log("Hello!");
self.addEventListener('push', function(event) {
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
This works okay. I wish to receive data that I have sent with my push cURL request like title and more. Is there any way to get all that data here in this waitUntil method?
Any help is highly appreciated.

There are two ways:
Push payload (example https://serviceworke.rs/push-payload.html). This is more complex and is currently only supported in Firefox and chrome v50. You can attach a payload to a push message and access it through the data property of the event (https://developer.mozilla.org/en-US/docs/Web/API/PushMessageData).
The payload needs to be encrypted (https://datatracker.ietf.org/doc/html/draft-thomson-webpush-encryption-01), using a library to take care of the encryption details is highly suggested (e.g. for Node.js https://github.com/marco-c/web-push).
The push event handler in this case would be (assuming the payload is sent as a JSON message):
var data = event.data.json();
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: data.icon,
tag: data.tag,
})
);
A GET request to your server to get the data. For example, assuming that your server returns a JSON response:
event.waitUntil(
fetch('someURL')
.then(response => response.json())
.then(data =>
self.registration.showNotification(data.title, {
body: data.body,
icon: data.icon,
tag: data.tag,
})
)
);

Wait until Chrome 49 comes out: Mar 8th, 2016
Like said in this article: https://www.chromestatus.com/features/5746279325892608, chrome will implement payloads

Related

twilio API not sending the repsonse in json format

I am making an API for sending whatsapp response to client's whatsapp number. I am using twilio as service provider. The problem I am facing is that i am not able to get response in Json. I am following code examples of Twilio
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const client = require('twilio')(accountSid, authToken);
client.messages
.create({
from: 'whatsapp:+14155238886',
body: 'Hello, there!',
to: 'whatsapp:+15005550006'
})
.then(message => console.log(message.sid));
According to API documentation. It should return the response in json or xml. but it returns an error and error is not also in json. Socket Hangs up and then nothing happens. API Reference
API
UPDATE:
After Alan's comment. I have added catch block in my code. But still nothing comes up. The API sends request and then everything hangs. After sometime server hangs and the socket hangs up error is thrown by postman console or from Browser.
Updated Code
client.messages
.create({
from: 'whatsapp:+14155238886',
body: 'Hello, there!',
to: 'whatsapp:+15005550006'
})
.then(message => console.log(message.sid)).catch(e =>
{console.error(e.error); });
I have been looking for JSON response from twilio. I couldn't even find in Twilio Documentation yet.
I recommend you to use try catch block
And in your try block you can add a customized JSON response which has a success response with your user defined header.
Default Twilio response will be like below
[Twilio.Api.V2010.MessageInstance accountSid=ACd7c9b4f84efc802cb7bcf8cbeb86b6b9 sid=SMa4d4976f77e844b8a251fcb14e40a855]
You can explode using space(' ') and change to JSON format
In your catch block you can embed catch error in JSON format
I hope this way you can get JSON response

Why is my Service Worker's push event data/payload null?

I have made multiple attempts to get desktop notifications working in Chrome, but I have not found a single source of documentation that covers a step by step procedure to get desktop notifications to work correctly. Each resource I have come across is either outdated or inconsistent with others.
The problem I am facing is: once the Service Worker receives the push event,
self.addEventListener('push', function (event) {
console.log(event);
event.waitUntil(
self.registration.showNotification(
event.data.title,
{
body: event.data.body,
icon: event.data.icon,
tag: event.data.tag
}));
});
event.data is null. I expect it to have data that I am sending as JSON in a POST request like this:
POST https://fcm.googleapis.com/fcm/send HTTP/1.1
Content-Type: application/json
Authorization: key=<FCM Server Key here>
{
"data": {
"title": "Foo",
"body": "Bar"
},
"to": "<recipient ID here>"
}
The weird thing is the registration script gets a "subscription endpoint" that looks like https://android.googleapis.com/gcm/<recipient ID here>, but I cannot get the POST to go through unless I follow other examples on the web that say to put the recipient ID as the to field in the JSON I am sending.
Of all the examples I have come across, there are multiple URLs that POST calls are being made to:
https://fcm.googleapis.com/fcm/send
https://android.googleapis.com/gcm/send
https://gcm-http.googleapis.com/gcm/send
I have tried all three, with each attempt having the recipient at the end of the API address (like https://fcm.googleapis.com/fcm/send/<recipient ID here> and alternatively in the JSON body. My goal is to get Foo and Bar from the data I am sending into the self.registration.showNotification( method of the service worker.
Why is event.data null? Can anyone point me to a complete guide from start to finish that favors FCM over GCM? Any help would be appreciated.
You may want to check the following statement from the documentation,
A downside to the current implementation of the Push API in Chrome is that you can't send any data with a push message. Nope, nothing. The reason for this is that in a future implementation, payload data will have to be encrypted on your server before it's sent to a push messaging endpoint. This way the endpoint, whatever push provider it is, will not be able to easily view the content of the push message. This also protects against other vulnerabilities like poor validation of HTTPS certificates and man-in-the-middle attacks between your server and the push provider. However, this encryption isn't supported yet, so in the meantime you'll need to perform a fetch to get information needed to populate a notification.
Reading further, you may want to try using fetch() to get data from an API, convert the response to an object and use it to populate notification. This same method was also used in this related SO post.
In addition to that, you may want to also check the response of #Indici Indici in the thread wherein he stated that push event does not contain data values; instead it contains different events which contains information(s). Here is the sample code that was provided as a possible workaround to receive notification in Firebase service-worker in "push" event:
self.addEventListener('push', function(event) {
if (event.data) {
const dataText = event.data.text();
notificationTitle = 'Custom Notification';
notificationOptions.body = 'Message: ' + `${dataText}`;
var title = event.data.notification.title;
var message = event.data.notification.message;
var icon = event.data.notification.icon;
var notificationTag = event.data.notification.tag;
}
}
For receive data need:
self.addEventListener('push', function(event) {
var jsonData = JSON.parse(event.data.text());
// jsonData -> here is you data
const options = {
body: 'set you body',
icon: 'img/apple-icon-120x120.png',
badge: 'img/apple-icon-120x120.png'
};
event.waitUntil(self.registration.showNotification(jsonData.data.title, options));
});

Push Notifications with data on push Event

I am trying to push notifications using GCM,able to show notifications with hard coded data or message on Push Event.But when I tried to push custom messages using data object as Json,Push event is triggering but ,data object always shoeing as null.
Service worker code:sw.js
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
console.log("event data",event.data);//here data is giving as null
var data=event.data.json();
var title= data.title||'No tiltle';
var body= data.message||'no messgae';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
am using third party site(requestmaker.com) to check the notifications.
format am sending like below
URL:https://android.googleapis.com/gcm/send
content-type:application/json
authorization:key=XXXXXXXXXX
below is data format
{
"registration_ids":["someid"],
"data":{"title":"hai",
"body":"hello new message"
}
}
How can i get data in Push Event and in which format i have to send data as request sothat i can get that data on push event(event.data).
You can access the data on notification click trigger event.
self.addEventListener('notificationclick', function(event) {
// here data you access from event using event.notification.data
console.log('On notification click: ', event.notification.tag);
}
From the push notification triggered, the payload data wont be sent across to the service worker. You will have to use browser auth keys while triggering the push notification for the payload to be sent across.
Please refer the documentation below for details.
https://developers.google.com/web/updates/2016/03/web-push-encryption?hl=en

Google Cloud Messaging (GCM) not working with firefox

I have this Service Worker that receives notification well with Chrome,
but it's not receiving with firefox.
the Push listener is not fired at all in firefox (by debugging it),
PS: the service worker is successfully registered, but it's not receiving notification.
what's the problem with my code?
self.addEventListener('install', function (event) {
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', function (event) {
console.log('Activated', event);
});
self.addEventListener('push', function (event) {
event.waitUntil(
fetch('/path', {
credentials: 'include',
method: 'post',
})
.then(function (response) {
return response.json()
.then(function (data) {
return self.registration.showNotification(data.title, {
body: data.body,
icon: '/images/image.png',
});
});
})
.catch(function (error) {
console.error('wrong', error);
})
);
});
Based from this documentation, if you are using the Channel Messaging API to comunicate with the service worker, set up a new message channel (MessageChannel.MessageChannel()) and send port2 over to the service worker by calling Worker.postMessage() on the service worker, in order to open up the communication channel. You should also set up a listener to respond to messages sent back from the service worker.
Make sure that you followed these steps on how to set up the GCM properly. You can also check this related link: GCM Equivalent for Firefox
Hope this helps!
You will need to share your code in the client for registering for push notifications.
With that said, once you register for push notifications, you will receive a subscription with an endpoint. In Firefox that endpoint will never be a GCM url, but a push server provided by Mozilla:
navigator.serviceWorker.ready
.then((reg) => reg.pushManager.subscribe({ userVisibleOnly: true }))
.then((subscription) => {
const endpoint = subscription.endpoint;
// endpoint will have different server values when using this code in Chrome or Firefox.
Here are key notes to be considered:
Are you registering for push notifications correctly in firefox?
Check the url for the endpoint you will need to reach for performing the push notification, is a mozilla server one?
Setup breakpoints just after the push listener to verify that you receive the push.

does service worker request, response from server continuously?

I'm using server send event to display a notification.I have created a service worker and i used EventSource to connect with the server (in my case i used a servlet. ) once i run the project. everything is working fine.
but the contents inside the event execute countiously. I want to know why?
my other question is
once i close the tab. it stops sending notification. service worker is nunning and server also running. but why it stops?
this is my service worker code.
var eventSource = new EventSource("HelloServ");
//MyDiv1 is a custom event
eventSource.addEventListener("MyDiv1",function(event){
console.log("data from down" , event.data);
var title = event.data;
//below notification is displaying continuously. why ?
var notification = new Notification(title, {
icon: 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
body: event.data,
});
notification.onclick = function () {
window.open("http://ageofthecustomer.com/wp-content/uploads/2014/03/success.jpg");
};
console.log("down");
});
this is my servlet code;
response.setContentType("text/event-stream");
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
String upVote = "my up vote";
writer.write("id:1\n");
writer.write("event:myid\n");
writer.write("data: "+ upVote +"\n");
writer.write("data: "+"new data 2\n\n");
System.out.println("servlet "+ i);
writer.flush();
i++;
writer.close();
Service workers have a limited lifetime, you shouldn't use things like web sockets or server sent events.
Push notifications are implemented in a different way.
In your page, you need to subscribe the user for push notifications. The subscription is an endpoint URL (and a set of keys, if you plan to use payloads). Once the user is subscribed, you need to send the subscription information to your server.
The server will send a push notification to the user via a POST request to the endpoint URL.
The service worker will be awakened when a push notification arrives, its 'push' event handler is going to be executed.
A simple example (for more complex ones, take a look at the ServiceWorker Cookbook).
Page
// Register a Service Worker.
navigator.serviceWorker.register('service-worker.js')
.then(function(registration) {
// Use the PushManager to get the user's subscription to the push service.
return registration.pushManager.getSubscription()
.then(function(subscription) {
// If a subscription was found, return it.
if (subscription) {
return subscription;
}
// Otherwise, subscribe the user (userVisibleOnly allows to
// specify that you don't plan to send notifications that
// don't have a visible effect for the user).
return registration.pushManager.subscribe({
userVisibleOnly: true
});
});
}).then(function(subscription) {
// subscription.endpoint is the endpoint URL that you want to
// send to the server (e.g. via the Fetch API or via
// XMLHTTPRequest).
console.log(subscription.endpoint);
// Here's an example with the Fetch API:
fetch('./register', {
method: 'post',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({
endpoint: subscription.endpoint,
}),
});
});
Service Worker
// Register event listener for the 'push' event.
self.addEventListener('push', function(event) {
// Keep the service worker alive until the notification is created.
event.waitUntil(
self.registration.showNotification('Title', {
body: 'Body',
})
);
});
Server
In the server, simply send a POST request to the endpoint URL.
For example, with curl:
curl -X POST [endpointURL]
Or, if you're using Node.js, you can use the web-push library (https://github.com/marco-c/web-push):
var webPush = require('web-push');
webPush.sendNotification(req.query.endpoint, req.query.ttl);
In Java, you could use this class (https://github.com/marco-c/java-web-push) that hides the details of the implementation and the differences between the protocols in the current versions of Firefox and Chrome (differences destined to disappear since Chrome is going to use the Web Push protocol soon).
Here's a "manual" example with a push service that implements the Web Push protocol (currently only works with Firefox):
URL url = new URL(endpointURL);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write("");
writer.flush();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
writer.close();
reader.close();

Categories

Resources