Skip to content

Commit f4e5596

Browse files
refact: Replace httparty in favor of core net/http package (#252)
* refact: Replace httparty in favor of core net/http package * move request into util * slight refactor to rename network_util http_util Co-authored-by: Tom Zurkan <thomas.zurkan@optimizely.com>
1 parent 1ee0df7 commit f4e5596

File tree

7 files changed

+104
-34
lines changed

7 files changed

+104
-34
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ Gemfile.lock
1111
/tmp/
1212
*.DS_Store
1313
.ruby-version
14+
vendor/bundle

lib/optimizely/config_manager/http_project_config_manager.rb

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@
1919
require_relative '../error_handler'
2020
require_relative '../exceptions'
2121
require_relative '../helpers/constants'
22+
require_relative '../helpers/http_utils'
2223
require_relative '../logger'
2324
require_relative '../notification_center'
2425
require_relative '../project_config'
2526
require_relative '../optimizely_config'
2627
require_relative 'project_config_manager'
2728
require_relative 'async_scheduler'
28-
require 'httparty'
29+
2930
require 'json'
31+
3032
module Optimizely
3133
class HTTPProjectConfigManager < ProjectConfigManager
3234
# Config manager that polls for the datafile and updated ProjectConfig based on an update interval.
@@ -148,16 +150,12 @@ def request_config
148150
"Fetching datafile from #{@datafile_url}"
149151
)
150152
begin
151-
headers = {
152-
'Content-Type' => 'application/json'
153-
}
154-
155-
headers[Helpers::Constants::HTTP_HEADERS['LAST_MODIFIED']] = @last_modified if @last_modified
153+
headers = {}
154+
headers['Content-Type'] = 'application/json'
155+
headers['If-Modified-Since'] = @last_modified if @last_modified
156156

157-
response = HTTParty.get(
158-
@datafile_url,
159-
headers: headers,
160-
timeout: Helpers::Constants::CONFIG_MANAGER['REQUEST_TIMEOUT']
157+
response = Helpers::HttpUtils.make_request(
158+
@datafile_url, :get, nil, headers, Helpers::Constants::CONFIG_MANAGER['REQUEST_TIMEOUT']
161159
)
162160
rescue StandardError => e
163161
@logger.log(

lib/optimizely/event_dispatcher.rb

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
#
4-
# Copyright 2016-2017, 2019, Optimizely and contributors
4+
# Copyright 2016-2017, 2019-2020 Optimizely and contributors
55
#
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
@@ -16,8 +16,7 @@
1616
# limitations under the License.
1717
#
1818
require_relative 'exceptions'
19-
20-
require 'httparty'
19+
require_relative 'helpers/http_utils'
2120

2221
module Optimizely
2322
class NoOpEventDispatcher
@@ -39,19 +38,13 @@ def initialize(logger: nil, error_handler: nil)
3938
#
4039
# @param event - Event object
4140
def dispatch_event(event)
42-
if event.http_verb == :get
43-
response = HTTParty.get(event.url, headers: event.headers, query: event.params, timeout: REQUEST_TIMEOUT)
44-
45-
elsif event.http_verb == :post
46-
response = HTTParty.post(event.url,
47-
body: event.params.to_json,
48-
headers: event.headers,
49-
timeout: REQUEST_TIMEOUT)
50-
end
41+
response = Helpers::HttpUtils.make_request(
42+
event.url, event.http_verb, event.params.to_json, event.headers, REQUEST_TIMEOUT
43+
)
5144

5245
error_msg = "Event failed to dispatch with response code: #{response.code}"
5346

54-
case response.code
47+
case response.code.to_i
5548
when 400...500
5649
@logger.log(Logger::ERROR, error_msg)
5750
@error_handler.handle_error(HTTPCallError.new("HTTP Client Error: #{response.code}"))

lib/optimizely/helpers/http_utils.rb

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# frozen_string_literal: true
2+
3+
#
4+
# Copyright 2020, Optimizely and contributors
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
require 'net/http'
20+
21+
module Optimizely
22+
module Helpers
23+
module HttpUtils
24+
module_function
25+
26+
def make_request(url, http_method, request_body = nil, headers = {}, read_timeout = nil)
27+
# makes http/https GET/POST request and returns response
28+
29+
uri = URI.parse(url)
30+
http = Net::HTTP.new(uri.host, uri.port)
31+
32+
http.read_timeout = read_timeout if read_timeout
33+
http.use_ssl = uri.scheme == 'https'
34+
35+
if http_method == :get
36+
request = Net::HTTP::Get.new(uri.request_uri)
37+
elsif http_method == :post
38+
request = Net::HTTP::Post.new(uri.request_uri)
39+
request.body = request_body if request_body
40+
else
41+
return nil
42+
end
43+
44+
# set headers
45+
headers&.each do |key, val|
46+
request[key] = val
47+
end
48+
49+
http.request(request)
50+
end
51+
end
52+
end
53+
end

optimizely-sdk.gemspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
2323
spec.add_development_dependency 'rubocop', '0.73.0'
2424
spec.add_development_dependency 'webmock'
2525

26-
spec.add_runtime_dependency 'httparty', '~> 0.11'
2726
spec.add_runtime_dependency 'json-schema', '~> 2.6'
2827
spec.add_runtime_dependency 'murmurhash3', '~> 0.1'
2928
end

spec/config_manager/http_project_config_manager_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,24 @@
6969
expect(@http_project_config_manager.config).to be_a Optimizely::ProjectConfig
7070
end
7171

72+
it 'should get project config when valid http url is given' do
73+
WebMock.reset!
74+
stub_request(:get, 'http://cdn.optimizely.com/datafiles/valid_sdk_key.json')
75+
.with(
76+
headers: {
77+
'Content-Type' => 'application/json'
78+
}
79+
)
80+
.to_return(status: 200, body: VALID_SDK_KEY_CONFIG_JSON, headers: {})
81+
82+
@http_project_config_manager = Optimizely::HTTPProjectConfigManager.new(
83+
url: 'http://cdn.optimizely.com/datafiles/valid_sdk_key.json'
84+
)
85+
86+
until @http_project_config_manager.ready?; end
87+
expect(@http_project_config_manager.config).to be_a Optimizely::ProjectConfig
88+
end
89+
7290
it 'should get project config when sdk_key is given' do
7391
@http_project_config_manager = Optimizely::HTTPProjectConfigManager.new(
7492
sdk_key: 'valid_sdk_key'

spec/event_dispatcher_spec.rb

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
#
4-
# Copyright 2016-2017, 2019, Optimizely and contributors
4+
# Copyright 2016-2017, 2019-2020 Optimizely and contributors
55
#
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
@@ -50,11 +50,20 @@
5050
.with(body: @params, headers: @post_headers)).to have_been_made.once
5151
end
5252

53+
it 'should properly dispatch V2 (POST) events to http url' do
54+
http_url = 'http://www.optimizely.com'
55+
stub_request(:post, http_url)
56+
event = Optimizely::Event.new(:post, http_url, @params, @post_headers)
57+
@event_dispatcher.dispatch_event(event)
58+
59+
expect(a_request(:post, http_url)
60+
.with(body: @params, headers: @post_headers)).to have_been_made.once
61+
end
62+
5363
it 'should properly dispatch V2 (POST) events with timeout exception' do
54-
stub_request(:post, @url)
5564
event = Optimizely::Event.new(:post, @url, @params, @post_headers)
5665
timeout_error = Timeout::Error.new
57-
allow(HTTParty).to receive(:post).with(any_args).and_raise(timeout_error)
66+
stub_request(:post, @url).to_raise(timeout_error)
5867
result = @event_dispatcher.dispatch_event(event)
5968

6069
expect(result).to eq(timeout_error)
@@ -71,21 +80,21 @@
7180

7281
it 'should properly dispatch V2 (GET) events with timeout exception' do
7382
get_url = @url + '?a=111001&g=111028&n=test_event&u=test_user'
74-
stub_request(:get, get_url)
7583
event = Optimizely::Event.new(:get, get_url, @params, @post_headers)
7684
timeout_error = Timeout::Error.new
77-
allow(HTTParty).to receive(:get).with(any_args).and_raise(timeout_error)
85+
stub_request(:get, get_url).to_raise(timeout_error)
86+
7887
result = @event_dispatcher.dispatch_event(event)
7988

8089
expect(result).to eq(timeout_error)
8190
end
8291

8392
it 'should log and handle Timeout error' do
8493
get_url = @url + '?a=111001&g=111028&n=test_event&u=test_user'
85-
stub_request(:post, get_url)
8694
event = Optimizely::Event.new(:post, get_url, @params, @post_headers)
8795
timeout_error = Timeout::Error.new
88-
allow(HTTParty).to receive(:post).with(any_args).and_raise(timeout_error)
96+
stub_request(:post, get_url).to_raise(timeout_error)
97+
8998
result = @customized_event_dispatcher.dispatch_event(event)
9099

91100
expect(result).to eq(timeout_error)
@@ -98,10 +107,9 @@
98107

99108
it 'should log and handle any standard error' do
100109
get_url = @url + '?a=111001&g=111028&n=test_event&u=test_user'
101-
stub_request(:post, get_url)
102110
event = Optimizely::Event.new(:post, get_url, @params, @post_headers)
103-
error = ArgumentError
104-
allow(HTTParty).to receive(:post).with(any_args).and_raise(error)
111+
stub_request(:post, get_url).to_raise(ArgumentError.new)
112+
105113
result = @customized_event_dispatcher.dispatch_event(event)
106114

107115
expect(result).to eq(nil)

0 commit comments

Comments
 (0)