pythonmockingimposter-patternmountebank

How to record request and reponse using a proxy in Mountebank?


I am creating an imposter process using Mountebank and want to record the request and response. To create a http imposter I used the following CURL command as described in their documentation.

curl -i -X POST -H 'Content-Type: application/json' http://127.0.0.1:2525/imposters --data '{
  "port": 6568,
  "protocol": "http",
  "name": "proxyAlways",
  "stubs": [
    {
      "responses": [
        {
          "proxy": {
            "to": "http://localhost:8000",
            "mode": "proxyAlways",
            "predicateGenerators": [
              {
                "matches": {
                  "method": true,
                  "path": true,
                  "query": true
                }
              }
            ]
          }
        }
      ]
    }
  ]
}'
 

I have another server running at http://localhost:8000 which is listening to all the request coming to port 6568.

Output of my server now:

mb
info: [mb:2525] mountebank v1.6.0-beta.1102 now taking orders - point your browser to http://localhost:2525 for help
info: [mb:2525] POST /imposters
info: [http:6568 proxyAlways] Open for business...
info: [http:6568 proxyAlways] ::ffff:127.0.0.1:55488 => GET /

I want to record all the request and response going around, and unable to do right now. When I enter curl -i -X GET -H 'Content-Type: application/json' http://127.0.0.1:6568/ it is giving me a response but how I do store it?

Also can anyone explain me the meaning of

save off the response in a new stub in front of the proxy response:

(from this Mountebank documentation)


Solution

  • How to store proxy results

    The short answer is that mountebank already is storing it. You can verify that by looking at the output of curl http://localhost:2525/imposters/6568. The real question is how do you replay the stored response?

    The common usage scenario with mountebank proxies is that you record the proxy responses on one running instance of mb, save off the results, and then start the next instance of mb with those saved responses. The way you would do that is to have the system under test talk to service you're trying to stub out via the mountebank proxy under whatever conditions you need it to, and then save off the responses (and their request predicates) by sending an HTTP GET or DELETE to http://localhost:2525/imposters/6568?removeProxies=true&replayable=true. You feed the JSON body of that response into the next mb instance, either through the REST API, or by saving it on disk and starting mountebank with a command of something like mb --configfile savedProxyResults.json. At that point, mountebank is providing the exact same responses to the requests without connecting to the downstream service.

    Proxies create new stubs

    Your last question revolves around understanding how the proxyAlways mode works. The default proxyOnce mode means that the first time a mountebank proxy sees a request that uniquely satisfies a predicate, it queries the downstream service and saves the response. The next time it seems a request that satisfies the exact same predicates, it avoids the downstream call and simply returns the saved result. It only proxies downstream once for the same request. The proxyAlways mode, on the other hand, always sends the requests downstream, and saves a list of responses for the same request.

    To make this clear, in the example you copied we care about the method, path, and query fields on the request, so if we see two requests with exactly the same combination of those three fields, we need to know whether we should send the saved response back or continue to proxy. Imagine we first sent:

    GET /test?q=elephants
    

    The method is GET, the path is /test, and the query is q=elephants. Since this is the first request, we send it to the downstream server, which returns a body of:

    No results
    

    That will be true regardless of which proxy mode you set mountebank to, since it has to query downstream at least once. Now suppose, while we're thinking about it, the downstream service added an elephant, and then our system under test makes the same call:

    GET /test?q=elephants
    

    If we're in proxyOnce mode, the fact that the elephant was added to the real service simply won't matter, we'll continue to return our saved response:

    No results
    

    You'd see the same behavior if you shut the mountebank process down and restarted it as described above. In the config file you saved, you'd see something like this (simplifying a bit):

    "stubs": [
      {
        "predicates": [{
          "deepEquals': {
            "method": "GET",
            "path": "/test",
            "query": { "q": "elephants" }
          }
        }],
        "responses": [
          {
            "is": {
              "body": "No results"
            }
          }
        ]
      }
    ]
    

    There's only the one stub. If, on the other hand, we use proxyAlways, then the second call to the GET /test?q=elephants would yield the new elephant:

    1. Jumbo reporting for duty!
    

    This is important, because if we shut down the mountebank process and restart it, now our tests can rely on the fact that we'll cycle through both responses:

    "stubs": [
      {
        "predicates": [{
          "deepEquals': {
            "method": "GET",
            "path": "/test",
            "query": { "q": "elephants" }
          }
        }],
        "responses": [
          {
            "is": {
              "body": "No results"
            }
          },
          {
            "is": {
              "body": "1. Jumbo reporting for duty!"
            }
          }
        ]
      }
    ]