Skip to content

Commit 4bb80e5

Browse files
committed
Support rewriting the request_url in the HttpClient when no Host header is provided
1 parent a4f18f2 commit 4bb80e5

File tree

2 files changed

+73
-5
lines changed

2 files changed

+73
-5
lines changed

lib/shopify_api/clients/http_client.rb

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,18 @@ def request(request, response_as_struct: false)
3939
headers = @headers
4040
headers["Content-Type"] = T.must(request.body_type) if request.body_type
4141
headers = headers.merge(T.must(request.extra_headers)) if request.extra_headers
42-
if headers["Host"].include?(".my.shop.dev")
43-
headers["x-forwarded-host"] = headers["Host"]
44-
headers["Host"] = "app.shop.dev"
45-
end
42+
43+
parsed_uri = URI(request_url(request))
44+
45+
headers = append_first_party_development_headers(headers, parsed_uri)
4646

4747
tries = 0
4848
response = HttpResponse.new(code: 0, headers: {}, body: "")
4949
while tries < request.tries
5050
tries += 1
5151
res = T.cast(HTTParty.send(
5252
request.http_method,
53-
request_url(request),
53+
parsed_uri.to_s,
5454
headers: headers,
5555
query: request.query,
5656
body: request.body.class == Hash ? T.unsafe(request.body).to_json : request.body,
@@ -119,6 +119,22 @@ def serialized_error(response)
119119
end
120120
body.to_json
121121
end
122+
123+
private
124+
125+
sig do
126+
params(headers: T::Hash[T.any(Symbol, String), T.untyped],
127+
parsed_uri: URI::Generic).returns(T::Hash[T.any(Symbol, String), T.untyped])
128+
end
129+
def append_first_party_development_headers(headers, parsed_uri)
130+
return headers unless headers["Host"]&.include?(".my.shop.dev") || parsed_uri.host&.include?(".my.shop.dev")
131+
132+
# These headers are only used for first party applications in development mode
133+
headers["x-forwarded-host"] = headers["Host"] || parsed_uri.host
134+
headers["Host"] = "app.shop.dev"
135+
136+
headers
137+
end
122138
end
123139
end
124140
end

test/clients/http_client_test.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,58 @@ def test_response_as_struct
289289
assert_equal("nested_value", response.body.key.nested_key)
290290
end
291291

292+
def test_rewrites_my_shop_dev_host_headers_when_present
293+
@success_body = {}
294+
shop = "test-shop.my.shop.dev"
295+
session = ShopifyAPI::Auth::Session.new(shop:, access_token: @token)
296+
297+
expected_headers = @expected_headers.dup
298+
expected_headers["Host"] = "app.shop.dev"
299+
expected_headers["x-forwarded-host"] = shop
300+
301+
stub_request(@request.http_method, "https://#{shop}#{@base_path}/#{@request.path}")
302+
.with(body: @request.body.to_json, query: @request.query, headers: expected_headers)
303+
.to_return(body: "", headers: @response_headers, status: 204)
304+
305+
@client = ShopifyAPI::Clients::HttpClient.new(session:, base_path: @base_path)
306+
@request = ShopifyAPI::Clients::HttpRequest.new(
307+
http_method: :post,
308+
path: "some-path",
309+
body: { foo: "bar" },
310+
body_type: "application/json",
311+
query: { id: 1234 },
312+
extra_headers: { extra: "header", "Host" => shop },
313+
)
314+
315+
verify_http_request
316+
end
317+
318+
def test_appends_host_headers_for_my_shop_dev_request_url
319+
@success_body = {}
320+
shop = "test-shop.my.shop.dev"
321+
session = ShopifyAPI::Auth::Session.new(shop:, access_token: @token)
322+
323+
expected_headers = @expected_headers.dup
324+
expected_headers["Host"] = "app.shop.dev"
325+
expected_headers["x-forwarded-host"] = shop
326+
327+
stub_request(@request.http_method, "https://#{shop}#{@base_path}/#{@request.path}")
328+
.with(body: @request.body.to_json, query: @request.query, headers: expected_headers)
329+
.to_return(body: "", headers: @response_headers, status: 204)
330+
331+
@client = ShopifyAPI::Clients::HttpClient.new(session:, base_path: @base_path)
332+
@request = ShopifyAPI::Clients::HttpRequest.new(
333+
http_method: :post,
334+
path: "some-path",
335+
body: { foo: "bar" },
336+
body_type: "application/json",
337+
query: { id: 1234 },
338+
extra_headers: { extra: "header" },
339+
)
340+
341+
verify_http_request
342+
end
343+
292344
private
293345

294346
def simple_http_test(http_method)

0 commit comments

Comments
 (0)