imposter icon indicating copy to clipboard operation
imposter copied to clipboard

Hybrid proxy mode

Open clarauso opened this issue 2 years ago • 9 comments

Hi, it could be very useful to have a new proxy mode that makes the server return the mock data when a matching resource has been found, otherwise forwards the request to the upstream endpoint.

Can you consider this feature for future releases?

Thanks!

clarauso avatar Feb 17 '23 18:02 clarauso

Hi @clarauso, thank you for the suggestion. This sounds like a useful feature.

I could imagine this being something like imposter proxy --use-existing http://example.com within a directory already containing Imposter config files. The mock engine would handle any matching resources and for any that don't have an exact match, the request would be forwarded to the specified URL.

In this mode, would you also expect features of imposter proxy, such as recording, to work as well, or is this just a passthrough for unmapped resources?

outofcoffee avatar Feb 20 '23 23:02 outofcoffee

Thanks for your feedback @outofcoffee! I imagine this as a passthrough for unmapped resources, so without recording, in order to use mocks only for a specific subset of requests with the goal of enriching partial/incomplete data in a test environment (in other words, in this scenario the target system can provide some data that could be used as it is, without mocking, but not all test cases are covered, so additional data must be mocked).

clarauso avatar Feb 22 '23 00:02 clarauso

Hi @clarauso - this feature is available now in the beta release.

I've put an example of how the config would work for this here: https://github.com/outofcoffee/imposter/tree/develop/examples/rest/passthrough-upstream

Note: no special CLI syntax is required - this is all done via config..

~Please note that at the moment, individual resources can be proxied in this way, rather than all unmapped resources using the proxy. This is a bit cumbersome, but there will be a subsequent feature to set this as a default/fallback for unmapped resources.~

Please note the use of the trailing wildcard in the path:

resources:
  # forward requests to upstream
  - path: /*
    passthrough: example

This will forward requests to the upstream unless there is an exact resource configured for them.

You can run this example with:

imposter up /path/to/config/dir -v beta

outofcoffee avatar Mar 06 '23 02:03 outofcoffee

Thanks @outofcoffee! It looks great, I will do some tests and give you a feedback shortly.

clarauso avatar Mar 11 '23 07:03 clarauso

Hi @clarauso - this is released in v3.12.0. I'll leave this issue open for now for any feedback.

outofcoffee avatar Mar 19 '23 13:03 outofcoffee

Hi @outofcoffee, I've done some tests and I confirm that unmatched resources are sent to the configured upstream, great!

However, if the upstream URL contains a context path (eventually with subpaths), the context path is ignored: in other words, given the following configuration

plugin: rest

upstreams:
  example:
    url: https://example.com/context-path/sub-path

resources:
  # forward requests to upstream
  - path: /*
    passthrough: example
  # mock a response
  - path: /mock
    response:
      statusCode: 200
      content: "Hello from a mock"
      headers:
        Content-Type: text/plain
  • a request to http://localhost:8080/mock correctly uses the given mock response
  • a request to http://localhost:8080/real is sent upstream, but it is sent to https://example.com/real instead of https://example.com/context-path/sub-path/real as I'd expect

Is it intended?

Thanks!

clarauso avatar Mar 20 '23 00:03 clarauso

Hi @clarauso - thank you for looking at this :)

I can see the value in appending the request path to the path specified for the upstream. I think the principle of least surprise suggests we treat this as a bug and fix it.

A related question; if the passthrough configuration were specified like this:

resources:
  # forward requests to upstream
  - path: /foo/*
    passthrough: example

…and the request path was /foo/bar, how would you expect the final URL to the upstream to look? Would it include or elide the /foo part of the path?

outofcoffee avatar Mar 20 '23 01:03 outofcoffee

@clarauso the first part of this (appending the request path to the upstream path) is fixed in v3.12.2.

Currently, on the second part, the full request path is appended.

outofcoffee avatar Mar 20 '23 13:03 outofcoffee

Tested v3.12.2 and it works!

For the second part, I think that the full request path should be appended, as already done.

For additional soundness, the upstream URL and the resources paths could be required to not overlap, and if it happens the configuration must be considered invalid: the logic underlying this proposal is that the upstream URL should represent server's base path (same for all endpoints), and the resources path should represent the relative paths of the endpoints/APIs.

Let me clarify using an example: having a backend application serving at https://example.com/context-path/sub-path with two endpoints, https://example.com/context-path/sub-path/resource-a and https://example.com/context-path/sub-path/resource-b, the following configuration should be invalid:

plugin: rest

upstreams:
  example:
    url: https://example.com/context-path/sub-path

resources:
  # forward requests to upstream
  - path: /sub-path/*
    passthrough: example
  - path: /sub-path/resource-b/*
    response:
      statusCode: 200
      content: "Hello from a mock"
      headers:
        Content-Type: text/plain

The correct one should be:

plugin: rest

upstreams:
  example:
    url: https://example.com/context-path/sub-path

resources:
  # forward requests to upstream
  - path: /*
    passthrough: example
  - path: /resource-b/*
    response:
      statusCode: 200
      content: "Hello from a mock"
      headers:
        Content-Type: text/plain

However, even without this additional check I think that the feature implementation is fine.

clarauso avatar Mar 20 '23 20:03 clarauso