pact-foundation / pact-reference

Reference implementations for the pact specifications
https://pact.io
MIT License
91 stars 46 forks source link

Broker URL does not support context paths #220

Closed mefellows closed 1 year ago

mefellows commented 1 year ago

Given a base URL of HOST/path, when the broker client navigates the HAL paths it joins the given Base URL with the path defined in the HAL response. This results in duplicate context paths in subsequent requests:

See the following slightly modified log (for readability):

Verifier Output
---------------

Failures:

1) Failed to load pact - Could not load pacts from the pact broker 'https://notarealhost/pactbroker/'

There were 1 pact failures

Verifier Logs
-------------
2022-09-22T08:41:28.393792Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier: fetch_pacts(source=PactBrokerWithDynamicConfiguration(https://notarealhost/pactbroker/, provider_name='MerchantsCore', enable_ending=false, include_wip_since=None, provider_tags=[], provider_branch=None, consumer_version_selectors='[ConsumerVersionSelector { consumer: None, tag: None, fallback_tag: None, latest: Some(true), deployed_or_released: None, deployed: None, released: None, environment: None, main_branch: None, branch: None, matching_branch: None }], auth=None'), consumers=[])
2022-09-22T08:41:28.393858Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier: fetch_pact(source=PactBrokerWithDynamicConfiguration(https://notarealhost/pactbroker/, provider_name='MerchantsCore', enable_ending=false, include_wip_since=None, provider_tags=[], provider_branch=None, consumer_version_selectors='[ConsumerVersionSelector { consumer: None, tag: None, fallback_tag: None, latest: Some(true), deployed_or_released: None, deployed: None, released: None, environment: None, main_branch: None, branch: None, matching_branch: None }], auth=None'))
2022-09-22T08:41:28.393934Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: fetch_pacts_dynamically_from_broker(broker_url='https://notarealhost/pactbroker/', provider_name='MerchantsCore', pending=false, include_wip_pacts_since=None, provider_tags: [], consumer_version_selectors: [ConsumerVersionSelector { consumer: None, tag: None, fallback_tag: None, latest: Some(true), deployed_or_released: None, deployed: None, released: None, environment: None, main_branch: None, branch: None, matching_branch: None }], auth=User(none, [no password]))
2022-09-22T08:41:28.407707Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: navigate(link='pb:provider-pacts-for-verification', template_values={"provider": "MerchantsCore"})
2022-09-22T08:41:28.407743Z  INFO ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: Fetching path '/' from pact broker
2022-09-22T08:41:28.408178Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::pool: checkout waiting for idle connection: ("https", notarealhost)
2022-09-22T08:41:28.408310Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: reqwest::connect: starting new connection: https://notarealhost/    
2022-09-22T08:41:28.408415Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::connect::http: Http::connect; scheme=Some("https"), host=Some("notarealhost"), port=None
2022-09-22T08:41:28.427866Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::connect::http: connecting to 10.60.132.36:443
2022-09-22T08:41:28.428570Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: mio::poll: registering event source with poller: token=Token(0), interests=READABLE | WRITABLE    
2022-09-22T08:41:28.475216Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::connect::http: connected to 10.60.132.36:443
2022-09-22T08:41:28.475331Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::hs: No cached session for DnsName(DnsName(DnsName("notarealhost")))    
2022-09-22T08:41:28.475585Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::hs: Not resuming any session    
2022-09-22T08:41:28.475913Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::hs: Sending ...
2022-09-22T08:41:28.610819Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::hs: ALPN protocol is None    
2022-09-22T08:41:28.610835Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::hs: Using ciphersuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    
2022-09-22T08:41:28.610890Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::tls12::server_hello: Server supports tickets    
2022-09-22T08:41:28.653907Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::tls12: ECDHE curve is ECParameters { curve_type: NamedCurve, named_group: secp256r1 }    
2022-09-22T08:41:28.654245Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::tls12: Server DNS name is DnsName(DnsName(DnsName("notarealhost")))    
2022-09-22T08:41:28.740611Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: rustls::client::tls12: Session saved    
2022-09-22T08:41:28.845266Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::pool: pooling idle connection for ("https", notarealhost)
2022-09-22T08:41:28.845302Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: reqwest::async_impl::client: response '200 OK' for https://notarealhost/pactbroker    
2022-09-22T08:41:28.845403Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::utils: with_retries: attempt 2/3 is Ok(Response { url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("notarealhost")), port: None, path: "/pactbroker", query: None, fragment: None }, status: 200, headers: {"server": "nginx", "date": "Thu, 22 Sep 2022 08:41:29 GMT", "content-type": "application/hal+json;charset=utf-8", "content-length": "5028", "status": "200 OK", "vary": "Accept", "x-content-type-options": "nosniff", "x-pact-broker-version": "2.102.2", "x-powered-by": "Phusion Passenger 5.3.7", "x-kong-upstream-latency": "8", "x-kong-proxy-latency": "1", "via": "kong/2.8.1"} })
2022-09-22T08:41:28.846124Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: fetch_link(link='pb:provider-pacts-for-verification', template_values={"provider": "MerchantsCore"})
2022-09-22T08:41:28.846177Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: fetch_url(link=Link { name: "pb:provider-pacts-for-verification", href: Some("https://notarealhost/pactbroker/pacts/provider/{provider}/for-verification"), templated: true, title: Some("Pact versions to be verified for the specified provider") }, template_values={"provider": "MerchantsCore"})
2022-09-22T08:41:28.846184Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: Link URL is templated
2022-09-22T08:41:28.846213Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: templated URL = https://notarealhost/pactbroker/pacts/provider/{provider}/for-verification
2022-09-22T08:41:28.847602Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: Looking up value for key 'provider'
2022-09-22T08:41:28.847614Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: final URL = https://notarealhost/pactbroker/pacts/provider/MerchantsCore/for-verification
2022-09-22T08:41:28.847681Z  INFO ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::pact_broker: Fetching path '/pactbroker/pacts/provider/MerchantsCore/for-verification' from pact broker
2022-09-22T08:41:28.847716Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::pool: take? ("https", notarealhost): expiration = Some(90s)
2022-09-22T08:41:28.847758Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::pool: reuse idle connection for ("https", notarealhost)
2022-09-22T08:41:28.940398Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::pool: put; add idle connection for ("https", notarealhost)
2022-09-22T08:41:28.940414Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: hyper::client::pool: pooling idle connection for ("https", notarealhost)
2022-09-22T08:41:28.940422Z DEBUG ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: reqwest::async_impl::client: response '404 Not Found' for https://notarealhost/pactbroker/pactbroker/pacts/provider/MerchantsCore/for-verification    
2022-09-22T08:41:28.940435Z TRACE ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier::utils: with_retries: attempt 2/3 is Ok(Response { url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("notarealhost")), port: None, path: "/pactbroker/pactbroker/pacts/provider/MerchantsCore/for-verification", query: None, fragment: None }, status: 404, headers: {"server": "nginx", "date": "Thu, 22 Sep 2022 08:41:29 GMT", "content-type": "application/hal+json;charset=utf-8", "content-length": "0", "status": "404 Not Found", "vary": "Accept", "x-content-type-options": "nosniff", "x-pact-broker-version": "2.102.2", "x-powered-by": "Phusion Passenger 5.3.7", "x-kong-upstream-latency": "2", "x-kong-proxy-latency": "0", "via": "kong/2.8.1"} })
2022-09-22T08:41:28.940827Z ERROR ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_verifier: Failed to load pact - \x1b[31mCould not load pacts from the pact broker 'https://notarealhost/pactbroker/'\x1b[0m
2022-09-22T08:41:28.940881Z  WARN ThreadId(01) pactffi_verifier_execute{handle=0x19ff671b120}: pact_matching::metrics: 

In this case, the URL given is https://notarealhost/pactbroker/, the HAL link is https://notarealhost/pactbroker/pacts/provider/{provider}/for-verification and the constructed URL is https://notarealhost/pactbroker/pactbroker/pacts/provider/MerchantsCore/for-verification (note the duplicate path).

I believe rather than joining the user defined BaseURL and extracting paths from the HAL resources, we should just follow the fully qualified HAL resources. Is there a reason (e.g. security) that we're not doing this?

rholshausen commented 1 year ago

Not for security, it makes testing easier.

mefellows commented 1 year ago

Thanks!