$(window).on('unload', function() { db.flipCounter.get(gon.slug, function(obj) { var payload = { slug: gon.slug, localFlipCount: obj.fc, time: Date.now() } navigator.sendBeacon('/analytics', csrfProtect(payload)) }) }) function csrfProtect(payload) { var param = $("meta[name=csrf-param]").attr("content") var token = $("meta[name=csrf-token]").attr("content") if (param && token) payload[param] = token return new Blob([JSON.stringify(payload)], { type: "application/x-www-form-urlencoded; charset=utf-8" }) }

In the code above I wish to hit POST to the '/analytics' url with the payload. I get the following error(warning) upon… attempting to fire a request:

Promise.js:840 Unhandled rejection: TypeError: Cannot create property 'authenticity_token' on string '{"slug":"test-page-by-marvin-danig","localFlipCount":1,"time":1524241435403}'

Hm.

…firing a request, I get:

Processing by BooksController#analytics as */* Parameters: {"{\"slug\":\"test-book-by-marvin-danig\",\"localFlipCount\":1,\"time\":1524243279653,\"param\":\"8rzDx/TNL8YeU1/NWgWSk6gB/UvmbB9Ip VajDCgfDUv5Q4pjh7x0GUG1il1jDJajtJyHf84Xv5Pt14fiCnA9w"=>"=\"}"} Can't verify CSRF token authenticity. exception ActionController::InvalidAuthenticityToken

UPDATE: The issue isn't resolved still. Here's where I am at right now:

I have the following GET & POST routes open on my routes.rb :

# Analytics (flipCounter) get 'auth_token', to: 'analytics#auth_token' post 'receptor', to: 'analytics#receptor', as: :receptor

These obviously map to the analytics_controller like so:

class AnalyticsController < ApplicationController respond_to :js def auth_token session[:_csrf_token] = form_authenticity_token end def receptor logger.debug "Check book slug first: #{params}" begin book = Book.friendly.find(params[:slug]) rescue ActiveRecord::RecordNotFound => e book = nil end if book.exists? book.flipcount += params[:flipcount].to_i end end private end

Alongside the auth_token method, I got an auth_token.json.erb template that is shipped per following:

{ "authenticity_token": "<%= session[:_csrf_token] %>" }

And the client side javascript (poor draft) goes the following way:

// When state of book changes to `not_flipping`: flipCount += 1 const o = { slug: gon.slug, fc: flipCount } // IndexedDb initiated elsewhere. db.transaction('rw', db.flipCounter, function(e) { db.flipCounter.put(o) }).then(function(e) { const URL = '/auth_token' // First fetch the authenticity_token! fetch(URL, { method: 'GET' }).then(function(res) { return res.json() }).then(function(token) { return postBookData(token) }).catch(err => console.log(err)) }).catch(function(e) { console.log(e) }) function postBookData(token) { db.flipCounter.get(gon.slug, function(obj) { // var payload = new FormData() // payload.append('slug', gon.slug) // payload.append('localFlipCount', obj.fc) // payload.append('authenticity_token', token.authenticity_token) // payload.append('type', 'application/x-www-form-urlencoded;') // payload.append('charset=utf-8', 'ok') // payload.append('X-CSRF-Token', token.authenticity_token) //var payload = { 'slug': gon.slug } let body = { slug: gon.slug, flipcount: obj.fc, time: Date.now() } let headers = { type: 'application/x-www-form-urlencoded; charset=utf-8', 'X-CSRF-Token': token.authenticity_token } let blob = new Blob([JSON.stringify(body)], headers); let url = '/receptor' navigator.sendBeacon(url, blob); }).then(function() { flipCount = 0 var o = { slug: gon.slug, fc: flipCount } }).catch(err => console.log(err)) }

The request object fired by the navigator.sendBeacon isn't correct because the X-CSRF-Token isn't set and I obviously get the following error on the server side:

Started POST "/receptor" for 127.0.0.1 at 2018-04-26 09:00:33 -0400 Processing by AnalyticsController#receptor as */* Parameters: {"{\"slug\":\"bookiza-documentation-by-marvin-danig\",\"fc\":1}"=>nil} Can't verify CSRF token authenticity. exception ActionController::InvalidAuthenticityToken Rendering public/500.html Rendered public/500.html (1.0ms) Completed 500 Internal Server Error in 337ms (Views: 335.8ms | ActiveRecord: 0.0ms)