Skip to content

Commit 5546e4d

Browse files
authored
fix: trim whitespace from API keys and host config (#133)
1 parent 4fbb90a commit 5546e4d

8 files changed

Lines changed: 139 additions & 89 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'posthog-ruby': patch
3+
---
4+
5+
Trim whitespace from `api_key`, `personal_api_key`, and `host` config values, and default `host` to `https://us.i.posthog.com`.

lib/posthog/client.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def _decrement_instance_count(api_key)
5959
# on the calling thread. Useful in forking environments like Sidekiq
6060
# and Resque. Defaults to +false+.
6161
# @option opts [Proc] :on_error Handles error calls from the API.
62-
# @option opts [String] :host Fully qualified hostname of the PostHog server. Defaults to `https://app.posthog.com`
62+
# @option opts [String] :host Fully qualified hostname of the PostHog server. Defaults to `https://us.i.posthog.com`
6363
# @option opts [Integer] :feature_flags_polling_interval How often to poll for feature flag definition changes.
6464
# Measured in seconds, defaults to 30.
6565
# @option opts [Integer] :feature_flag_request_timeout_seconds How long to wait for feature flag evaluation.
@@ -74,7 +74,9 @@ def _decrement_instance_count(api_key)
7474
def initialize(opts = {})
7575
symbolize_keys!(opts)
7676

77-
opts[:host] ||= 'https://app.posthog.com'
77+
opts[:api_key] = normalize_string_option(opts[:api_key])
78+
opts[:personal_api_key] = normalize_string_option(opts[:personal_api_key], blank_as_nil: true)
79+
opts[:host] = normalize_host_option(opts[:host])
7880

7981
@queue = Queue.new
8082
@api_key = opts[:api_key]
@@ -102,6 +104,7 @@ def initialize(opts = {})
102104
@personal_api_key = opts[:personal_api_key]
103105

104106
check_api_key!
107+
logger.error('api_key is empty after trimming whitespace; check your project API key') if @api_key == ''
105108

106109
# Warn when multiple clients are created with the same API key (can cause dropped events)
107110
unless opts[:test_mode] || opts[:disable_singleton_warning]
@@ -585,6 +588,22 @@ def check_api_key!
585588
raise ArgumentError, 'API key must be initialized' if @api_key.nil?
586589
end
587590

591+
def normalize_string_option(value, blank_as_nil: false)
592+
return value unless value.is_a?(String)
593+
594+
normalized = value.strip
595+
return nil if blank_as_nil && normalized.empty?
596+
597+
normalized
598+
end
599+
600+
def normalize_host_option(host)
601+
normalized = normalize_string_option(host)
602+
return 'https://us.i.posthog.com' if normalized.nil? || normalized.empty?
603+
604+
normalized
605+
end
606+
588607
def ensure_worker_running
589608
return if worker_running?
590609

lib/posthog/defaults.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Defaults
55
MAX_HASH_SIZE = 50_000
66

77
module Request
8-
HOST = 'app.posthog.com'
8+
HOST = 'us.i.posthog.com'
99
PORT = 443
1010
PATH = '/batch/'
1111
SSL = true

spec/posthog/client_spec.rb

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
require 'spec_helper'
44

55
module PostHog
6-
flags_endpoint = 'https://app.posthog.com/flags/?v=2'
6+
flags_endpoint = 'https://us.i.posthog.com/flags/?v=2'
77

88
RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = nil
99

@@ -16,6 +16,7 @@ module PostHog
1616
allow(logger).to receive(:warn)
1717
allow(logger).to receive(:info)
1818
allow(logger).to receive(:debug)
19+
allow(logger).to receive(:error)
1920
end
2021

2122
describe '#initialize' do
@@ -32,16 +33,41 @@ module PostHog
3233
end
3334

3435
it 'handles skip_ssl_verification' do
35-
expect(PostHog::Transport).to receive(:new).with({ api_host: 'https://app.posthog.com',
36+
expect(PostHog::Transport).to receive(:new).with({ api_host: 'https://us.i.posthog.com',
3637
skip_ssl_verification: true })
3738
expect { Client.new api_key: API_KEY, skip_ssl_verification: true }.to_not raise_error
3839
end
3940

41+
it 'trims whitespace-sensitive options' do
42+
client = Client.new(
43+
api_key: " \n#{API_KEY}\t ",
44+
personal_api_key: " \n\t ",
45+
host: " \nhttps://eu.i.posthog.com/\t ",
46+
test_mode: true
47+
)
48+
49+
expect(client.instance_variable_get(:@api_key)).to eq(API_KEY)
50+
expect(client.instance_variable_get(:@personal_api_key)).to be_nil
51+
expect(client.instance_variable_get(:@feature_flags_poller).instance_variable_get(:@host)).to eq('https://eu.i.posthog.com/')
52+
end
53+
54+
it 'defaults a blank host after trimming whitespace' do
55+
client = Client.new(api_key: API_KEY, host: " \n\t ", test_mode: true)
56+
57+
expect(client.instance_variable_get(:@feature_flags_poller).instance_variable_get(:@host)).to eq('https://us.i.posthog.com')
58+
end
59+
60+
it 'logs when the api_key is empty after trimming whitespace' do
61+
Client.new(api_key: " \n\t ", test_mode: true)
62+
63+
expect(logger).to have_received(:error).with(include('api_key is empty after trimming whitespace'))
64+
end
65+
4066
context 'singleton warning' do
4167
before do
4268
# Stub HTTP to allow creating clients without test_mode (which triggers the warning)
43-
stub_request(:post, 'https://app.posthog.com/batch/').to_return(status: 200, body: '{}')
44-
stub_request(:get, %r{https://app\.posthog\.com/api/feature_flag/}).to_return(status: 200, body: '{}')
69+
stub_request(:post, 'https://us.i.posthog.com/batch/').to_return(status: 200, body: '{}')
70+
stub_request(:get, %r{https://us\.i\.posthog\.com/api/feature_flag/}).to_return(status: 200, body: '{}')
4571
end
4672

4773
it 'warns when multiple clients are created with the same API key' do
@@ -252,7 +278,7 @@ module PostHog
252278

253279
stub_request(
254280
:get,
255-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
281+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
256282
).to_return(status: 200, body: api_feature_flag_res.to_json)
257283
stub_request(:post, flags_endpoint)
258284
.to_return(status: 200, body: flags_response.to_json)
@@ -297,7 +323,7 @@ module PostHog
297323

298324
stub_request(
299325
:get,
300-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
326+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
301327
).to_return(status: 200, body: api_feature_flag_res.to_json)
302328
stub_request(:post, flags_endpoint)
303329
.to_return(status: 200, body: flags_response.to_json)
@@ -322,7 +348,7 @@ module PostHog
322348
'off-feature' => false } }
323349
stub_request(
324350
:get,
325-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
351+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
326352
).to_return(status: 200, body: {}.to_json)
327353
stub_request(:post, flags_endpoint)
328354
.to_return(status: 200, body: flags_response.to_json)
@@ -347,7 +373,7 @@ module PostHog
347373

348374
stub_request(
349375
:get,
350-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
376+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
351377
).to_return(status: 401, body: { 'error' => 'not authorized' }.to_json)
352378
stub_request(:post, flags_endpoint)
353379
.to_return(status: 200, body: flags_response.to_json)
@@ -364,7 +390,7 @@ module PostHog
364390
expect(properties['$feature/beta-feature']).to eq('random-variant')
365391
expect(properties['$active_feature_flags']).to eq(['beta-feature'])
366392

367-
assert_not_requested :get, 'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
393+
assert_not_requested :get, 'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
368394
end
369395

370396
it 'manages memory well when sending feature flags' do
@@ -388,7 +414,7 @@ module PostHog
388414
}
389415
stub_request(
390416
:get,
391-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
417+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
392418
).to_return(status: 200, body: api_feature_flag_res.to_json)
393419

394420
stub_const('PostHog::Defaults::MAX_HASH_SIZE', 10)
@@ -456,7 +482,7 @@ module PostHog
456482

457483
stub_request(
458484
:get,
459-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
485+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
460486
).to_return(status: 200, body: api_feature_flag_res.to_json)
461487

462488
stub_const('PostHog::Defaults::MAX_HASH_SIZE', 10)
@@ -613,7 +639,7 @@ module PostHog
613639

614640
stub_request(
615641
:get,
616-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
642+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
617643
).to_return(status: 200, body: api_feature_flag_res.to_json)
618644
stub_request(:post, flags_endpoint)
619645
.to_return(status: 200, body: flags_response.to_json)
@@ -651,7 +677,7 @@ module PostHog
651677

652678
stub_request(
653679
:get,
654-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
680+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
655681
).to_return(status: 200, body: api_feature_flag_res.to_json)
656682
stub_request(:post, flags_endpoint)
657683
.to_return(status: 200, body: flags_response.to_json)
@@ -677,7 +703,7 @@ module PostHog
677703
it 'ignores feature flags with invalid send_feature_flags parameter' do
678704
stub_request(
679705
:get,
680-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
706+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
681707
).to_return(status: 200, body: { flags: [] }.to_json)
682708
c = Client.new(api_key: API_KEY, personal_api_key: API_KEY, test_mode: true)
683709

@@ -715,7 +741,7 @@ module PostHog
715741
}
716742
stub_request(
717743
:get,
718-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
744+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
719745
).to_return(status: 200, body: api_feature_flag_res.to_json)
720746

721747
# This should NOT be called because only_evaluate_locally is true
@@ -767,7 +793,7 @@ module PostHog
767793
}
768794
stub_request(
769795
:get,
770-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
796+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
771797
).to_return(status: 200, body: api_feature_flag_res.to_json)
772798

773799
# This should NOT be called because only_evaluate_locally is true
@@ -818,7 +844,7 @@ module PostHog
818844
}
819845
stub_request(
820846
:get,
821-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
847+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
822848
).to_return(status: 200, body: api_feature_flag_res.to_json)
823849

824850
# This SHOULD be called because only_evaluate_locally is explicitly false
@@ -1160,7 +1186,7 @@ def run
11601186
# Mock response for api/feature_flag
11611187
stub_request(
11621188
:get,
1163-
'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
1189+
'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true'
11641190
).to_return(status: 200, body: api_feature_flag_res.to_json)
11651191

11661192
# Mock response for `/flags`

spec/posthog/feature_flag_error_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
module PostHog
66
describe 'Feature Flag Error Tracking' do
7-
let(:flags_endpoint) { 'https://app.posthog.com/flags/?v=2' }
8-
let(:feature_flag_endpoint) { 'https://app.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true' }
7+
let(:flags_endpoint) { 'https://us.i.posthog.com/flags/?v=2' }
8+
let(:feature_flag_endpoint) { 'https://us.i.posthog.com/api/feature_flag/local_evaluation?token=testsecret&send_cohorts=true' }
99
let(:client) { Client.new(api_key: API_KEY, personal_api_key: API_KEY, test_mode: true) }
1010

1111
before do

0 commit comments

Comments
 (0)