Skip to content

Commit 7518098

Browse files
committed
feat: include test webhook request in execution response body
1 parent 460b194 commit 7518098

File tree

7 files changed

+88
-12
lines changed

7 files changed

+88
-12
lines changed

lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb

+27
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,32 @@ class ErrorDecorator < BaseDecorator
1111
property :backtrace
1212
end
1313

14+
class HTTPRequestDecorator < BaseDecorator
15+
property :headers, exec_context: :decorator
16+
property :body, exec_context: :decorator
17+
property :url, exec_context: :decorator
18+
19+
def headers
20+
headers_hash = represented.to_hash
21+
headers_hash.keys.each_with_object({}) do | name, new_headers_hash|
22+
new_headers_hash[name] = headers_hash[name].join(", ")
23+
end
24+
end
25+
26+
def body
27+
begin
28+
::JSON.parse(represented.body)
29+
rescue StandardError => e
30+
represented.body
31+
end
32+
end
33+
34+
def url
35+
(represented.uri || represented.path).to_s
36+
end
37+
end
38+
39+
1440
class HTTPResponseDecorator < BaseDecorator
1541
property :status, :getter => lambda { |_| code.to_i }
1642
property :headers, exec_context: :decorator
@@ -33,6 +59,7 @@ def body
3359
end
3460

3561
property :error, :extend => ErrorDecorator, if: lambda { |context| context[:options][:user_options][:show_response] }
62+
property :request, :extend => HTTPRequestDecorator
3663
property :response, :extend => HTTPResponseDecorator, if: lambda { |context| context[:options][:user_options][:show_response] }
3764
property :response_hidden_message, as: :message, exec_context: :decorator, if: lambda { |context| !context[:options][:user_options][:show_response] }
3865

lib/pact_broker/domain/webhook.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def execute pact, verification, options
4646
end
4747

4848
def to_s
49-
"webhook for consumer=#{consumer_name} provider=#{provider_name} uuid=#{uuid} request=#{request}"
49+
"webhook for consumer=#{consumer_name} provider=#{provider_name} uuid=#{uuid}"
5050
end
5151

5252
def consumer_name

lib/pact_broker/domain/webhook_execution_result.rb

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ module Domain
44

55
class WebhookExecutionResult
66

7-
def initialize response, logs, error = nil
7+
def initialize request, response, logs, error = nil
8+
@request = request
89
@response = response
910
@logs = logs
1011
@error = error
@@ -14,6 +15,10 @@ def success?
1415
!@response.nil? && @response.code.to_i < 300
1516
end
1617

18+
def request
19+
@request
20+
end
21+
1722
def response
1823
@response
1924
end

lib/pact_broker/domain/webhook_request.rb

+18-7
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ module PactBroker
1515
module Domain
1616

1717
class WebhookRequestError < StandardError
18-
1918
def initialize message, response
2019
super message
2120
@response = response
2221
end
23-
2422
end
2523

2624
class WebhookResponseWithUtf8SafeBody < SimpleDelegator
@@ -41,6 +39,18 @@ def unsafe_body?
4139
end
4240
end
4341

42+
class WebhookRequestWithRedactedHeaders < SimpleDelegator
43+
def to_hash
44+
__getobj__().to_hash.each_with_object({}) do | (key, values), new_hash |
45+
new_hash[key] = redact?(key) ? ["**********"] : values
46+
end
47+
end
48+
49+
def redact? name
50+
WebhookRequest::HEADERS_TO_REDACT.any?{ | pattern | name =~ pattern }
51+
end
52+
end
53+
4454
class WebhookRequest
4555

4656
include PactBroker::Logging
@@ -95,15 +105,15 @@ def execute_and_build_result pact, verification, options, logs, execution_logger
95105
req = build_request(uri, pact, verification, execution_logger)
96106
response = do_request(uri, req)
97107
log_response(response, execution_logger, options)
98-
result = WebhookExecutionResult.new(response, logs.string)
108+
result = WebhookExecutionResult.new(WebhookRequestWithRedactedHeaders.new(req), response, logs.string)
99109
log_completion_message(options, execution_logger, result.success?)
100110
result
101111
end
102112

103113
def handle_error_and_build_result e, options, logs, execution_logger
104114
log_error(e, execution_logger, options)
105115
log_completion_message(options, execution_logger, false)
106-
WebhookExecutionResult.new(nil, logs.string, e)
116+
WebhookExecutionResult.new(nil, nil, logs.string, e)
107117
end
108118

109119
def build_request uri, pact, verification, execution_logger
@@ -123,11 +133,12 @@ def build_request uri, pact, verification, execution_logger
123133
end
124134

125135
execution_logger.info(req.body) if req.body
136+
logger.info "Making webhook #{uuid} request #{method.upcase} URI=#{uri} headers=#{headers_to_log} (body in debug logs)"
137+
logger.debug "body=#{req.body}"
126138
req
127139
end
128140

129141
def do_request uri, req
130-
logger.info "Making webhook #{uuid} request #{to_s}"
131142
options = PactBroker::BuildHttpOptions.call(uri)
132143
response = Net::HTTP.start(uri.hostname, uri.port, :ENV, options) do |http|
133144
http.request req
@@ -149,8 +160,8 @@ def response_body_hidden_message
149160
end
150161

151162
def log_response_to_application_logger response
152-
logger.info "Received response for webhook #{uuid} status=#{response.code}"
153-
logger.debug "headers=#{response.to_hash}"
163+
logger.info "Received response for webhook #{uuid} status=#{response.code} (headers and body in debug logs)"
164+
logger.debug "headers=#{response.to_hash} "
154165
logger.debug "body=#{response.unsafe_body}"
155166
end
156167

script/seed.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
.create_global_webhook(method: 'GET', url: "http://example.org?consumer=${pactbroker.consumerName}&provider=${pactbroker.providerName}")
4848
.create_certificate(path: 'spec/fixtures/certificates/self-signed.badssl.com.pem')
4949
.create_consumer("Bethtest")
50-
.create_verification_webhook(method: 'POST', url: "http://localhost:9292", body: webhook_body)
50+
.create_verification_webhook(method: 'POST', url: "http://localhost:9292", body: webhook_body, username: "foo", password: "bar")
5151
.create_consumer("Foo")
5252
.create_label("microservice")
5353
.create_provider("Bar")

spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb

+34-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ module Decorators
88

99
describe "to_json" do
1010

11-
let(:webhook_execution_result) { PactBroker::Domain::WebhookExecutionResult.new(response, logs, error)}
11+
let(:webhook_execution_result) { PactBroker::Domain::WebhookExecutionResult.new(request, response, logs, error)}
1212
let(:logs) { "logs" }
1313
let(:headers) { { "Something" => ["blah", "thing"]} }
14+
let(:request) do
15+
req = Net::HTTP::Get.new("http://example.org?foo=bar")
16+
req['Foo'] = ['bar', 'wiffle']
17+
req.body = { foo: 'bar' }.to_json
18+
req
19+
end
1420
let(:response) { double('http_response', code: '200', body: response_body, to_hash: headers) }
1521
let(:response_body) { 'body' }
1622
let(:error) { nil }
@@ -43,6 +49,32 @@ module Decorators
4349
end
4450
end
4551

52+
context "when there is a request" do
53+
it "includes the request URL" do
54+
expect(subject[:request][:url]).to eq "http://example.org?foo=bar"
55+
end
56+
57+
it "includes the request headers" do
58+
expect(subject[:request][:headers][:'foo']).to eq "bar, wiffle"
59+
end
60+
61+
context "when the request body is JSON" do
62+
it "includes the request body as JSON" do
63+
expect(subject[:request][:body]).to include( foo: 'bar' )
64+
end
65+
end
66+
67+
context "when the request body is not json" do
68+
before do
69+
request.body = "<xml></xml>"
70+
end
71+
72+
it "includes the request body as a String" do
73+
expect(subject[:request][:body]).to eq "<xml></xml>"
74+
end
75+
end
76+
end
77+
4678
context "when there is a response" do
4779
it "includes the response code" do
4880
expect(subject[:response][:status]).to eq 200
@@ -51,6 +83,7 @@ module Decorators
5183
it "includes the response headers" do
5284
expect(subject[:response][:headers]).to eq :'Something' => "blah, thing"
5385
end
86+
5487
it "includes the response body" do
5588
expect(subject[:response][:body]).to eq response_body
5689
end

spec/support/test_data_builder.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ def create_triggered_webhook params = {}
294294
def create_webhook_execution params = {}
295295
params.delete(:comment)
296296
logs = params[:logs] || "logs"
297-
webhook_execution_result = PactBroker::Domain::WebhookExecutionResult.new(OpenStruct.new(code: "200"), logs, nil)
297+
webhook_execution_result = PactBroker::Domain::WebhookExecutionResult.new(nil, OpenStruct.new(code: "200"), logs, nil)
298298
@webhook_execution = PactBroker::Webhooks::Repository.new.create_execution @triggered_webhook, webhook_execution_result
299299
created_at = params[:created_at] || @pact.created_at + Rational(1, 86400)
300300
set_created_at_if_set created_at, :webhook_executions, {id: @webhook_execution.id}

0 commit comments

Comments
 (0)