Skip to content

Commit

Permalink
chore: set user-agent for non browser apps (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored Mar 13, 2024
1 parent 7cd510c commit b27cd3f
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 38 deletions.
29 changes: 16 additions & 13 deletions posthog-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ export abstract class PostHogCoreStateless {
const url = `${this.host}/decide/?v=3`
const fetchOptions: PostHogFetchOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
body: JSON.stringify({
token: this.apiKey,
distinct_id: distinctId,
Expand Down Expand Up @@ -532,6 +532,19 @@ export abstract class PostHogCoreStateless {
return this.flushPromise
}

protected getCustomHeaders(): { [key: string]: string } {
// Don't set the user agent if we're not on a browser. The latest spec allows
// the User-Agent header (see https://fetch.spec.whatwg.org/#terminology-headers
// and https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader),
// but browsers such as Chrome and Safari have not caught up.
const customUserAgent = this.getCustomUserAgent()
const headers: { [key: string]: string } = {}
if (customUserAgent && customUserAgent !== '') {
headers['User-Agent'] = customUserAgent
}
return headers
}

private async _flush(): Promise<any[]> {
this.clearFlushTimer()
await this._initPromise
Expand All @@ -556,16 +569,6 @@ export abstract class PostHogCoreStateless {
sent_at: currentISOTime(),
}

// Don't set the user agent if we're not on a browser. The latest spec allows
// the User-Agent header (see https://fetch.spec.whatwg.org/#terminology-headers
// and https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader),
// but browsers such as Chrome and Safari have not caught up.
const customUserAgent = this.getCustomUserAgent()
const headers: { [key: string]: string } = {}
if (customUserAgent) {
headers['user-agent'] = customUserAgent
}

const payload = JSON.stringify(data)

const url =
Expand All @@ -579,12 +582,12 @@ export abstract class PostHogCoreStateless {
method: 'POST',
mode: 'no-cors',
credentials: 'omit',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
}
: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
body: payload,
}

Expand Down
7 changes: 7 additions & 0 deletions posthog-core/test/posthog.featureflags.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ describe('PostHog Core', () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'posthog-core-tests',
},
signal: expect.anything(),
})
Expand Down Expand Up @@ -224,6 +225,7 @@ describe('PostHog Core', () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'posthog-core-tests',
},
signal: expect.anything(),
})
Expand All @@ -250,6 +252,7 @@ describe('PostHog Core', () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'posthog-core-tests',
},
signal: expect.anything(),
})
Expand Down Expand Up @@ -327,6 +330,7 @@ describe('PostHog Core', () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'posthog-core-tests',
},
signal: expect.anything(),
})
Expand All @@ -353,6 +357,7 @@ describe('PostHog Core', () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'posthog-core-tests',
},
signal: expect.anything(),
})
Expand Down Expand Up @@ -545,6 +550,7 @@ describe('PostHog Core', () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'posthog-core-tests',
},
signal: expect.anything(),
})
Expand All @@ -570,6 +576,7 @@ describe('PostHog Core', () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'posthog-core-tests',
},
signal: expect.anything(),
})
Expand Down
18 changes: 11 additions & 7 deletions posthog-node/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# Next

1. Sets `User-Agent` headers with SDK name and version for RN

# 4.0.0-beta.2 - 2024-03-12

- `flushAsync` and `shutdownAsync` are removed with `flush` and `shutdown` now being the async methods.
- Fixed an issue where `shutdown` would potentially exit early if a flush was already in progress
- Flushes will now try to flush up to `maxBatchSize` (default 100) in one go
1. `flushAsync` and `shutdownAsync` are removed with `flush` and `shutdown` now being the async methods.
2. Fixed an issue where `shutdown` would potentially exit early if a flush was already in progress
3. Flushes will now try to flush up to `maxBatchSize` (default 100) in one go

# 4.0.0-beta.1 - 2024-03-04

- Adds a `disabled` option and the ability to change it later via `posthog.disabled = true`. Useful for disabling PostHog tracking for example in a testing environment without having complex conditional checking
- Fixes some typos in types
- `shutdown` and `shutdownAsync` takes a `shutdownTimeoutMs` param with a default of 30000 (30s). This is the time to wait for flushing events before shutting down the client. If the timeout is reached, the client will be shut down regardless of pending events.
- Adds a new `featureFlagsRequestTimeoutMs` timeout parameter for feature flags which defaults to 3 seconds, updated from the default 10s for all other API calls.
1. Adds a `disabled` option and the ability to change it later via `posthog.disabled = true`. Useful for disabling PostHog tracking for example in a testing environment without having complex conditional checking
2. Fixes some typos in types
3. `shutdown` and `shutdownAsync` takes a `shutdownTimeoutMs` param with a default of 30000 (30s). This is the time to wait for flushing events before shutting down the client. If the timeout is reached, the client will be shut down regardless of pending events.
4. Adds a new `featureFlagsRequestTimeoutMs` timeout parameter for feature flags which defaults to 3 seconds, updated from the default 10s for all other API calls.

# 3.6.3 - 2024-02-15

Expand Down
7 changes: 5 additions & 2 deletions posthog-node/src/feature-flags.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createHash } from 'rusha'
import { FeatureFlagCondition, FlagProperty, PostHogFeatureFlag, PropertyGroup } from './types'
import { version } from '../package.json'
import { JsonType, PostHogFetchOptions, PostHogFetchResponse } from 'posthog-core/src'
import { safeSetTimeout } from 'posthog-core/src/utils'
import fetch from './fetch'
Expand Down Expand Up @@ -38,6 +37,7 @@ type FeatureFlagsPollerOptions = {
timeout?: number
fetch?: (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>
onError?: (error: Error) => void
customHeaders?: { [key: string]: string }
}

class FeatureFlagsPoller {
Expand All @@ -55,13 +55,15 @@ class FeatureFlagsPoller {
fetch: (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>
debugMode: boolean = false
onError?: (error: Error) => void
customHeaders?: { [key: string]: string }

constructor({
pollingInterval,
personalApiKey,
projectApiKey,
timeout,
host,
customHeaders,
...options
}: FeatureFlagsPollerOptions) {
this.pollingInterval = pollingInterval
Expand All @@ -78,6 +80,7 @@ class FeatureFlagsPoller {
// NOTE: as any is required here as the AbortSignal typing is slightly misaligned but works just fine
this.fetch = options.fetch || fetch
this.onError = options.onError
this.customHeaders = customHeaders

void this.loadFeatureFlags()
}
Expand Down Expand Up @@ -413,9 +416,9 @@ class FeatureFlagsPoller {
const options: PostHogFetchOptions = {
method: 'GET',
headers: {
...this.customHeaders,
'Content-Type': 'application/json',
Authorization: `Bearer ${this.personalApiKey}`,
'user-agent': `posthog-node/${version}`,
},
}

Expand Down
3 changes: 2 additions & 1 deletion posthog-node/src/posthog-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
onError: (err: Error) => {
this._events.emit('error', err)
},
customHeaders: this.getCustomHeaders(),
})
}
this.distinctIdHasSentFlagCalls = {}
Expand All @@ -83,7 +84,7 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
return version
}
getCustomUserAgent(): string {
return `posthog-node/${version}`
return `${this.getLibraryId()}/${this.getLibraryVersion()}`
}

enable(): Promise<void> {
Expand Down
28 changes: 16 additions & 12 deletions posthog-react-native/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
# Next

1. Sets `User-Agent` headers with SDK name and version for RN

# 3.0.0-beta.2 - 2024-03-12

- `flushAsync` and `shutdownAsync` are removed with `flush` and `shutdown` now being the async methods.
- Fixed an issue where `shutdownAsync` would potentially exit early if a flush was already in progress
- Flushes will now try to flush up to `maxBatchSize` (default 100) in one go
1. `flushAsync` and `shutdownAsync` are removed with `flush` and `shutdown` now being the async methods.
2. Fixed an issue where `shutdownAsync` would potentially exit early if a flush was already in progress
3. Flushes will now try to flush up to `maxBatchSize` (default 100) in one go

# 3.0.0-beta.1 - 2024-03-04

- `PostHog.initAsync` is no more! You can now initialize PostHog as you would any other class `const posthog = new PostHog(...)`
- PostHogProvider now requires either an `apiKey` or `client` property and `usePostHog` now always returns a `PostHog` instance instead of `PostHog | undefined`. The `disabled` option can be used when initializing the `PostHogProvider` if desired and all subsequent calls to `posthog` will work but without actually doing anything.
- Removes the `enable` option. You can now specify `defaultOptIn: false` to start the SDK opted out of tracking
- Adds a `disabled` option and the ability to change it later via `posthog.disabled = true`. Useful for disabling PostHog tracking for example in a testing environment without having complex conditional checking
- Many methods such as `capture` and `identify` no longer return the `this` object instead returning nothing
- Fixes some typos in types
- `shutdown` and `shutdownAsync` takes a `shutdownTimeoutMs` param with a default of 30000 (30s). This is the time to wait for flushing events before shutting down the client. If the timeout is reached, the client will be shut down regardless of pending events.
- Adds a new `featureFlagsRequestTimeoutMs` timeout parameter for feature flags which defaults to 10 seconds.
- Replaces the option `customAsyncStorage` with `customStorage` to allow for custom synchronous or asynchronous storage implementations.
1. `PostHog.initAsync` is no more! You can now initialize PostHog as you would any other class `const posthog = new PostHog(...)`
2. PostHogProvider now requires either an `apiKey` or `client` property and `usePostHog` now always returns a `PostHog` instance instead of `PostHog | undefined`. The `disabled` option can be used when initializing the `PostHogProvider` if desired and all subsequent calls to `posthog` will work but without actually doing anything.
3. Removes the `enable` option. You can now specify `defaultOptIn: false` to start the SDK opted out of tracking
4. Adds a `disabled` option and the ability to change it later via `posthog.disabled = true`. Useful for disabling PostHog tracking for example in a testing environment without having complex conditional checking
5. Many methods such as `capture` and `identify` no longer return the `this` object instead returning nothing
6. Fixes some typos in types
7. `shutdown` and `shutdownAsync` takes a `shutdownTimeoutMs` param with a default of 30000 (30s). This is the time to wait for flushing events before shutting down the client. If the timeout is reached, the client will be shut down regardless of pending events.
8. Adds a new `featureFlagsRequestTimeoutMs` timeout parameter for feature flags which defaults to 10 seconds.
9. Replaces the option `customAsyncStorage` with `customStorage` to allow for custom synchronous or asynchronous storage implementations.

# 2.11.6 - 2024-02-22

Expand Down
9 changes: 6 additions & 3 deletions posthog-react-native/src/posthog-rn.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AppState, Dimensions, Linking } from 'react-native'
import { AppState, Dimensions, Linking, Platform } from 'react-native'

import {
PostHogCaptureOptions,
Expand Down Expand Up @@ -136,8 +136,11 @@ export class PostHog extends PostHogCore {
getLibraryVersion(): string {
return version
}
getCustomUserAgent(): void {
return
getCustomUserAgent(): string {
if (Platform.OS === 'web') {
return ''
}
return `${this.getLibraryId()}/${this.getLibraryVersion()}`
}

getCommonEventProperties(): any {
Expand Down

0 comments on commit b27cd3f

Please sign in to comment.