I'm using service worker for push notifications, following this article. Everything is working with Chrome but with Firefox (v.44.0.2) I have a weird issue.
On successful login to my app, I register the service worker which does nothing but waiting for push events; I see that is correctly registered (from some logging and from about:serviceworkers). Now, if I refresh the page (CTRL+R) all my POST have CORS issues (missing Access-Control-Allow-Origin header) due to this service worker and the user is redirected to login page; from here on all POSTs do not work for the same reason.
Conversely, if I login, unregister the service worker and then refresh, there are no problems at all. Any idea of what's going on? Again my service worker just handles push events, no caching no other processing done and it perfectly works on Chrome.
Here's my service worker code ( SOME_API_URL points to a real API which is not needed for testing purpose cause the issue happens after the service worker registers, no push events needed)
self.addEventListener('push', function(event) {
// Since there is no payload data with the first version
// of push messages, we'll grab some data from
// an API and use it to populate a notification
event.waitUntil(
fetch(SOME_API_URL).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.error('The API returned an error.', data.error);
throw new Error();
}
var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
var notificationTag = data.notification.tag;
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
});
}).catch(function(err) {
console.error('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this push message';
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
tag: notificationTag
});
})
);
});
self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event.notification.tag);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: 'window'
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWindow('/');
}
})
);
});
Firefox 44 has bug 1243453, which causes the Origin header of cross-origin requests to get dropped if the service worker doesn't listen for fetch events.
The bug has been fixed in Firefox 45, which will be released the week of March 8, 2016 (next week, as of the time of this writing). In the meantime, and for users who don't immediately upgrade to the latest Firefox release, you can work around the problem by adding this code to the service worker:
addEventListener('fetch', function(evt) {
evt.respondWith(fetch(evt.request));
});
Related
I want to build an email verification. After the user registers, the user gets an email and clicks on it for verification purposes. The email-link invokes a netlify lambda function (api end point). Inside the link is a jwt token, which I decode on the backend. I used
window.location.href
for it and sliced the part I needed and decoded it. On localhost, it works fine, however, if I deploy it to netlify, I get an
window is undefined
error. I read that you have to check for
typeof window !== 'undefined'
However, if I add that to my lambda function I don't get any console.log statements.
exports.handler = async (event, context, callback) => {
if (typeof window !== 'undefined') {
let url = window.location.href
let index = url.indexOf("=");
let token = url.slice(index+1)
console.log(token, 'token here')
const decoded = jwt.verify(token, process.env.SECRET);
console.log('confirm registration route triggered',decoded)
if (decoded) {
const { email } = decoded;
console.log(decoded, 'decoded here')
User.findOneAndUpdate({email: email}, {verified: true },(...e)=>{
console.log(e)
});
} else {
console.log('could not update user')
//redirect user to page with message about email confirmation link expiration
//and proposal to register again
}
console.log('confirm registration got invoked')
}
return {
statusCode: 400,
body: "Oops"
}
};
I read that the function first runs on the server when deployed and afterwards on the client. Seems like it does not run on my client, as I invoke the api-endpoint directly? I'm quite a beginner when it comes to API-Endpoints, thanks for reading!
In case you have the same issue when deploying to netlify, you have to run
event.queryStringParameters
which gives you access to the query parts of your url.
Most of the time the messages are passed normally, but a couple messages in particular arent recieved until the recieving client sends a message. This happens everytime for specific methods/messages, but not at all for others.
Example: user1 sends a message, user2 then sends a message to receive message from user1.
Related Material
Deleted question: websocket receives previous message only when new message is sent
Github issue: webSocket client does not receive messages before sending...
We ran into this issue and the solution had to do with how we wrote our promises. We initially used the sample code provided by Amazon
https://github.com/aws-samples/simple-websockets-chat-app/blob/master/sendmessage/app.js#L26
const postCalls = connectionData.Items.map(async ({ connectionId }) => {
try {
await apigwManagementApi.postToConnection({ ConnectionId: connectionId, Data: postData }).promise();
} catch (e) {
if (e.statusCode === 410) {
console.log(`Found stale connection, deleting ${connectionId}`);
await ddb.delete({ TableName: TABLE_NAME, Key: { connectionId } }).promise();
} else {
throw e;
}
}
});
And I'm pretty sure having an async function as a map function doesn't work properly or reliably (for whatever reason. maybe this is documented somewhere), so we changed it to a simple for loop and it fixed the issue.
for(const connection of connectionData.Items) {
const connectionId = connection.connectionId;
...same logic goes here
}
The DOC says:
Note: If your add-in calls saveAsync on an item in compose mode in order to get an item ID to use with EWS or the REST API, be aware that when Outlook is in cached mode, it may take some time before the item is actually synced to the server. Until the item is synced, using the itemId will return an error.
As best I can tell, that's the cause of my ErrorItemNotFound problems trying to use that ID? (It's a shame Microsoft did not specifically tell us what error to expect).
Since my code is invoked asynchronously - how exactly do I wait for the noted "some time"? Do we set a timer to re-try every second or something? When do we give up?? Is there something else I can do which will give me a call-back to continue when the item sync has completed? [FYI - even waiting 10 seconds after the save does not work for me]
Be aware that I expect my users may be composing mail with large attachments, so while most no-attachment messages should sync in less than 1 second, folks attaching large pdf/zip/etc files could easily cause more than 1 minute delays here...
The best what you could do is to start polling for an item appeared on the server side. For example, you may try an ugly solution when you use sub-sequential EWS query with Id you've got from saveAsync in the loop and wait for success.
For example, I've noticed the following example how developers try to handle such scenarious:
app.makeEwsRequestAsync = function (request, callback, countRepeatIfCrash, callbackIfCrash) {
try {
Office.context.mailbox.makeEwsRequestAsync(request, function (asyncResult) {
try {
if (asyncResult.status !== 'succeeded') {
app.showError(asyncResult.error.message);
return;
} else {
var $result = app.getResponseElementByName(asyncResult.value, 'm:ResponseCode');
if ($result) {
var responseCOde = $result.text();
if (responseCOde !== 'NoError') {
if (countRepeatIfCrash > 0) {
setTimeout(function () {
app.makeEwsRequestAsync(request, callback, countRepeatIfCrash - 1);
}, 500);
} else if (callbackIfCrash) {
setTimeout(function() {
callbackIfCrash();
}, 500);
} else if (responseCOde === 'ErrorItemNotFound') {
app.showError('EWS ' + responseCOde, function () {
app.makeEwsRequestAsync(request, callback, 70);
});
}
else {
app.showError('EWS ' + responseCOde);
}
return;
}
}
}
callback(asyncResult);
} catch (e) {
app.showError(e);
}
});
} catch (e) {
app.showError(e);
}
}
See App for Outlook: EWS request failed with item Id returned by item.saveAsync on compose new message for more information.
You may also can try using the simple GetItem request:
<GetItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
<ItemShape>
<t:BaseShape>IdOnly</t:BaseShape>
</ItemShape>
<ItemIds><t:ItemId Id="' + itemId + '"/></ItemIds>
</GetItem>
The request should return ChangeKey if item was created on exchange.
I am using the 'Web push notificatoins API' to send notifications from my server to my website.
Long story short - the notifications are received and shown by all major browsers except firefox android (ios untested). I suspect the service worker file to be the culprit but have no idea how to debug see/log its errors / messages.
The service_worker.js :
self.addEventListener('push', function (event) {
if (!(self.Notification && self.Notification.permission === 'granted')) {
console.log('back) ;
return;
}
const sendNotification = body => {
const title = "BTC changed - coinvalue.me";
return self.registration.showNotification(title, {
body,
});
};
if (event.data) {
const message = event.data.text();
event.waitUntil(sendNotification(message));
}
});
Question: How to debug the results of this file? Firefox WebIDE doesn't show any console.log()
Edit : Firefox version 54.0.11 on android 4.2.1
I'm using YouTube's V3 Data API to add a subscription to a channel. This occurs on a Wordpress installation.
I added Google APIs (for oauth) on Wordpress theme functions:
wp_enqueue_script( 'googleapi', 'https://apis.google.com/js/client.js?onload=googleApiClientReady', array(), '1.0.0', true );
I added in the same way the oauth javascript file, which is the first one here: https://developers.google.com/youtube/v3/code_samples/javascript.
Following this guide(https://developers.google.com/youtube/v3/docs/subscriptions/insert (Apps Script)), I extended the OAuth js with the addSubscription method.
Google Client API seems to be loaded and working as it calls correctly googleApiClientReady on the oauth javascript.
So, this is how the subscription is being inserted:
OAUTH JAVASCRIPT
... ... ...
// After the API loads
function handleAPILoaded() {
addSubscription();
}
function addSubscription() {
// Replace this channel ID with the channel ID you want to subscribe to
var channelId = 'this is filled with the channel ID';
var resource = {
snippet: {
resourceId: {
kind: 'youtube#channel',
channelId: channelId
}
}
};
try {
var response = YouTube.Subscriptions.insert(resource, 'snippet');
jQuery('#success').show();
} catch (e) {
if(e.message.match('subscriptionDuplicate')) {
jQuery('#success').show();
} else {
jQuery('#fail').show();
alert("Please send us a mail () with the following: ERROR: " + e.message);
}
}
So, the first error comes with
YouTube.Subscriptions.insert(resource, 'snippet')
It says YouTube is not defined. I replaced it with:
gapi.client.youtube.subscriptions.insert(resource, 'snippet');
And that error went away. When checking response, as the subscription isn't completed, this is what I get
{"wc":1,"hg":{"Ph":null,"hg":{"path":"/youtube/v3/subscriptions","method":"POST","params":{},"headers":{},"body":"snippet","root":"https://www.googleapis.com"},"wc":"auto"}}
So, I would like to know what's happening on that POST request and what's the solution to this.
I can post the full OAuth file, but it's just as in the example, plus that addSubscription method at the end.
Okay, I got it working, the problem was on the POST request. Here is the full method working:
// Subscribes the authorized user to the channel specified
function addSubscription(channelSub) {
var resource = {
part: 'id,snippet',
snippet: {
resourceId: {
kind: 'youtube#channel',
channelId: channelSub
}
}
};
var request = gapi.client.youtube.subscriptions.insert(resource);
request.execute(function (response) {
var result = response.result;
if (result) {
// alert("Subscription completed");
}
} else {
// alert("Subscripion failed");
// ...
}
});
}
Also make sure to load Google Apps API (in fact without it the authorize/login button won't work) and jQuery.
Any chance you can post everything that made this work...all the JS entire auth.js save for your private keys, im working on this exact problem.