mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.54k stars 1.06k forks source link

retrieveRecordedExpectations of format.Json not consistent when downstream returns different content-type values #1160

Closed RamiaSaidawi closed 2 years ago

RamiaSaidawi commented 2 years ago

Describe the issue When printing the recorded JSON, i get different schema

MockServerClient(MOCK_SERVER_HOST_NAME,MOCK_SERVER_PORT)
                .retrieveRecordedExpectations(
                    null,
                    Format.JSON
                )

sometimes i get this:

{
    "id": "...",
    "priority": 0,
    "httpRequest": {
        "method": "GET",
        "path": "......",
        "headers": { 
            "Content-Type": [ "application/json; charset=UTF-8" ],
            "Accept": [ "*/*" ],
            "jwt": [ "..." ],
            "Host": [ "localhost:55000" ],
            "Connection": [ "Keep-Alive" ],
            "Accept-Encoding": [ "gzip,deflate" ],
            "content-length": [ "0" ]
        },
        "keepAlive": true,
        "secure": false
    },
    "httpResponse": {
        "statusCode": 200,
        "reasonPhrase": "Ok",
        "headers": {
            "Date": [ "Sat, 29 Jan 2022 21:26:00 GMT" ],
            "Content-Type": [ "application/json" ],
            "Content-Length": [ "146" ],
            "Connection": [ "keep-alive" ],
            "Vary": [ "Origin" ]
        },
        "body": {
            "contentType": "application/json",
            "type": "JSON",
            "json": {
                            .... My api response ...
            },
            "rawBytes": "......"
        }
    },
    "times": {
        "remainingTimes": 1
    },
    "timeToLive": {
        "unlimited": true
    }
}

and sometimes i get

{
    "id": "...",
    "priority": 0,
    "httpRequest": {
        "method": "GET",
        "path": "......",
        "headers": {
            "Content-Type": [ "application/json; charset=UTF-8" ],
            "Accept": [ "*/*" ],
            "jwt": [ "..." ],
            "Host": [ "localhost:55000" ],
            "Connection": [ "Keep-Alive" ],
            "Accept-Encoding": [ "gzip,deflate" ],
            "content-length": [ "0" ]
        },
        "keepAlive": true,
        "secure": false
    },
    "httpResponse": {
        "statusCode": 200,
        "reasonPhrase": "Ok",
        "headers": {
            "Date": [ "Sat, 29 Jan 2022 21:26:00 GMT" ],
            "Content-Type": [ "application/json; charset=utf-8" ],
            "Content-Length": [ "2239" ],
            "Connection": [ "keep-alive" ],
            "Vary": [ "Origin" ]
        },
        "body": {
            .... My api response body directly, not in json field and no rawBytes...
        }
    },
    "times": {
        "remainingTimes": 1
    },
    "timeToLive": {
        "unlimited": true
    }
}

What you are trying to do i want to use printed expectation json to create my mockserver expectations

MockServer version 5.11.1

To Reproduce

  1. How you are running MockServer (i.e maven plugin, docker, etc) Mockserver as Junit Rule as well as on Docker

  2. Code you used to create expectations see above

  3. What error you saw no error, just not consistent json

Expected behaviour have the same fields returned always for recorded response

"body": {
            "contentType": "application/json",
            "type": "JSON",
            "json": {
                            .... My api response ...
            },
            "rawBytes": "......"
        }

MockServer Log Log output, as INFO level (or lower)

jamesdbloom commented 2 years ago

This is happening because the server your target server is not returning a stable Content-Type sometimes it is "application/json; charset=UTF-8" and sometimes it is "application/json".

This means that some response bodies are serialised as if all the values are default and so the more compressed format is used and some response are serialised in the full format because the contentType field is not the default.

I'm not sure if this should be fixed or not. Ideally it would be fixed in this one case when returning recorded expectations but no in any other scenario when response bodies are being serialised otherwise the logs and UI and other elements would become more complex for scenarios when all default values are used. I'll think about if it is feasible / practical to do this or not without adding lots of complexity.

RamiaSaidawi commented 2 years ago

Thank you for your reply, hope you find a way to force the retrieveRecordedExpectations to be the same so i can build a robest mocking solution