Skip to content

Commit c5f33fb

Browse files
committed
Explicitly tell when a body should be transformed
...or not before the request. By exposing the request options as a Hash param of http_request. Reason: - Currently, we transform the HTTP request body into JSON before each request. - Now, we may have body of different String types (JSON, NDJSON, CSV) that shouldn't be transformed into JSON. - Thus, we're exposing a flag to tell when a body should be transformed or not into JSON. - I've decided to use a flag over a complex rules that could check the content along with headers because ideally, the body transformation should be responsibility of a level above that knows about the content. Other benefit: - Improve options' organization and its default values, as they were spread around. - In the future: this could be even extracted into another class, maybe as Value Object - Note: RuboCop is complaining about "too many optional params" in http_post
1 parent 1ddbc92 commit c5f33fb

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed

lib/meilisearch/http_request.rb

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,30 @@ class HTTPRequest
1212
def initialize(url, api_key = nil, options = {})
1313
@base_url = url
1414
@api_key = api_key
15-
@options = options
16-
@headers = {
17-
'Content-Type' => 'application/json',
18-
'X-Meili-API-Key' => api_key
19-
}.compact
20-
@headers_no_body = {
21-
'X-Meili-API-Key' => api_key
22-
}.compact
15+
@options = merge_options({
16+
timeout: 1,
17+
max_retries: 0,
18+
headers: build_default_options_headers(api_key),
19+
transform_body?: true
20+
}, options)
2321
end
2422

2523
def http_get(relative_path = '', query_params = {})
2624
send_request(
2725
proc { |path, config| self.class.get(path, config) },
2826
relative_path,
2927
query_params: query_params,
30-
headers: @headers_no_body
28+
options: remove_options_header(@options, 'Content-Type')
3129
)
3230
end
3331

34-
def http_post(relative_path = '', body = nil, query_params = nil)
32+
def http_post(relative_path = '', body = nil, query_params = nil, options = {})
3533
send_request(
3634
proc { |path, config| self.class.post(path, config) },
3735
relative_path,
3836
query_params: query_params,
3937
body: body,
40-
headers: @headers
38+
options: merge_options(@options, options)
4139
)
4240
end
4341

@@ -47,24 +45,49 @@ def http_put(relative_path = '', body = nil, query_params = nil)
4745
relative_path,
4846
query_params: query_params,
4947
body: body,
50-
headers: @headers
48+
options: @options
5149
)
5250
end
5351

5452
def http_delete(relative_path = '')
5553
send_request(
5654
proc { |path, config| self.class.delete(path, config) },
5755
relative_path,
58-
headers: @headers_no_body
56+
options: remove_options_header(@options, 'Content-Type')
5957
)
6058
end
6159

6260
private
6361

62+
def build_default_options_headers(api_key = nil)
63+
{
64+
'Content-Type' => 'application/json',
65+
'X-Meili-API-Key' => api_key
66+
}.compact
67+
end
68+
69+
def merge_options(defaults, added = {})
70+
merged = defaults.merge(added)
71+
merged[:headers].merge(added[:headers]) if added.key?(:headers)
72+
merged
73+
end
74+
75+
def remove_options_header(options, key)
76+
new_options = clone_options(options)
77+
new_options[:headers].tap { |headers| headers.delete(key) }
78+
new_options
79+
end
80+
81+
def clone_options(options)
82+
cloned_options = options.clone
83+
cloned_options[:headers] = options[:headers].clone
84+
cloned_options
85+
end
86+
6487
SNAKE_CASE = /[^a-zA-Z0-9]+(.)/.freeze
6588

66-
def send_request(http_method, relative_path, query_params: nil, body: nil, headers: nil)
67-
config = http_config(query_params, body, headers)
89+
def send_request(http_method, relative_path, query_params: nil, body: nil, options: {})
90+
config = http_config(query_params, body, options)
6891
begin
6992
response = http_method.call(@base_url + relative_path, config)
7093
rescue Errno::ECONNREFUSED => e
@@ -73,14 +96,14 @@ def send_request(http_method, relative_path, query_params: nil, body: nil, heade
7396
validate(response)
7497
end
7598

76-
def http_config(query_params, body, headers)
99+
def http_config(query_params, body, options)
77100
body = transform_attributes(body).to_json
78101
{
79-
headers: headers,
102+
headers: options[:headers],
80103
query: query_params,
81104
body: body,
82-
timeout: @options[:timeout] || 1,
83-
max_retries: @options[:max_retries] || 0
105+
timeout: options[:timeout],
106+
max_retries: options[:max_retries]
84107
}.compact
85108
end
86109

spec/meilisearch/index/base_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,15 @@
7272
options = { timeout: 2, max_retries: 1 }
7373
new_client = MeiliSearch::Client.new(URL, MASTER_KEY, options)
7474
index = new_client.create_index('options')
75-
expect(index.options).to eq({ timeout: 2, max_retries: 1 })
75+
expect(index.options).to eq({
76+
headers: {
77+
'Content-Type' => 'application/json',
78+
'X-Meili-API-Key' => MASTER_KEY
79+
},
80+
max_retries: 1,
81+
timeout: 2,
82+
transform_body?: true
83+
})
7684
expect(MeiliSearch::Index).to receive(:get).with(
7785
"#{URL}/indexes/options",
7886
{

0 commit comments

Comments
 (0)