WireMock-Net / WireMock.Net

WireMock.Net is a flexible product for stubbing and mocking web HTTP responses using advanced request matching and response templating. Based on the functionality from http://WireMock.org, but extended with more functionality.
Apache License 2.0
1.42k stars 209 forks source link

Feature: Add support to recognise custom json media-types #211

Closed alefranz closed 6 years ago

alefranz commented 6 years ago

Hi,

This is a feature request to add support to recognise as json custom media types: e.g. application/vnd.*+json.

I think it could be either match on this pattern (or just +json) or open the BodyParser so it can be customized or media-types can be registered.

Specifically I'm after the ability to correctly save the payload as json when saving the auto generated mappings (when capturing as proxy).

If you are open to the idea I can contribute a PR for this.

StefH commented 6 years ago

Or define at the mapping that the request body should be parsed as String, Json or Bytes by using a new property at the body mapping named ParseBodyAs.

Using this new setting overrides the default Content-Type logic.

Example

{
    "Guid": "debaf408-3b23-4c04-9d18-ef1c020e79f3",
    "Request": {
        "Path": {
            "Matchers": [
                {
                    "Name": "WildcardMatcher",
                    "Pattern": "/jsonbodytest2",
                    "IgnoreCase": true
                }
            ]
        },
        "Methods": [
            "post"
        ],
        "Body": {
            "ParseBodyAs": "Json",
            "Matcher": {
                "Name": "JsonMatcher",
                "Pattern": {
                  "x": 42,
                  "s": "s"
                }
            }
        }
    },
    "Response": {
        "StatusCode": 200,
        "Body": "{ \"result\": \"jsonbodytest2\" }"
    }
}
lesnes commented 6 years ago

i am very interested in this new feature (ParseBodyAs). currently, BodyParser only supports parsing as string for certain content types. this means that one cannot use IStringMatcher implementations for matching request Body when content type is something like multipart/form-data.

when do you expect to release a new version to nuget that includes this functionality ? is it on a branch that i could take a look at?

StefH commented 6 years ago

I'll take a look and start building this new functionality.

lesnes commented 6 years ago

that would be great, thanks!

alefranz commented 6 years ago

@StefH is there a way to specify ParseBodyAs with the fluent syntax? and what about in the ProxyAndRecordSettings?

StefH commented 6 years ago

Hello @lesnes and @alefranz, I'm currently working on a PR https://github.com/WireMock-Net/WireMock.Net/pull/212 which updates the logic for the body parser.

In short:

Please have a look to see if this will solve your questions.

alefranz commented 6 years ago

In the current version I believe sometimes you only have the body as bytes. Also matching a json with a string is often a pain as the sample response data for the mock are usually not minified, so in my scenario I still need the ability to change something in DetectBodyTypeFromContentType to be able to set custom media type as json. Ideally would be nice for that class to not be static and the library support to extend it but that seems quite a lot of work. What about using a regex and testing against application/vnd\..*+json?

StefH commented 6 years ago

1. The property DetectBodyTypeFromContentType is not really used in the logic, it's just for information.

The Content-Type is not used anymore in the logic now.

The real logic is done with the DetectedBodyType.

2. I can implement application/vnd\..*+json as a RegEx if you like, but the logic is not really used.

alefranz commented 6 years ago

Ok, I guess I didn't really get the gist of the PR. I'll have a better look. Do you publish the PR builds as prerelease on myget by any chance?

StefH commented 6 years ago

Added a preview version to MyGet https://www.myget.org/F/wiremock-net/api/v3/index.json

lesnes commented 6 years ago

wow, that was quick. great job! looks like it would suit my purposes

StefH commented 6 years ago

@alefranz PR build is published at https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net / https://www.myget.org/F/wiremock-net/api/v3/index.json

Can you please test this one ?

lesnes commented 6 years ago

i've tested my usage requirement for multipart/form-data against 1.0.4.18-ci-1343 and it is working now 👍

StefH commented 6 years ago

Good news.

@alefranz : If you can confirm this issue and also the other issue; I can create a new official build.

alefranz commented 6 years ago

Apologies, I will be able to test only on Monday.

alefranz commented 6 years ago

Nice, now the mapping has the body as json, however when I save the mappings with SaveStaticMappings I end up with all 3 versions of it (text, json and binary) in the json. It would be nice to define which format to save in SaveStaticMappings

StefH commented 6 years ago

Ah, I did not think of that. By default, the mapping should only be saved for the DetectedBodyType, just as it is now. I'll fix this and a new version should be automatically added to MyGet once it's ready.

Saving all 3 would be an additional option, which will be available in the next version.

alefranz commented 6 years ago

but in my scenario with application/vnd.*+json what would be the DetectedBodyType?

StefH commented 6 years ago

@alefranz When I think about it again...

1] The DetectBodyType will be be based on the body, not on content-type.

2] The DetectBodyTypeFromContentType will be be based on the content-type, but it's not used in the logic.

3] I think you mean /__admin/requests or RequestsGet() ? That code does indeed save all 3 versions:

"Body": "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }",
"BodyAsJson": {
    "things": [
        {
            "name": "RequiredThing"
        },
        {
            "name": "Wiremock"
        }
    ]
},
"BodyAsBytes": "eyAidGhpbmdzIjogWyB7ICJuYW1lIjogIlJlcXVpcmVkVGhpbmciIH0sIHsgIm5hbWUiOiAiV2lyZW1vY2siIH0gXSB9",

This I can update.

alefranz commented 6 years ago

This is my workflow:

All this responses are json but I have custom media types application/vnd.*+json.

The purpose of this is to automatically generate the mappings to load in my tests.

My goal is to have only BodyAsJson in the saved mapping as it is the readable one.

StefH commented 6 years ago

I see your point. Can you try latest from the MyGet feed: 1.0.4.18-ci-1349 ?

See https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions for details on MyGet

StefH commented 6 years ago

@alefranz : did you have time to test the latest version on MyGet?

alefranz commented 6 years ago

Apologies for the delay.

It works like a charm!

Thanks!

StefH commented 6 years ago

@alefranz Are you sure you tested the 1.0.4.18-ci-1349 (or later) MyGet version ?

alefranz commented 6 years ago

Yes, I've tested 1.0.4.18-ci-1349 and the saved mapping contains only the BodyAsJson as desired

alefranz commented 6 years ago

Thank you!