pact-foundation / pact-stub-server

Standalone pact stub server
MIT License
75 stars 19 forks source link

Regex matching does not work for query params #33

Closed oliverlockwood closed 4 years ago

oliverlockwood commented 4 years ago

Ultimately I would like to define a pact which returns a given payload, for matching the following:

/api/test?firstParam=SPECIFIC&firstParam=<any number>

In the interactions block of my pact JSON, I tried to follow the description given in the V3 Pact specification, and I configured an entry like:

        {
            "description": "regex matching of query params",
            "provider_state": "testing",
            "request": {
                "method": "GET",
                "matchingRules": {
                    "path": {
                        "matchers": [
                            {
                                "match": "regex",
                                "regex": "/api/test"
                            }
                        ]
                    },
                    "query": {
                        "firstParam": {
                            "matchers": [
                                {
                                    "match": "regex",
                                    "regex": ".*"
                                }
                            ]
                        },
                        "secondParam": {
                            "matchers": [
                                {
                                    "match": "regex",
                                    "regex": ".*"
                                }
                            ]
                        }
                    }
                }
            },
            "response": {
                "status": 200,
                "headers": {
                    "Content-Type": "application/json"
                },
                "body": {
                    "fred": "hi"
                }
            }
        }

In case the query was being handled as a pure string, as the v2 specification seems to suggest it used to be, I then tried changing the query block to instead be:

                    "query": {
                        "matchers": [
                            {
                                "match": "regex",
                                "regex": ".*"
                            }
                        ]
                    }

In both cases, hitting /api/test returns just fine, but adding any query parameters returns a 404 instead.

Maybe I'm missing some nuance of the Rust implementation which I understand this stub server to be built on (https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_matching)

Or maybe there's a bug.

I would welcome your views.

oliverlockwood commented 4 years ago

I eventually figured this out. For the value it may give to others encountering this post, I shall explain here.

If you want a matchingRule to be used, you also have to configure a (completely pointless as its value is ignored!) static entry. To satisfy my original need the required interaction is:

        {
            "description": "regex matching of query params",
            "provider_state": "testing",
            "request": {
                "method": "GET",
                "path": "/api/test",
                "query": {
                    "firstParam": "SPECIFIC",
                    "secondParam": "Pointless Meaningless Ignored Value"
                },
                "matchingRules": {
                    "query": {
                        "secondParam": {
                            "matchers": [
                                {
                                    "match": "regex",
                                    "regex": ".*"
                                }
                            ]
                        }
                    }
                }
            },
            "response": {
                "status": 200,
                "headers": {
                    "Content-Type": "application/json"
                },
                "body": {
                    "fred": "hi"
                }
            }
        }

The fact remains that:

  1. This behaviour is unintuitive
  2. The logs say things like: 19:34:21 [INFO] comparing to expected Request ( method: GET, path: /api/test, query: None, headers: None, body: Missing ) and give no information on matchingRules whatsoever, so debugging matchingRules is largely a matter of guesswork.

Could some improvement perhaps be made on this basis?

uglyog commented 4 years ago

Pact files are normally used to verify both a consumer and provider. That is why an expected request is required, so when a provider is verified a correct request can be made. The matchers are annotations to how elements are compared, not what needs to be compared. So without the query parameters defined, the pact matcher does not know to compare them.

The stub server uses the pact libraries, so that behaviour can't be changed.