does service worker request, response from server continuously? - javascript

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();

Related

Modify POST request body in service worker

I am trying to add a parameter to the body of a POST request in a service worker but the original body is send. I use the following code
let token = '';
self.addEventListener('message', function (event) {
if (event.data && event.data.type === 'SET_TOKEN') {
token = event.data.token;
}
});
self.addEventListener('fetch', function (event) {
const destURL = new URL(event.request.url);
const headers = new Headers(event.request.headers);
if (token) headers.append('Authorization', token);
if (destURL.pathname === '/logout/') {
const promiseChain = event.request.json().then((originalBody) => {
return fetch(event.request.url, {
method: event.request.method,
headers,
// this body is not send to the server but only the original body
body: JSON.stringify(Object.assign(originalBody, { token })),
});
});
event.respondWith(promiseChain);
return;
}
const authReq = new Request(event.request, {
headers,
mode: 'cors',
});
event.respondWith(fetch(authReq));
});
Generally speaking, that should work. Here's a very similar live example that you can run and confirm:
https://glitch.com/edit/#!/materialistic-meadow-rowboat?path=sw.js%3A18%3A7
It will just POST to https://httpbin.org/#/Anything/post_anything, which will in turn echo back the request body and headers.
If your code isn't working, I would suggest using that basic sample as a starting point and slowing customizing it with your own logic. Additionally, it would be a good idea to confirm that your service worker is properly in control of the client page when its makes that request. Using Chrome DevTool's debugger interface, you should be able to put breakpoints in your service worker's fetch event handler and confirm that everything is running as expected.
Taking a step back, you should make sure that your web app isn't coded in such a way that it requires the service worker to be in control in order to go things like expire auth tokens. It's fine to have special logic in the service worker to account for auth, but make sure your code paths work similarly when the service worker doesn't intercept requests, as might be the case when a user force-reloads a web page by holding down the Shift key.

Connecting to websocket channels after successful connection

I have been working on a websocket client application.
I am currently using the ws client library, because it is easy to add some headers (I need this for authentication purposes). I have made a successful connection to the server, but now I need to connect to a specific channel.
Current code:
const WebSocket = require('ws');
var option = {
headers: {
api_key: 'xxxxx'
}
};
// I know this is not a correct url, but I removed it for security reasons
const url = '../websocket/';
const wss = new WebSocket(url, option);
wss.on('open', () => {
console.log("Connection is succesfull");
wss.on('message', message => {
console.log(message);
});
});
When I ran the code it prints the "Connection succesfull", but now I want to connect to a channel called /people. How can I do this.
I have tried several things like:
Changed the url websocket/people.
This doesn't work because it first needs to authenticate to user, before making a connection to a channel
Changed the url to websocket/?people.
I don't get an error, but I also don't get response back when something is send to this channel.
Add this in the open function:
wss.on('/people', message => {
console.log(message);
});
I don't get an error, but I also don't get response back when something is send to this channel.
For the record. I only have access to the documentation and not to the server.

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.

Receive notifications 24/7 via service-worker.js in Chrome

I've been doing push notifications,
when I register the page then test it via curl commands, i received the notification!
However after a while (maybe 1-2 minutes), when I close the tab that the push notifications scope has been registered, then test the notifications again, i cant receive the notifications. This usually happens more in google Chrome in mobiles.
The workaround I did in here is that i need to go to the page of the scoped page first, then when I test the notification again, it now works. Though i cant have this because I need the clients to receive notifications without being on the site all the time.
Here are my push event in service worker
self.addEventListener('push', function(event) {
var SOME_API_ENDPOINT = "https://somewhre.com/push_notification_api/service_worker_endpoint";
event.waitUntil(
fetch(SOME_API_ENDPOINT, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'subscription_id=' + subscriptionId
}).then(function(response) {
return response.json().then(function(data) {
var title = data.notification.title;
var message = data.notification.message;
var icon = base + "assets/images/logo_notification.png";
var notificationTag = data.notification.url;
// var notificationTag = 'https://google.com'; //data.notification.tag;
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
});
})
);
});
How do i make my service workers 24/7 even though i am not in the page of the scope in the registration of SW?
Do I need to use eventListeners 'install', 'activate' and 'fetch'?
Service workers appear to persist but really don't - a new instance spins up in response to events. This will be the case when restarting on mobile to handle a push event, but there are also suggestions that busy service workers should allow multiple instances in parallel.
Your subscriptionId is a global parameter, so it may well be undefined by the time your push event fires.
To fix this you need to retain the subscriptionId in some kind of storage (mayber IndexedDB).
I also think in order for a service worker to persist it needs to have an install event and that event needs to succeed.

Communicating Data Received from Server to Browser in Application based on Vert.x

I am developing an application which will show data on browser received from server using Ver.x. So, I have the following modules:
server.java:
NetServer server = vertxx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
#Override
public void handle(final NetSocket sock) {
System.out.println("A client has connected");
while (true) {
//Sending Message to Client after each five seconds
Thread.sleep(5000);
socket.write("HELLO Server: I am Client: " + i);
}
}
});
client.js:
var client = vertx.createNetClient();
client.connect(1234, 'localhost', function(err, sock) {
sock.dataHandler(function(buffer) {
//Here I received data sent from server. Now, I want to show this data on browser.
});
});
So, I want to show data on browser received on client from server. What can be possibilities for this? How I can show this data on browser gradually as received on client from server? Will I have to use some third component like vertex event bus? I need to append it in some HTML file to show data. Thanks
why you don't use websockets..also you can check the event bus bridge...which allows you send and receive data from a event bus from your browser (basically you use websocket like other eventBus)
http://vertx.io/core_manual_java.html#sockjs-eventbus-bridge
<script src="http://cdn.sockjs.org/sockjs-0.3.4.min.js"></script>
<script src='vertxbus.js'></script>
<script>
var eb = new vertx.EventBus('http://localhost:8080/eventbus');
eb.onopen = function() {
eb.registerHandler('some-address', function(message) {
console.log('received a message: ' + JSON.stringify(message);
});
eb.send('some-address', {name: 'tim', age: 587}); //--------2)
}
</script>
here you have a bus in your server named 'some-addres' then you can send data directly from your browser 2)
and you can register a eventbus and send it data from your server...
this is pretty clear, only remember configure your bus correctly allowing or not which bus are visibles from the browser..
vertx.createSockJSServer(server).bridge(config, noPermitted, noPermitted);

Categories

Resources