diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c74a59..d915bbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # CHANGELOG +## v3.7.2 + +* Fix wrong AWS signatures by generating the json before passing it to http-rb + ## v3.7.1 * Fix thread-safety issue of http-rb diff --git a/lib/search_flip/aws_sigv4_plugin.rb b/lib/search_flip/aws_sigv4_plugin.rb index 3fd61ce..b0336e9 100644 --- a/lib/search_flip/aws_sigv4_plugin.rb +++ b/lib/search_flip/aws_sigv4_plugin.rb @@ -37,7 +37,6 @@ def call(request, method, uri, options = {}) } signature_request[:body] = options[:body] if options.key?(:body) - signature_request[:body] = options[:json].respond_to?(:to_str) ? options[:json] : JSON.generate(options[:json]) if options[:json] signature = signer.sign_request(signature_request) diff --git a/lib/search_flip/http_client.rb b/lib/search_flip/http_client.rb index 132f31f..5ac60ee 100644 --- a/lib/search_flip/http_client.rb +++ b/lib/search_flip/http_client.rb @@ -58,9 +58,22 @@ class << self private def execute(method, uri, options = {}) - final_request = plugins.inject(self) { |res, cur| cur.call(res, method, uri, options) } + opts = options.dup + final_request = self + + if opts[:json] + # Manually generate and pass the json body to http-rb to guarantee that + # we have the same json which is used for aws signatures and to + # guarantee that json is always generated as stated in the config + + opts[:body] = JSON.generate(opts.delete(:json)) + final_request = final_request.headers(content_type: "application/json") + end + + final_request = plugins.inject(final_request) { |res, cur| cur.call(res, method, uri, opts) } final_request = final_request.headers({}) # Prevent thread-safety issue of http-rb: https://github.com/httprb/http/issues/558 - response = final_request.request.send(method, uri, options) + + response = final_request.request.send(method, uri, opts) raise SearchFlip::ResponseError.new(code: response.code, body: response.body.to_s) unless response.status.success? diff --git a/lib/search_flip/version.rb b/lib/search_flip/version.rb index c2f1185..567962d 100644 --- a/lib/search_flip/version.rb +++ b/lib/search_flip/version.rb @@ -1,3 +1,3 @@ module SearchFlip - VERSION = "3.7.1" + VERSION = "3.7.2" end diff --git a/spec/search_flip/aws_sigv4_plugin_spec.rb b/spec/search_flip/aws_sigv4_plugin_spec.rb index 8d2ed33..bd8828f 100644 --- a/spec/search_flip/aws_sigv4_plugin_spec.rb +++ b/spec/search_flip/aws_sigv4_plugin_spec.rb @@ -29,15 +29,17 @@ end it "feeds the http method, full url and body to the signer" do + body = JSON.generate(key: "value") + signing_request = { http_method: "GET", url: "http://localhost/index?param=value", - body: JSON.generate(key: "value") + body: body } expect(plugin.signer).to receive(:sign_request).with(signing_request).and_call_original - plugin.call(client, :get, "http://localhost/index", params: { param: "value" }, json: { key: "value" }) + plugin.call(client, :get, "http://localhost/index", params: { param: "value" }, body: body) end end end diff --git a/spec/search_flip/http_client_spec.rb b/spec/search_flip/http_client_spec.rb index b850c85..33ef2c4 100644 --- a/spec/search_flip/http_client_spec.rb +++ b/spec/search_flip/http_client_spec.rb @@ -36,6 +36,12 @@ def initialize expect(SearchFlip::HTTPClient.new.send(method, "http://localhost/path", body: "body", params: { key: "value" }).body.to_s).to eq("success") end + + it "generates json, passes it as body and sets the content type when the json option is used" do + stub_request(method, "http://localhost/path").with(body: '{"key":"value"}', headers: { "Content-Type" => "application/json" }).to_return(body: "success") + + expect(SearchFlip::HTTPClient.new.send(method, "http://localhost/path", json: { "key" => "value" }).body.to_s).to eq("success") + end end end