ijpiantanida / talkback

A simple HTTP proxy that records and playbacks requests
MIT License
284 stars 41 forks source link

Partial body matching, possibly with Regex #7

Closed Vages closed 6 years ago

Vages commented 6 years ago

I could give the following a try and make a PR if you think the it sounds like a worthwhile undertaking, @ijpiantanida.

Our problem

My team and I have often found that a request body contains some piece of ever-changing data, e.g. a date or timestamp. Consequently, Talkback is unable to serve a cached response for the request the next time we run our tests.

The new ignore body option partially solves our problem: It works fine when we want to cache just one response for a given URL. But there are some URLs for which we need to cache two or more responses and serve them based on differing characteristics of the bodies. (This is especially true for GraphQL-endpoints, where the body is the only thing that matters and we may have hundreds of different bodies.) Ignore body is not of much help to us in these situations.

Proposed solution

We discussed this in my team. Our best idea was to giving Talkback-users the option of adding a reqBodyIsRegex field to the meta-object in the cached response file, signifying that the request body is to be interpreted as a regular expression (requiring the author to convert the string to a regex). If any request body matches the regex, the cached response is served, exactly as stored. (Regex capturing groups could be used to adapt responses in the future, but I think this should not be in the first version of this.)

{
    meta: {
        createdAt: "2018-02-16T14:51:35.972Z",
        host: "http://example.com/",
        resHumanReadable: true,
        reqBodyIsRegex: true,
    },
    req: {
        body: 'Your body as a regex here. \(You would probably have to escape parentheses and stuff, but exactly how, remains to be seen\)'
    }
    ...
}

Matching priority

My thoughts are that exact matching will have priority over regex-matching. I do not have any ideas about how to tie-break between competing regexes, but my guess is there's either no solution or some really good, pre-existing solution.

ijpiantanida commented 6 years ago

Hi @Vages, glad you find talkback useful, and thank you for the feature idea.

I understand the problem you're facing, and I already have in mind something that would cover this case and also be more generic to support other users' use cases.

My idea is to add an option that let's you hook up your own body matching function. The function would be called with the original request and with every saved tape that matched everything else (url, method, headers, etc...). If the function returns true, then that would be the tape to be used. That would let you use the regex approach, or you can parse the body and do JSON handling, etc...

What do you think?

Vages commented 6 years ago

Sounds like a great idea, @ijpiantanida! More versatile than my proposition. Reminds me of another tool we're already using, https://www.npmjs.com/package/dyson.

I think you may have a better plan than I about how this should be implemented, but if you want any other kind of assistance (questions, code review, testing), I would be glad to help.

ijpiantanida commented 6 years ago

@Vages I just released v1.5.0 which adds the bodyMatcher option. There's an example on how to use it in the README.

Hope it helps!