Skip to content

Commit

Permalink
feat(custom provider header): Allow a --custom-provider-header to be …
Browse files Browse the repository at this point in the history
…specified

This header will be added to the replayed requests AND the provider state setup request.
It is intended to allow valid authorization credentials to be used in the situation where
authorization cannot be turned off in the provider when verifying pacts.
  • Loading branch information
bethesque committed Aug 8, 2017
1 parent b4bee08 commit e3ea6fa
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 3 deletions.
33 changes: 33 additions & 0 deletions lib/pact/provider_verifier/add_header_middlware.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Pact
module ProviderVerifier
class AddHeaderMiddlware

def initialize app, headers
@app = app
@headers = headers
end

def call env
@app.call(add_headers(env))
end

def add_headers env
new_env = env.dup
@headers.each_pair do | key, value |
header_name = "HTTP_#{key.upcase.gsub("-", "_")}"
warn_about_header_replacement key, new_env[header_name], value
new_env[header_name] = value
end
new_env
end

def warn_about_header_replacement header_name, existing_value, new_value
if existing_value.nil?
$stderr.puts "WARN: Adding header '#{header_name}: #{new_value}' to replayed request. This header did not exist in the pact, and hence this test cannot confirm that the request will work in real life."
else
$stdout.puts "INFO: Replacing header '#{header_name}: #{existing_value}' with '#{header_name}: #{new_value}'"
end
end
end
end
end
19 changes: 16 additions & 3 deletions lib/pact/provider_verifier/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'net/https'
require 'faraday_middleware'
require 'json'
require 'pact/provider_verifier/add_header_middlware'

module Pact
module ProviderVerifier
Expand Down Expand Up @@ -33,16 +34,23 @@ def verify_pacts
proxy_pact_helper = File.expand_path(File.join(File.dirname(__FILE__), "pact_helper.rb"))
ENV['PROVIDER_STATES_SETUP_URL'] = @options.provider_states_setup_url
ENV['VERBOSE_LOGGING'] = @options.verbose if @options.verbose
ENV['CUSTOM_PROVIDER_HEADER'] = @options.custom_provider_header if @options.custom_provider_header
provider_base_url = @options.provider_base_url

provider_application_version = @options.provider_app_version
publish_results = @options.publish_verification_results

rack_reverse_proxy = Rack::ReverseProxy.new do
reverse_proxy '/', provider_base_url
end

if @options.custom_provider_header
rack_reverse_proxy = Pact::ProviderVerifier::AddHeaderMiddlware.new(rack_reverse_proxy, parse_header)
end

Pact.service_provider "Running Provider Application" do
app do
Rack::ReverseProxy.new do
reverse_proxy '/', provider_base_url
end
rack_reverse_proxy
end

if provider_application_version
Expand Down Expand Up @@ -74,6 +82,11 @@ def verify_pacts
exit exit_statuses.count{ | status | status != 0 }
end

def parse_header
header_name, header_value = @options.custom_provider_header.split(":", 2).collect(&:strip)
{header_name => header_value}
end

def print_deprecation_note
if @options.provider_states_url
$stderr.puts "The --provider-states-url option is deprecated and the URL endpoint can be removed from the application"
Expand Down
1 change: 1 addition & 0 deletions lib/pact/provider_verifier/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CLI < Thor
method_option :broker_username, aliases: "-n", desc: "Pact Broker username", :required => false
method_option :broker_password, aliases: "-p", desc: "Pact Broker password", :required => false
method_option :verbose, aliases: "-v", desc: "Verbose output", :required => false
method_option :custom_provider_header, desc: "Header to add to provider state set up and pact requests. eg 'Authorization: Basic cGFjdDpwYWN0'", :required => false
method_option :provider_states_url, aliases: "-s", desc: "DEPRECATED", :required => false

def verify
Expand Down
19 changes: 19 additions & 0 deletions lib/pact/provider_verifier/set_up_provider_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def post_to_provider_state
connection = Faraday.new(:url => provider_states_setup_url)
connection.post do |req|
req.headers["Content-Type"] = "application/json"
add_custom_provider_header req
req.body = {consumer: consumer, state: provider_state, states: [provider_state] }.to_json
end
end
Expand All @@ -48,6 +49,24 @@ def verbose?
ENV['VERBOSE_LOGGING']
end

def provider_header_set?
ENV.fetch('CUSTOM_PROVIDER_HEADER', '') != ''
end

def provider_header_name
ENV['CUSTOM_PROVIDER_HEADER'].split(":", 2)[0]
end

def provider_header_value
ENV['CUSTOM_PROVIDER_HEADER'].split(":", 2)[1]
end

def add_custom_provider_header request
if provider_header_set?
request[provider_header_name] = provider_header_value
end
end

def check_for_error response
if response.status >= 300
raise SetUpProviderStateError.new("Error setting up provider state '#{provider_state}' for consumer '#{consumer}' at #{provider_states_setup_url}. response status=#{response.status} response body=#{response.body}")
Expand Down
24 changes: 24 additions & 0 deletions spec/integration_with_custom_header_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
describe "pact-provider-verifier with basic auth" do
before(:all) do
@pipe = IO.popen("USE_BASIC_AUTH=true bundle exec rackup -p 4567 spec/support/config.ru")
sleep 2
end

context "with --custom-provider-header specified" do

subject { `bundle exec bin/pact-provider-verifier --custom-provider-header "Authorization: Basic cGFjdDpwYWN0" -a 1.0.100 --provider-base-url http://localhost:4567 --pact-urls ./test/me-they.json --provider_states_setup_url http://localhost:4567/provider-state -v` }

it "exits with a 0 exit code" do
subject
expect($?).to eq 0
end

it "the output contains a success message" do
expect(subject).to include "2 interactions, 0 failures"
end
end

after(:all) do
Process.kill 'KILL', @pipe.pid
end
end
46 changes: 46 additions & 0 deletions spec/lib/pact/provider_verifier/add_header_middlware_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'pact/provider_verifier/add_header_middlware'

module Pact
module ProviderVerifier
describe AddHeaderMiddlware do
describe "call" do
let(:target_app) { double(:app, call: nil) }
let(:middlware) { AddHeaderMiddlware.new(target_app, headers) }
let(:headers) { {'Foo-Bar' => 'foo'} }

before do
allow($stdout).to receive(:puts)
allow($stderr).to receive(:puts)
end

it "keeps the existing headers" do
expect(target_app).to receive(:call) do | env |
expect(env['MOO']).to eq 'bar'
end
middlware.call('MOO' => 'bar')
end

it "adds the headers to the env" do
expect(target_app).to receive(:call) do | env |
expect(env['HTTP_FOO_BAR']).to eq 'foo'
end
middlware.call({'HTTP_FOO_BAR' => 'ick'})
end

context "when the specified header does not already exist" do
it "warns the user" do
expect($stderr).to receive(:puts).with(/WARN: Adding header 'Foo-Bar: foo'/)
middlware.call({})
end
end

context "when the specified header already exists" do
it "notifies the user" do
expect($stdout).to receive(:puts).with(/INFO: Replacing header 'Foo-Bar: wiffle' with 'Foo-Bar: foo'/)
middlware.call({'HTTP_FOO_BAR' => 'wiffle' })
end
end
end
end
end
end
6 changes: 6 additions & 0 deletions spec/support/config.ru
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
require_relative 'provider'

if ENV['USE_BASIC_AUTH'] == 'true'
use Rack::Auth::Basic, "Restricted Area" do |username, password|
username == 'pact' and password == 'pact'
end
end

run Provider

0 comments on commit e3ea6fa

Please sign in to comment.