Skip to content

Commit

Permalink
Experiment: Don't compress json sent to the server
Browse files Browse the repository at this point in the history
lzstring has performance problems on the server-side, causing issues for
session recording: see PostHog/posthog#2560

Note that this is not a backwards-compatible change, requires a change
on posthog side to support plain/text header as well.

We can't use application/json as content-type as that would trigger CORS
requests for every xhr request as that's considered a custom header.
  • Loading branch information
macobo committed Dec 3, 2020
1 parent 7f145ec commit e25ec49
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 28 deletions.
6 changes: 3 additions & 3 deletions src/__tests__/__snapshots__/send-request.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`encodePostDataBody() handles arrays 1`] = `"data=foo%2Cbar"`;
exports[`formEncodePostData() handles arrays 1`] = `"data=foo%2Cbar"`;

exports[`encodePostDataBody() handles data with compression 1`] = `"data=content&compression=lz64"`;
exports[`formEncodePostData() handles data with compression 1`] = `"data=content&compression=lz64"`;

exports[`encodePostDataBody() handles objects 1`] = `"data=content"`;
exports[`formEncodePostData() handles objects 1`] = `"data=content"`;
6 changes: 3 additions & 3 deletions src/__tests__/send-request.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { encodePostDataBody } from '../send-request'
import { formEncodePostData } from '../send-request'

describe('encodePostDataBody()', () => {
given('subject', () => encodePostDataBody(given.data))
describe('formEncodePostData()', () => {
given('subject', () => formEncodePostData(given.data))

it('handles arrays', () => {
given('data', () => ['foo', 'bar'])
Expand Down
20 changes: 7 additions & 13 deletions src/posthog-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { optIn, optOut, hasOptedIn, hasOptedOut, clearOptInOut, addOptOutCheckPo
import { cookieStore, localStore } from './storage'
import { RequestQueue } from './request-queue'
import { CaptureMetrics } from './capture-metrics'
import { encodePostDataBody } from './send-request'
import { formEncodePostData } from './send-request'

/*
SIMPLE STYLE GUIDE:
Expand Down Expand Up @@ -339,7 +339,9 @@ PostHogLib.prototype._handle_queued_event = function (url, data, options) {
}

PostHogLib.prototype.__compress_and_send_json_request = function (url, jsonData, options, callback) {
if (this.compression['lz64'] || (options.compression && options.compression === 'lz64')) {
if (this.get_config('_capture_metrics')) {
this._send_request(url, jsonData, { ...options, plainJSON: true }, callback)
} else if (this.compression['lz64'] || (options.compression && options.compression === 'lz64')) {
this._send_request(url, { data: LZString.compressToBase64(jsonData), compression: 'lz64' }, options, callback)
} else {
this._send_request(url, { data: _.base64Encode(jsonData) }, options, callback)
Expand All @@ -355,6 +357,7 @@ PostHogLib.prototype._send_request = function (url, data, options, callback) {
var DEFAULT_OPTIONS = {
method: this.get_config('api_method'),
transport: this.get_config('api_transport'),
verbose: this.get_config('verbose') || data['verbose'],
}

if (!callback && (_.isFunction(options) || typeof options === 'string')) {
Expand All @@ -368,18 +371,9 @@ PostHogLib.prototype._send_request = function (url, data, options, callback) {

const useSendBeacon = window.navigator.sendBeacon && options.transport.toLowerCase() === 'sendbeacon'

// needed to correctly format responses
var verbose_mode = this.get_config('verbose')
if (data['verbose']) {
verbose_mode = true
}

if (this.get_config('test')) {
data['test'] = 1
}
if (verbose_mode) {
data['verbose'] = 1
}
if (this.get_config('img')) {
data['img'] = 1
}
Expand Down Expand Up @@ -410,11 +404,11 @@ PostHogLib.prototype._send_request = function (url, data, options, callback) {
// beacons format the message and use the type property
// also no need to try catch as sendBeacon does not report errors
// and is defined as best effort attempt
const body = new Blob([encodePostDataBody(data)], { type: 'application/x-www-form-urlencoded' })
const body = new Blob([formEncodePostData(data)], { type: 'application/x-www-form-urlencoded' })
window.navigator.sendBeacon(url, body)
} else if (USE_XHR) {
try {
xhr(url, options.method, data, this.get_config('xhr_headers'), verbose_mode, this._captureMetrics, callback)
xhr(url, data, this.get_config('xhr_headers'), options, this._captureMetrics, callback)
} catch (e) {
console.error(e)
}
Expand Down
24 changes: 15 additions & 9 deletions src/send-request.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { _, console } from './utils'

export const encodePostDataBody = (data) => {
export const formEncodePostData = (data) => {
let body_data
if (Array.isArray(data)) {
body_data = 'data=' + encodeURIComponent(data)
Expand All @@ -15,8 +15,16 @@ export const encodePostDataBody = (data) => {
return body_data
}

export const xhr = (url, method, data, headers, verbose, captureMetrics, callback) => {
const body = method === 'POST' ? encodePostDataBody(data) : null
export const xhr = (url, data, headers, options, captureMetrics, callback) => {
const req = new XMLHttpRequest()
req.open(options.method, url, true)

let body = null
if (options.plainJSON) {
body = data
} else if (options.method === 'POST') {
body = formEncodePostData()
}

this._captureMetrics.incr('_send_request')
this._captureMetrics.incr('_send_request_inflight')
Expand All @@ -27,14 +35,12 @@ export const xhr = (url, method, data, headers, verbose, captureMetrics, callbac
...options._metrics,
})

const req = new XMLHttpRequest()
req.open(method, url, true)
if (method === 'POST') {
headers['Content-Type'] = 'application/x-www-form-urlencoded'
}
_.each(headers, function (headerValue, headerName) {
req.setRequestHeader(headerName, headerValue)
})
if (options.method === 'POST' && !options.plainJSON) {
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
}

// send the ph_optout cookie
// withCredentials cannot be modified until after calling .open on Android and Mobile Safari
Expand Down Expand Up @@ -71,7 +77,7 @@ export const xhr = (url, method, data, headers, verbose, captureMetrics, callbac
})

if (callback) {
if (verbose) {
if (options.verbose) {
callback({ status: 0, error: error })
} else {
callback(0)
Expand Down

0 comments on commit e25ec49

Please sign in to comment.