Background:
I'm trying the simple web push notifications example given in Google's documentation of the same (link: https://developers.google.com/web/fundamentals/push-notifications/subscribing-a-user)
I keep running into a SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data
error, which means I'm doing something fundamentally wrong. I'm a JS neophyte, can you help?
My simple function to subscribe user to push is simply:
function subscribeUserToPush() {
const pub_key = document.getElementById("notif_pub_key");
const service_worker_location = document.getElementById("sw_loc");
return navigator.serviceWorker.register(service_worker_location.value)
.then(function(registration) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(pub_key.value)
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(function(pushSubscription) {
sendSubscriptionToBackEnd(pushSubscription);
return pushSubscription;
});
}
And sendSubscriptionToBackEnd() essentially uses fetch
like so:
function sendSubscriptionToBackEnd(subscription) {
const sub_obj = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'CSRFToken':get_cookie('csrftoken')
},
body: JSON.stringify(subscription)
}
return fetch('/subscription/save/', sub_obj)
.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.');
}
});
}
This fails with the error SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data
.
Doing console.log(sub_obj)
shows this object:
Object { method: "POST", headers: {…}, body: "{\"endpoint\":\"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABcaErG3Zn6Urzn5Hfhpyjl0eJg_IVtcgZI-sQr5KGE0WEWt9mKjYb7YXU60wgJtj9gYusApIJnObN0Vvm7oJFRXhbehxtSFxqHLOhSt9MvbIg0tQancpNAcSZ3fWA89E-W6hu0x4dqzqnxqP9KeQ42MYZnelO_IK7Ao1cWlJ41w8wZSlc\",\"keys\":{\"auth\":\"AJfXcUMO3ciEZL1DdD2AbA\",\"p256dh\":\"BN84oKD3-vFqlJnLU4IY7qgmPeSG96un-DttKZnSJhrFMWwLrH2j1a0tTB_QLoq5oLCAQql6hLDJ1W4hgnFQQUs\"}}" }
Also doing console.log(response);
right before return response.json();
displays:
Response { type: "basic", url: "http://127.0.0.1:8001/subscription/save/", redirected: false, status: 200, ok: true, statusText: "OK", headers: Headers, body: ReadableStream, bodyUsed: false }
What's the problem and how do I fix it?
Changing return response.json()
to return response.text()
and then doing a console log on responseData
gives the entire HTML of the page. I end up with the error Error: Bad response from server.
The main issue was that CSRFToken
was mislabeled when being set in sendSubscriptionToBackEnd
. It should have been X-CSRFToken
. I.e.
function sendSubscriptionToBackEnd(subscription) {
const sub_obj = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken':get_cookie('csrftoken'),
},
body: JSON.stringify(subscription)
}
return fetch('/subscription/save/', sub_obj)
.then(function(response) {
console.log(response);
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
// response from the server
console.log(responseData)
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
So why was this leading to return response.json();
failing?
Because the project in question routes requests that fail csrf checks to a default view - one which doesn't return a json response at all. Mystery solved!