pact_broker 2.19.2 → 2.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/example/README.md +7 -1
  4. data/example/config.ru +2 -3
  5. data/lib/pact_broker/api/contracts/webhook_contract.rb +73 -6
  6. data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +9 -13
  7. data/lib/pact_broker/api/resources/base_resource.rb +3 -3
  8. data/lib/pact_broker/api/resources/pact_webhooks.rb +1 -1
  9. data/lib/pact_broker/api/resources/webhook_execution.rb +5 -2
  10. data/lib/pact_broker/configuration.rb +9 -1
  11. data/lib/pact_broker/doc/views/webhooks.markdown +23 -0
  12. data/lib/pact_broker/domain/webhook_request.rb +49 -37
  13. data/lib/pact_broker/locale/en.yml +2 -0
  14. data/lib/pact_broker/version.rb +1 -1
  15. data/lib/pact_broker/webhooks/check_host_whitelist.rb +22 -0
  16. data/lib/pact_broker/webhooks/render.rb +23 -0
  17. data/lib/pact_broker/webhooks/service.rb +2 -1
  18. data/lib/pact_broker/webhooks/webhook.rb +0 -5
  19. data/spec/features/create_webhook_spec.rb +2 -3
  20. data/spec/features/edit_webhook_spec.rb +2 -2
  21. data/spec/features/execute_webhook_spec.rb +32 -1
  22. data/spec/fixtures/webhook_valid.json +1 -1
  23. data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +64 -1
  24. data/spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb +17 -9
  25. data/spec/lib/pact_broker/api/resources/pact_spec.rb +1 -1
  26. data/spec/lib/pact_broker/api/resources/pact_webhooks_spec.rb +3 -3
  27. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -1
  28. data/spec/lib/pact_broker/domain/webhook_request_spec.rb +73 -68
  29. data/spec/lib/pact_broker/webhooks/check_host_whitelist_spec.rb +47 -0
  30. data/spec/lib/pact_broker/webhooks/render_spec.rb +36 -0
  31. data/spec/lib/pact_broker/webhooks/service_spec.rb +7 -0
  32. data/spec/support/shared_examples_for_responses.rb +2 -2
  33. metadata +8 -2
@@ -9,6 +9,8 @@ en:
9
9
  valid_consumer_version_number?: "Consumer version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
10
10
 
11
11
  pact_broker:
12
+ messages:
13
+ response_body_hidden: For security purposes, the response details are not logged. To enable response logging, configure the webhook_host_whitelist property. See /doc/webhooks#whitelist for more information.
12
14
  errors:
13
15
  validation:
14
16
  blank: "cannot be blank."
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.19.2'
2
+ VERSION = '2.20.0'
3
3
  end
@@ -0,0 +1,22 @@
1
+ module PactBroker
2
+ module Webhooks
3
+ class CheckHostWhitelist
4
+
5
+ def self.call(host, whitelist = PactBroker.configuration.webhook_host_whitelist)
6
+ whitelist.select{ | whitelist_host | match?(host, whitelist_host) }
7
+ end
8
+
9
+ def self.match?(host, whitelist_host)
10
+ if whitelist_host.is_a?(Regexp)
11
+ host =~ whitelist_host
12
+ else
13
+ begin
14
+ IPAddr.new(whitelist_host) === IPAddr.new(host)
15
+ rescue IPAddr::Error
16
+ host == whitelist_host
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ module PactBroker
2
+ module Webhooks
3
+ class Render
4
+ def self.call(body, pact, verification = nil, &escaper)
5
+ base_url = PactBroker.configuration.base_url
6
+ params = {
7
+ '${pactbroker.pactUrl}' => PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact),
8
+ '${pactbroker.consumerVersionNumber}' => pact.consumer_version_number
9
+ }
10
+
11
+ if escaper
12
+ params.keys.each do | key |
13
+ params[key] = escaper.call(params[key])
14
+ end
15
+ end
16
+
17
+ params.inject(body) do | body, (key, value) |
18
+ body.gsub(key, value)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -61,7 +61,8 @@ module PactBroker
61
61
 
62
62
  def self.execute_webhook_now webhook, pact
63
63
  triggered_webhook = webhook_repository.create_triggered_webhook(next_uuid, webhook, pact, USER)
64
- webhook_execution_result = execute_triggered_webhook_now triggered_webhook, failure_log_message: "Webhook execution failed"
64
+ options = { failure_log_message: "Webhook execution failed", show_response: PactBroker.configuration.show_webhook_response?}
65
+ webhook_execution_result = execute_triggered_webhook_now triggered_webhook, options
65
66
  if webhook_execution_result.success?
66
67
  webhook_repository.update_triggered_webhook_status triggered_webhook, TriggeredWebhook::STATUS_SUCCESS
67
68
  else
@@ -5,7 +5,6 @@ require 'pact_broker/domain/pacticipant'
5
5
  module PactBroker
6
6
  module Webhooks
7
7
  class Webhook < Sequel::Model
8
-
9
8
  set_primary_key :id
10
9
  associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
11
10
  associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
@@ -84,13 +83,11 @@ module PactBroker
84
83
  is_json_request_body: is_json_request_body
85
84
  }
86
85
  end
87
-
88
86
  end
89
87
 
90
88
  Webhook.plugin :timestamps, :update_on_create=>true
91
89
 
92
90
  class WebhookHeader < Sequel::Model
93
-
94
91
  associate(:many_to_one, :webhook, :class => "PactBroker::Repositories::Webhook", :key => :webhook_id, :primary_key => :id)
95
92
 
96
93
  def self.from_domain name, value, webhook_id
@@ -100,8 +97,6 @@ module PactBroker
100
97
  db_header.webhook_id = webhook_id
101
98
  db_header
102
99
  end
103
-
104
100
  end
105
101
  end
106
-
107
102
  end
@@ -24,7 +24,7 @@ describe "Creating a webhook" do
24
24
 
25
25
  it "returns a JSON content type" do
26
26
  subject
27
- expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
27
+ expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
28
28
  end
29
29
 
30
30
  it "returns the validation errors" do
@@ -43,7 +43,7 @@ describe "Creating a webhook" do
43
43
  }],
44
44
  request: {
45
45
  method: 'POST',
46
- url: 'http://example.org',
46
+ url: 'https://example.org',
47
47
  headers: {
48
48
  :"Content-Type" => "application/json"
49
49
  },
@@ -76,5 +76,4 @@ describe "Creating a webhook" do
76
76
  expect(response_body).to include webhook_hash
77
77
  end
78
78
  end
79
-
80
79
  end
@@ -14,7 +14,7 @@ describe "Creating a webhook" do
14
14
  let(:response_body) { JSON.parse(last_response.body, symbolize_names: true)}
15
15
  let(:webhook_json) do
16
16
  h = load_json_fixture('webhook_valid.json')
17
- h['request']['method'] = 'GET'
17
+ h['request']['url'] = 'https://bar.com'
18
18
  h.to_json
19
19
  end
20
20
 
@@ -55,7 +55,7 @@ describe "Creating a webhook" do
55
55
 
56
56
  it "updates the webhook" do
57
57
  subject
58
- expect(reloaded_webhook.request.method).to eq 'GET'
58
+ expect(reloaded_webhook.request.url).to eq 'https://bar.com'
59
59
  end
60
60
  end
61
61
  end
@@ -23,8 +23,9 @@ describe "Execute a webhook" do
23
23
 
24
24
  context "when the execution is successful" do
25
25
  let!(:request) do
26
- stub_request(:post, /http/).with(body: 'http://example.org/pacts/provider/Bar/consumer/Foo/version/1').to_return(:status => 200)
26
+ stub_request(:post, /http/).with(body: 'http://example.org/pacts/provider/Bar/consumer/Foo/version/1').to_return(:status => 200, body: response_body)
27
27
  end
28
+ let(:response_body) { "webhook-response-body" }
28
29
 
29
30
  it "performs the HTTP request" do
30
31
  subject
@@ -42,6 +43,36 @@ describe "Execute a webhook" do
42
43
  it "saves a WebhookExecution" do
43
44
  expect { subject }.to change { PactBroker::Webhooks::Execution.count }.by(1)
44
45
  end
46
+
47
+ context "when a webhook host whitelist is not configured" do
48
+ before do
49
+ allow(PactBroker.configuration).to receive(:show_webhook_response?).and_return(false)
50
+ end
51
+
52
+ it "does not show any response details" do
53
+ expect(subject.body).to_not include response_body
54
+ end
55
+
56
+ it "does not log any response details" do
57
+ subject
58
+ expect(PactBroker::Webhooks::Execution.order(:id).last.logs).to_not include response_body
59
+ end
60
+ end
61
+
62
+ context "when a webhook host whitelist is configured" do
63
+ before do
64
+ allow(PactBroker.configuration).to receive(:show_webhook_response?).and_return(true)
65
+ end
66
+
67
+ it "includes response details" do
68
+ expect(subject.body).to include response_body
69
+ end
70
+
71
+ it "logs the response details" do
72
+ subject
73
+ expect(PactBroker::Webhooks::Execution.order(:id).last.logs).to include response_body
74
+ end
75
+ end
45
76
  end
46
77
 
47
78
  context "when an error occurs", no_db_clean: true do
@@ -4,7 +4,7 @@
4
4
  }],
5
5
  "request": {
6
6
  "method": "POST",
7
- "url": "http://some.url",
7
+ "url": "HTTPS://some.url",
8
8
  "username": "username",
9
9
  "password": "password",
10
10
  "headers": {
@@ -10,6 +10,7 @@ module PactBroker
10
10
  let(:hash) { JSON.parse(json) }
11
11
  let(:webhook) { PactBroker::Api::Decorators::WebhookDecorator.new(Domain::Webhook.new).from_json(json) }
12
12
  let(:subject) { WebhookContract.new(webhook) }
13
+ let(:matching_hosts) { ['foo'] }
13
14
 
14
15
  def valid_webhook_with
15
16
  hash = load_json_fixture 'webhook_valid.json'
@@ -18,11 +19,17 @@ module PactBroker
18
19
  end
19
20
 
20
21
  describe "errors" do
21
-
22
22
  before do
23
+ PactBroker.configuration.webhook_http_method_whitelist = webhook_http_method_whitelist
24
+ PactBroker.configuration.webhook_host_whitelist = webhook_host_whitelist
25
+ allow(PactBroker::Webhooks::CheckHostWhitelist).to receive(:call).and_return(whitelist_matches)
23
26
  subject.validate(hash)
24
27
  end
25
28
 
29
+ let(:webhook_http_method_whitelist) { ['POST'] }
30
+ let(:whitelist_matches) { ['foo'] }
31
+ let(:webhook_host_whitelist) { [] }
32
+
26
33
  context "with valid fields" do
27
34
  it "is empty" do
28
35
  expect(subject.errors).to be_empty
@@ -81,6 +88,62 @@ module PactBroker
81
88
  end
82
89
  end
83
90
 
91
+ context "with an invalid scheme" do
92
+ let(:json) do
93
+ valid_webhook_with do |hash|
94
+ hash['request']['url'] = 'ftp://foo'
95
+ end
96
+ end
97
+
98
+ it "contains an error for the URL" do
99
+ expect(subject.errors[:"request.url"]).to include "scheme must be https. See /doc/webhooks#whitelist for more information."
100
+ end
101
+ end
102
+
103
+ context "with an HTTP method that is not whitelisted" do
104
+ let(:json) do
105
+ valid_webhook_with do |hash|
106
+ hash['request']['method'] = 'DELETE'
107
+ end
108
+ end
109
+
110
+ context "when there is only one allowed HTTP method" do
111
+ it "contains an error for invalid method" do
112
+ expect(subject.errors[:"request.http_method"]).to include "must be POST. See /doc/webhooks#whitelist for more information."
113
+ end
114
+ end
115
+
116
+ context "when there is more than one allowed HTTP method", pending: "need to work out how to dynamically create this message" do
117
+ let(:webhook_http_method_whitelist) { ['POST', 'GET'] }
118
+
119
+ it "contains an error for invalid method" do
120
+ expect(subject.errors[:"request.http_method"]).to include "must be one of POST, GET"
121
+ end
122
+ end
123
+ end
124
+
125
+ context "when the host whitelist is empty" do
126
+ it "does not attempt to validate the host" do
127
+ expect(PactBroker::Webhooks::CheckHostWhitelist).to_not have_received(:call)
128
+ end
129
+ end
130
+
131
+ context "when the host whitelist is populated" do
132
+ let(:webhook_host_whitelist) { [/foo/, "bar"] }
133
+
134
+ it "validates the host" do
135
+ expect(PactBroker::Webhooks::CheckHostWhitelist).to have_received(:call).with("some.url", webhook_host_whitelist)
136
+ end
137
+
138
+ context "when the host does not match the whitelist" do
139
+ let(:whitelist_matches) { [] }
140
+
141
+ it "contains an error", pending: "need to work out how to do dynamic messages" do
142
+ expect(subject.errors[:"request.url"]).to include "host must be in the whitelist /foo/, \"bar\" . See /doc/webhooks#whitelist for more information."
143
+ end
144
+ end
145
+ end
146
+
84
147
  context "with no URL" do
85
148
  let(:json) do
86
149
  valid_webhook_with do |hash|
@@ -14,10 +14,11 @@ module PactBroker
14
14
  let(:response) { double('http_response', code: '200', body: response_body, to_hash: headers) }
15
15
  let(:response_body) { 'body' }
16
16
  let(:error) { nil }
17
- let(:webhook) { instance_double(PactBroker::Domain::Webhook, uuid: 'some-uuid')}
17
+ let(:webhook) { instance_double(PactBroker::Domain::Webhook, uuid: 'some-uuid') }
18
+ let(:show_response) { true }
18
19
  let(:json) {
19
20
  WebhookExecutionResultDecorator.new(webhook_execution_result)
20
- .to_json(user_options: { base_url: 'http://example.org', webhook: webhook })
21
+ .to_json(user_options: { base_url: 'http://example.org', webhook: webhook, show_response: show_response })
21
22
  }
22
23
 
23
24
  let(:subject) { JSON.parse(json, symbolize_names: true)}
@@ -30,11 +31,7 @@ module PactBroker
30
31
  expect(subject[:_links][:webhook][:href]).to eq 'http://example.org/webhooks/some-uuid'
31
32
  end
32
33
 
33
- it "includes a message about the response being redacted" do
34
- expect(subject[:message]).to match /redacted/
35
- end
36
-
37
- context "when there is an error", pending: "temporarily disabled" do
34
+ context "when there is an error" do
38
35
  let(:error) { double('error', message: 'message', backtrace: ['blah','blah']) }
39
36
 
40
37
  it "includes the message" do
@@ -46,7 +43,7 @@ module PactBroker
46
43
  end
47
44
  end
48
45
 
49
- context "when there is a response", pending: "temporarily disabled" do
46
+ context "when there is a response" do
50
47
  it "includes the response code" do
51
48
  expect(subject[:response][:status]).to eq 200
52
49
  end
@@ -66,8 +63,19 @@ module PactBroker
66
63
  end
67
64
  end
68
65
  end
69
- end
70
66
 
67
+ context "when show_response is false" do
68
+ let(:show_response) { false }
69
+
70
+ it "does not include the response" do
71
+ expect(subject).to_not have_key(:response)
72
+ end
73
+
74
+ it "includes a message about why the response is hidden" do
75
+ expect(subject[:message]).to match /security purposes/
76
+ end
77
+ end
78
+ end
71
79
  end
72
80
  end
73
81
  end
@@ -76,7 +76,7 @@ module PactBroker::Api
76
76
  end
77
77
 
78
78
  it "returns a JSON content type" do
79
- expect(response.headers['Content-Type']).to eq "application/json;charset=utf-8"
79
+ expect(response.headers['Content-Type']).to eq "application/hal+json;charset=utf-8"
80
80
  end
81
81
 
82
82
  it "returns an error message" do
@@ -93,7 +93,7 @@ module PactBroker::Api
93
93
 
94
94
  it "returns a JSON content type" do
95
95
  subject
96
- expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
96
+ expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
97
97
  end
98
98
 
99
99
  it "returns an error message" do
@@ -111,7 +111,7 @@ module PactBroker::Api
111
111
 
112
112
  it "returns a JSON content type" do
113
113
  subject
114
- expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
114
+ expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
115
115
  end
116
116
 
117
117
  it "returns an error message" do
@@ -132,7 +132,7 @@ module PactBroker::Api
132
132
 
133
133
  it "returns a JSON content type" do
134
134
  subject
135
- expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
135
+ expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
136
136
  end
137
137
 
138
138
  it "returns the validation errors" do
@@ -57,7 +57,8 @@ module PactBroker
57
57
  end
58
58
 
59
59
  it "generates a JSON response body for the execution result" do
60
- expect(decorator).to receive(:to_json).with(user_options: { base_url: 'http://example.org', webhook: webhook })
60
+ allow(PactBroker.configuration).to receive(:show_webhook_response?).and_return('foo')
61
+ expect(decorator).to receive(:to_json).with(user_options: { base_url: 'http://example.org', webhook: webhook, show_response: 'foo' })
61
62
  subject
62
63
  end
63
64
 
@@ -69,6 +70,7 @@ module PactBroker
69
70
 
70
71
  context "when execution is not successful" do
71
72
  let(:success) { false }
73
+
72
74
  it "returns a 500 JSON response" do
73
75
  subject
74
76
  expect(last_response.status).to eq 500
@@ -8,9 +8,9 @@ module PactBroker
8
8
  before do
9
9
  allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).and_return('http://example.org/pact-url')
10
10
  allow(PactBroker.configuration).to receive(:base_url).and_return('http://example.org')
11
- allow(PactBroker.logger).to receive(:info).and_call_original
12
- allow(PactBroker.logger).to receive(:debug).and_call_original
13
- allow(PactBroker.logger).to receive(:warn).and_call_original
11
+ allow(PactBroker::Webhooks::Render).to receive(:call) do | content, pact, verification, &block |
12
+ content
13
+ end
14
14
  end
15
15
 
16
16
  let(:username) { nil }
@@ -19,7 +19,8 @@ module PactBroker
19
19
  let(:body) { 'body' }
20
20
  let(:logs) { StringIO.new }
21
21
  let(:execution_logger) { Logger.new(logs) }
22
- let(:options) { {failure_log_message: 'oops'}}
22
+ let(:options) { {failure_log_message: 'oops', show_response: show_response} }
23
+ let(:show_response) { true }
23
24
  let(:pact) { instance_double('PactBroker::Domain::Pact') }
24
25
 
25
26
  subject do
@@ -57,51 +58,37 @@ module PactBroker
57
58
  describe "execute" do
58
59
  let!(:http_request) do
59
60
  stub_request(:post, "http://example.org/hook").
60
- with(:headers => {'Content-Type'=>'text/plain'}, :body => 'body').
61
+ with(:headers => {'Content-Type'=>'text/plain'}, :body => request_body).
61
62
  to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'})
62
63
  end
63
64
 
64
- describe "when the String body contains a ${pactbroker.pactUrl} parameter" do
65
- let!(:http_request) do
66
- stub_request(:post, "http://example.org/hook").
67
- with(:headers => {'Content-Type'=>'text/plain'}, :body => "<xml><url>http://example.org/pact-url</url></xml>").
68
- to_return(:status => 200)
69
- end
70
-
71
- let(:body) { "<xml><url>${pactbroker.pactUrl}</url></xml>" }
65
+ let(:request_body) { 'body' }
72
66
 
73
- it "replaces the token with the live value" do
74
- subject.execute(pact, options)
75
- expect(http_request).to have_been_made
67
+ it "renders the url template" do
68
+ expect(PactBroker::Webhooks::Render).to receive(:call).with("http://example.org/hook", pact) do | content, pact, verification, &block |
69
+ expect(content).to eq "http://example.org/hook"
70
+ expect(pact).to be pact
71
+ expect(verification).to be nil
72
+ expect(block.call("foo bar")).to eq "foo+bar"
73
+ "http://example.org/hook"
76
74
  end
75
+ subject.execute(pact, options)
77
76
  end
78
77
 
79
- describe "when the JSON body contains a ${pactbroker.pactUrl} parameter" do
80
- let!(:http_request) do
81
- stub_request(:post, "http://example.org/hook").
82
- with(:headers => {'Content-Type'=>'text/plain'}, :body => '{"url":"http://example.org/pact-url"}').
83
- to_return(:status => 200)
84
- end
85
-
86
- let(:body) { { url: '${pactbroker.pactUrl}' } }
87
-
88
- it "replaces the token with the live value" do
78
+ context "when the body is a string" do
79
+ it "renders the body template with the String" do
80
+ expect(PactBroker::Webhooks::Render).to receive(:call).with('body', pact)
89
81
  subject.execute(pact, options)
90
- expect(http_request).to have_been_made
91
82
  end
92
83
  end
93
84
 
94
- describe "when the URL contains a ${pactbroker.pactUrl} parameter" do
95
- let!(:http_request) do
96
- stub_request(:post, "http://example.org/hook?url=http%3A%2F%2Fexample.org%2Fpact-url").
97
- to_return(:status => 200)
98
- end
99
-
100
- let(:url) { 'http://example.org/hook?url=${pactbroker.pactUrl}' }
85
+ context "when the body is an object" do
86
+ let(:body) { {"foo" => "bar"} }
87
+ let(:request_body) { '{"foo":"bar"}' }
101
88
 
102
- it "replaces the token with the live value" do
89
+ it "renders the body template with JSON" do
90
+ expect(PactBroker::Webhooks::Render).to receive(:call).with(request_body, pact)
103
91
  subject.execute(pact, options)
104
- expect(http_request).to have_been_made
105
92
  end
106
93
  end
107
94
 
@@ -120,18 +107,11 @@ module PactBroker
120
107
  allow(PactBroker.logger).to receive(:info)
121
108
  allow(PactBroker.logger).to receive(:debug)
122
109
  expect(PactBroker.logger).to receive(:info).with(/response.*200/)
110
+ expect(PactBroker.logger).to receive(:debug).with(/content-type/)
123
111
  expect(PactBroker.logger).to receive(:debug).with(/respbod/)
124
112
  subject.execute(pact, options)
125
113
  end
126
114
 
127
- it "does not write the response body to the exeuction log for security purposes" do
128
- expect(logs).to_not include "An error"
129
- end
130
-
131
- it "logs a message about why there is no response information" do
132
- expect(logs).to include "Webhook response has been redacted temporarily for security purposes"
133
- end
134
-
135
115
  describe "execution logs" do
136
116
 
137
117
  it "logs the request method and path" do
@@ -150,16 +130,38 @@ module PactBroker
150
130
  expect(logs).to include body
151
131
  end
152
132
 
153
- it "logs the response status" do
154
- expect(logs).to include "HTTP/1.0 200"
155
- end
133
+ context "when show_response is true" do
134
+ it "logs the response status" do
135
+ expect(logs).to include "HTTP/1.0 200"
136
+ end
137
+
138
+ it "logs the response headers" do
139
+ expect(logs).to include "Content-Type: text/foo, blah"
140
+ end
156
141
 
157
- it "does not log the response headers" do
158
- expect(logs).to_not include "Content-Type: text/foo, blah"
142
+ it "logs the response body" do
143
+ expect(logs).to include "respbod"
144
+ end
159
145
  end
160
146
 
161
- it "does not log the response body" do
162
- expect(logs).to_not include "respbod"
147
+ context "when show_response is false" do
148
+ let(:show_response) { false }
149
+
150
+ it "does not log the response status" do
151
+ expect(logs).to_not include "HTTP/1.0 200"
152
+ end
153
+
154
+ it "does not log the response headers" do
155
+ expect(logs).to_not include "Content-Type: text/foo, blah"
156
+ end
157
+
158
+ it "does not log the response body" do
159
+ expect(logs).to_not include "respbod"
160
+ end
161
+
162
+ it "logs a message about why the response is hidden" do
163
+ expect(logs).to include "security purposes"
164
+ end
163
165
  end
164
166
 
165
167
  context "when the response code is a success" do
@@ -234,21 +236,6 @@ module PactBroker
234
236
  end
235
237
  end
236
238
 
237
- context "when the request has a JSONable body" do
238
- let(:body) { [{"some": "json"}] }
239
-
240
- let!(:http_request) do
241
- stub_request(:post, "http://example.org/hook").
242
- with(:headers => {'Content-Type'=>'text/plain'}, :body => body.to_json).
243
- to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'})
244
- end
245
-
246
- it "converts the body to JSON before submitting the request" do
247
- subject.execute(pact, options)
248
- expect(http_request).to have_been_made
249
- end
250
- end
251
-
252
239
  context "when the request has a nil body" do
253
240
  let(:body) { nil }
254
241
 
@@ -291,7 +278,7 @@ module PactBroker
291
278
  end
292
279
  end
293
280
 
294
- context "when the response body contains a non UTF-8 character", pending: "execution logs disabled temporarily for security purposes" do
281
+ context "when the response body contains a non UTF-8 character" do
295
282
  let!(:http_request) do
296
283
  stub_request(:post, "http://example.org/hook").
297
284
  to_return(:status => 200, :body => "This has some \xC2 invalid chars")
@@ -316,10 +303,10 @@ module PactBroker
316
303
 
317
304
  before do
318
305
  allow(subject).to receive(:http_request).and_raise(WebhookTestError.new("blah"))
306
+ allow(PactBroker.logger).to receive(:error)
319
307
  end
320
308
 
321
309
  it "logs the error" do
322
- allow(PactBroker.logger).to receive(:error)
323
310
  expect(PactBroker.logger).to receive(:error).with(/Error.*WebhookTestError.*blah/)
324
311
  subject.execute(pact, options)
325
312
  end
@@ -335,6 +322,24 @@ module PactBroker
335
322
  it "logs the failure_log_message" do
336
323
  expect(logs).to include "oops"
337
324
  end
325
+
326
+ context "when show_response is true" do
327
+ it "logs the exception information" do
328
+ expect(logs).to include "blah"
329
+ end
330
+ end
331
+
332
+ context "when show_response is false" do
333
+ let(:show_response) { false }
334
+
335
+ it "does not logs the exception information" do
336
+ expect(logs).to_not include "blah"
337
+ end
338
+
339
+ it "logs a message about why the response is hidden" do
340
+ expect(logs).to include "security purposes"
341
+ end
342
+ end
338
343
  end
339
344
  end
340
345
  end