Mockintosh: HTTP Request Matching

​ In this part we will talk about the HTTP request matching in Mockintosh. Let's get started with path matching. ​

Path Matching

​ You can define variables as path segments through templating.

services:
    - port: 8081
      endpoints:
          - path: "/example/path/{{my_variable}}/lastsegment"
            response: "my_variable is captured: {{my_variable}}"

This path is translated into a regular expression that matches everything in the third segment. This is displayed through the verbose flag of Mockintosh. ​ So a request with path localhost:8081/example/path/some-value/lastsegment returns a my_variable is captured: some-value response. ​ For a request like localhost:8081/example/path/some-value/different, you would get a 404 response. All the segments except some-value are static values, and the last segment doesn't match the requested path.

You can also use multiple variable declarations in a single segment. Such a usage is automatically translated into the proper regular expression capture groups.

services:
    - port: 8081
      endpoints:
          - path: "/example/path/{{x}}-middle-{{y}}/lastsegment"
            response: "x is: {{x}} and y is {{y}}"

Display: GET /example/path/([^/]+)-middle-([^/]+)/lastsegment ​ So a request like GET /example/path/value1-middle-value2/lastsegment you would get x is: value1 and y is: value2 as the response. ​ It's possible to define custom regular expression path matching rules using the regEx template helper.

services:
    - port: 8081
      endpoints:
          - path: "/example/path/{{regEx '(\\d)' 'x'}}/lastsegment"
            response: "x is: {{x}}"

For example, this path only matches to the requests if the third path segment is a digit. Otherwise it returns a 404. ​ Note that: Using the regEx helper in any places that request matching through templating is possible. ​

Matching HTTP Methods

services:
    - port: 8081
      endpoints:
          - path: "/example"
            method: GET
            response: "Matched to GET /example"
          - path: "/example"
            method: POST
            response: "Matched to POST /example"
          - path: "/example"
            method: PUT
            response: "Matched to PUT /example"
          - path: "/example"
            method: PATCH
            response: "Matched to PATCH /example"

​ The default HTTP method for an endpoint is GET. You can choose the HTTP method for the endpoint using the method field. ​ In this example, there are endpoints to match GET, POST, PUT and PATCH HTTP methods for the same /example path. But if you request DELETE /example, you get a 405 response. ​

Query String Matching

If query string parameters are defined under the queryString field as key-value pairs then the request matching mechanism expects to have those proper key-value pairs in the query string otherwise it responds with a 400.

services:
    - port: 8081
      endpoints:
          - path: "/static-value" # static value endpoint
            method: GET
            queryString:
                param1: myValue
            response:
                body: "matched with static value: {{request.queryString.paraml}}"
                status: 200
          - path: "/alternative" # first alternative endpoint
            method: GET
            queryString:
                param1: my Value
                param2: "{{myVar}}"
                param3: "{{regEX 'prefix-(.+)-suffix' 'myCapturedVar'}}"
            response:
                body: "query string match: {{request.queryString.param1}} {{myVar}} {{myCapturedVar}}"
                status: 2-1
          - path: "/alternative" # second alternative endpoint
            method: GET
            queryString:
                param4: another query string
            response:
                body: "param4 request query string: {{request.queryString.param4}}"

​ So as you can see from this example, there can be multiple definitions of a path with the same HTTP method but different query string expectations. Mockintosh will try to match one of those alternatives of the same endpoint and will respond with a 400 in case of a match failure. ​ The static value endpoint expecting to have my Value as the query string parameter 1 and my Value only. ​ The first alternative endpoint expects to see two additional query string parameters, parameter 2 and parameter 3. These should match accordingly in terms of the regular expressions. ​ For the second alternative endpoint, there is only one required query string parameter: the static value another query string.

Matching Headers

Similar to query string matching, if the headers are defined under the headers field as key-value pairs, then the request matching mechanism expects to have those proper key-value pairs in the headers otherwise it responds with a 400.

services:
    - port: 8081
      endpoints:
          - path: "/alternative"
            method: GET
            headers:
                hdr1: myValue
                hdr2: "{{myVar}}"
                hdr3: "{{regEX 'prefix-(.+)-suffix' 'myCapturedVar'}}"
            response:
                body: "headers match: {{request.headers.hdr1}} {{myVar}} {{myCapturedVar}}"
                status: 201
                headers:
                    Set-Cookie:
                        - name1={{request.headers.hdr2}}
                        - name2={{request.headers.hdr3}}
          - path: "/alternative"
            headers:
                hdr4: another header
            response:
                body: "hdr4 request header: {{request.headers.hdr4}}"
                headers:
                    hdr4: "hdr4 request header: {{request.headers.hdr4}}"

​ It's also possible to pass any component of the HTTP request to response headers using the request object. You can even set the cookies using the references in the request as shown in the example. ​

Body Matching - Plain Text

​ The body field can either be plain text, or a JSON schema, or a list of URL encoded or multipart key-value pairs. Similar to query string matching, the request body has to match the description in the body field. If there are no matches, then the response is 400.

services:
    - name: Mock for Service1
      port: 8081
      endpoints:
          - path: "/example"
            method: POST
            body:
                text: { { regEx 'expectedval-(.+)' 'namedValue' } }

​ In this example, body is a plain text that should start with the expectedval- prefix. Otherwise, the request is not matched. ​

Body Matching - Multipart & URL Encoded

​ In this example, the body field is detailed into a list of urlencoded or multipart key-value pairs.

services:
    - port: 8081
      endpoints:
          - path: "/body-urlencoded"
            method: POST
            body:
                urlencoded:
                    param1: myValue
                    param2: "{{myVar}}"
                    param3: "{{regEx 'prefix-(.+)-suffix' 'myCapturedVar'}}"
          - path: "/body-multipart"
            method: POST
            body:
                multipart:
                    param1: myValue
                    param2: "{{myVar}}"
                    param3: "{{regEx 'prefix-(.+)-suffix' 'myCapturedVar'}}"

​ For the first endpoint, these three URL encoded form-data parameters are expected to match, and for the second endpoint, these three URL multipart form-data parameters are expected to match. ​

Body Matching - JSON Schema

In this example, the body field is a JSON schema and it describes a required field for the incoming JSON payload. It matches only if the request body (which is a JSON string) contains the somekey field.

services:
    - name: Mock for Service1
      port: 8081
      endpoints:
          - path: "/example"
            method: POST
            body:
                schema:
                    type: object
                    properties:
                        somekey: {}
                    required:
                        - somekey
            response: "example: body JSON schema matched"

Support

You can view these examples in action in this video, and learn more at Mockintosh and UP9. Join our community Slack at up9.slack.com.