Content-Type multipart/form-data is not serialized in proxy and recording mode #171

Closed
opened 2025-12-29 08:23:21 +01:00 by adam · 17 comments
Owner

Originally created by @pmiossec on GitHub (Apr 1, 2019).

Originally assigned to: @StefH on GitHub.

In the last version of WireMock.Net.StandAlone ( Version="1.0.8"), when doing a Content-Type multipart/form-data POST request, the mapping generated doesn't contain the Matcher for the body (so that don't made it a valid mapping).

Note: I forward to another Wiremock instance and see the content of the body, so the content seems to be forwarded.

I get the generated mapping (Notice the empty "Body" key) :

{
  "Guid": "ba19b8f6-432e-4e4b-92e0-d51c372b4277",
  "Title": "",
  "Priority": 0,
  "Request": {
    "Path": {
      "Matchers": [
        {
          "Name": "WildcardMatcher",
          "Pattern": "/export/xxxxxx/upload",
          "IgnoreCase": false
        }
      ]
    },
    "Methods": [
      "POST"
    ],
    "Headers": [
      {
        "Name": "Content-Type",
        "Matchers": [
          {
            "Name": "WildcardMatcher",
            "Pattern": "multipart/form-data; boundary=\"31455f07-7487-400f-906e-9e1aefa04869\"",
            "IgnoreCase": true
          }
        ]
      },
      {
        "Name": "Host",
        "Matchers": [
          {
            "Name": "WildcardMatcher",
            "Pattern": "localhost:8080",
            "IgnoreCase": true
          }
        ]
      },
      {
        "Name": "Content-Length",
        "Matchers": [
          {
            "Name": "WildcardMatcher",
            "Pattern": "298",
            "IgnoreCase": true
          }
        ]
      }
    ],
    "Body": {}
  },
  "Response": {
    "StatusCode": 404,
    "BodyAsJson": {
      "Status": "No matching mapping found"
    },
    "UseTransformer": false,
    "Headers": {
      "Content-Type": "application/json",
      "Date": "Mon, 01 Apr 2019 10:09:04 GMT",
      "Server": "Kestrel",
      "Transfer-Encoding": "chunked"
    }
  }
}

I have the same behavior when doing the request through Postman or C# code...

If you want to test, you could reproduce with this code.

        public async Task<T> UploadFileFromPath<T>(string uri, string filePath, string filename = null)
        {
            if (!File.Exists(filePath))
            {
                throw new ArgumentException($"The file to upload '{filePath}' doesn't exist!");
            }

            using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            using (var form = new MultipartFormDataContent())
            using (var sc = new StreamContent(fs))
            {
                sc.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
                form.Add(sc, "file", filename ?? Path.GetFileName(filePath));
                var response = await _httpClient.PostAsync(uri, form).ConfigureAwait(false);
                response.EnsureSuccessStatusCode();
                return await HandleResponse<T>(response).ConfigureAwait(false);
            }
        }
Originally created by @pmiossec on GitHub (Apr 1, 2019). Originally assigned to: @StefH on GitHub. In the last version of `WireMock.Net.StandAlone` ( Version="1.0.8"), when doing a Content-Type multipart/form-data POST request, the mapping generated doesn't contain the Matcher for the body (so that don't made it a valid mapping). Note: I forward to another Wiremock instance and see the content of the body, so the content seems to be forwarded. I get the generated mapping (Notice the empty "Body" key) : ```json { "Guid": "ba19b8f6-432e-4e4b-92e0-d51c372b4277", "Title": "", "Priority": 0, "Request": { "Path": { "Matchers": [ { "Name": "WildcardMatcher", "Pattern": "/export/xxxxxx/upload", "IgnoreCase": false } ] }, "Methods": [ "POST" ], "Headers": [ { "Name": "Content-Type", "Matchers": [ { "Name": "WildcardMatcher", "Pattern": "multipart/form-data; boundary=\"31455f07-7487-400f-906e-9e1aefa04869\"", "IgnoreCase": true } ] }, { "Name": "Host", "Matchers": [ { "Name": "WildcardMatcher", "Pattern": "localhost:8080", "IgnoreCase": true } ] }, { "Name": "Content-Length", "Matchers": [ { "Name": "WildcardMatcher", "Pattern": "298", "IgnoreCase": true } ] } ], "Body": {} }, "Response": { "StatusCode": 404, "BodyAsJson": { "Status": "No matching mapping found" }, "UseTransformer": false, "Headers": { "Content-Type": "application/json", "Date": "Mon, 01 Apr 2019 10:09:04 GMT", "Server": "Kestrel", "Transfer-Encoding": "chunked" } } } ``` I have the same behavior when doing the request through Postman or C# code... If you want to test, you could reproduce with this code. ```csharp public async Task<T> UploadFileFromPath<T>(string uri, string filePath, string filename = null) { if (!File.Exists(filePath)) { throw new ArgumentException($"The file to upload '{filePath}' doesn't exist!"); } using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) using (var form = new MultipartFormDataContent()) using (var sc = new StreamContent(fs)) { sc.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); form.Add(sc, "file", filename ?? Path.GetFileName(filePath)); var response = await _httpClient.PostAsync(uri, form).ConfigureAwait(false); response.EnsureSuccessStatusCode(); return await HandleResponse<T>(response).ConfigureAwait(false); } } ```
adam added the bug label 2025-12-29 08:23:21 +01:00
adam closed this issue 2025-12-29 08:23:21 +01:00
Author
Owner

@StefH commented on GitHub (Apr 1, 2019):

If possible, can you provide the full body (captured using fiddler for example)?

@StefH commented on GitHub (Apr 1, 2019): If possible, can you provide the full body (captured using fiddler for example)?
Author
Owner

@pmiossec commented on GitHub (Apr 1, 2019):

Body content obtained with fiddler:

POST http://localhost:8080/export/via-fiddler/upload HTTP/1.1
Content-Type: multipart/form-data; boundary="5aaf4468-6f12-49e4-ae28-88d5e18593ca"
Content-Length: 298
Host: localhost:8080

--5aaf4468-6f12-49e4-ae28-88d5e18593ca
Content-Type: application/json
Content-Disposition: form-data; name=file; filename=relationship_types.json; filename*=utf-8''relationship_types.json

[{"relationshipTypeId":1,"relationshipTypeCode":"Ownership"}]
--5aaf4468-6f12-49e4-ae28-88d5e18593ca--
@pmiossec commented on GitHub (Apr 1, 2019): Body content obtained with fiddler: ``` POST http://localhost:8080/export/via-fiddler/upload HTTP/1.1 Content-Type: multipart/form-data; boundary="5aaf4468-6f12-49e4-ae28-88d5e18593ca" Content-Length: 298 Host: localhost:8080 --5aaf4468-6f12-49e4-ae28-88d5e18593ca Content-Type: application/json Content-Disposition: form-data; name=file; filename=relationship_types.json; filename*=utf-8''relationship_types.json [{"relationshipTypeId":1,"relationshipTypeCode":"Ownership"}] --5aaf4468-6f12-49e4-ae28-88d5e18593ca-- ```
Author
Owner

@StefH commented on GitHub (Apr 1, 2019):

I checked, and this is actually by design.
Only full text or json body is saved on the mapping.

I left out Bytes / Multipart because I'm not sure which matcher to use.

@StefH commented on GitHub (Apr 1, 2019): I checked, and this is actually `by design`. Only full text or json body is saved on the mapping. I left out Bytes / Multipart because I'm not sure which matcher to use.
Author
Owner

@pmiossec commented on GitHub (Apr 1, 2019):

I don't know what to do with this answer 😢

It seems to me that the content in sent in text so it should be possible to do some checks.
But what worries me much is that the body is empty and we could think that nothing was sent...

I don't know if we could not have a "No check" matcher so that we could have the value received serialized in the mapping file but ignored in the matching process. That way the developer could really see what have been sent.

Thanks for the answer.

@pmiossec commented on GitHub (Apr 1, 2019): I don't know what to do with this answer 😢 It seems to me that the content in sent in text so it should be possible to do some checks. But what worries me much is that the body is empty and we could think that nothing was sent... I don't know if we could not have a "No check" matcher so that we could have the value received serialized in the mapping file but ignored in the matching process. That way the developer could **really** see what have been sent. Thanks for the answer.
Author
Owner

@StefH commented on GitHub (Apr 1, 2019):

Sorry for my short answer. What I just meant to say is that up until your question, I did not really think it would be usefull / possible to save the body in case of Bytes or Multipart.

I think using the ExactObjectMatcher could be an option in this case. I'll take a look at the code.

@StefH commented on GitHub (Apr 1, 2019): Sorry for my short answer. What I just meant to say is that up until your question, I did not really think it would be usefull / possible to save the body in case of **Bytes** or **Multipart**. I think using the `ExactObjectMatcher` could be an option in this case. I'll take a look at the code.
Author
Owner

@StefH commented on GitHub (Apr 1, 2019):

Using the ExactObjectMatcher would return the body in the mapping as:

Example:

"Body": {
  "Matcher": {
    "Name": "ExactObjectMatcher",
    "Pattern": "LS0xNjU4YTNjMi05NzhkLTQyNWUtOTZiMy04YzE1MTcxZDc1NWQNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPXRlc3Q7IGZpbGVuYW1lPXRlc3QudHh0OyBmaWxlbmFtZSo9dXRmLTgnJ3Rlc3QudHh0DQoNCmRhdGENCi0tMTY1OGEzYzItOTc4ZC00MjVlLTk2YjMtOGMxNTE3MWQ3NTVkLS0NCg=="
   }
}

Would this be ok?

@StefH commented on GitHub (Apr 1, 2019): Using the ExactObjectMatcher would return the body in the mapping as: Example: ```js "Body": { "Matcher": { "Name": "ExactObjectMatcher", "Pattern": "LS0xNjU4YTNjMi05NzhkLTQyNWUtOTZiMy04YzE1MTcxZDc1NWQNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPXRlc3Q7IGZpbGVuYW1lPXRlc3QudHh0OyBmaWxlbmFtZSo9dXRmLTgnJ3Rlc3QudHh0DQoNCmRhdGENCi0tMTY1OGEzYzItOTc4ZC00MjVlLTk2YjMtOGMxNTE3MWQ3NTVkLS0NCg==" } } ``` Would this be ok?
Author
Owner

@StefH commented on GitHub (Apr 2, 2019):

Linked to PR - https://github.com/WireMock-Net/WireMock.Net/pull/264

@StefH commented on GitHub (Apr 2, 2019): Linked to PR - https://github.com/WireMock-Net/WireMock.Net/pull/264
Author
Owner

@StefH commented on GitHub (Apr 2, 2019):

I can also build some logic to check if the data is a valid ASCII string, in that case I can change the detection from MultiPart logic and the code will automatically used the current string matchers...

In this case, the mapping would look like:

"Body": {
  "Matcher": {
    "Name": "ExactMatcher",
    "Pattern": "--cea0a92a-94b2-4c5c-b3d9-da77d4220113\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=test; filename=test.txt; filename*=utf-8''test.txt\r\n\r\ndata\r\n--cea0a92a-94b2-4c5c-b3d9-da77d4220113--\r\n"
  }
}
@StefH commented on GitHub (Apr 2, 2019): I can also build some logic to check if the data is a valid ASCII string, in that case I can change the detection from MultiPart logic and the code will automatically used the current string matchers... In this case, the mapping would look like: ``` js "Body": { "Matcher": { "Name": "ExactMatcher", "Pattern": "--cea0a92a-94b2-4c5c-b3d9-da77d4220113\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=test; filename=test.txt; filename*=utf-8''test.txt\r\n\r\ndata\r\n--cea0a92a-94b2-4c5c-b3d9-da77d4220113--\r\n" } } ```
Author
Owner

@pmiossec commented on GitHub (Apr 2, 2019):

I'm really impress and appreciate this very quick PR 👍
But that didn't let me the time to answer your question 😢

Using the ExactObjectMatcher would return the body in the mapping as:
Would this be ok?

I don't think it will be very useful due to the multiparts boundaries that are by default auto generated and, so, varies and consequently, the ExactObjectMatcher will match nothing :(

I can also build some logic to check if the data is a valid ASCII string, in that case I can change the detection from MultiPart logic and the code will automatically used the current string matchers...

Something like that will indeed be much more valuable and will let the developer check for part of the string (without the boundaries, for example).

@pmiossec commented on GitHub (Apr 2, 2019): I'm really impress and appreciate this very quick PR 👍 But that didn't let me the time to answer your question 😢 >Using the ExactObjectMatcher would return the body in the mapping as: >Would this be ok? I don't think it will be very useful due to the multiparts boundaries that are by default auto generated and, so, varies and consequently, the ExactObjectMatcher will match nothing :( >I can also build some logic to check if the data is a valid ASCII string, in that case I can change the detection from MultiPart logic and the code will automatically used the current string matchers... Something like that will indeed be much more valuable and will let the developer check for part of the string (without the boundaries, for example).
Author
Owner

@StefH commented on GitHub (Apr 2, 2019):

Would the mapping in my proposal work for you?

"Body": {
  "Matcher": {
    "Name": "ExactMatcher",
    "Pattern": "--cea0a92a-94b2-4c5c-b3d9-da77d4220113\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=test; filename=test.txt; filename*=utf-8''test.txt\r\n\r\ndata\r\n--cea0a92a-94b2-4c5c-b3d9-da77d4220113--\r\n"
  }
}
@StefH commented on GitHub (Apr 2, 2019): Would the mapping in my proposal work for you? ``` js "Body": { "Matcher": { "Name": "ExactMatcher", "Pattern": "--cea0a92a-94b2-4c5c-b3d9-da77d4220113\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=test; filename=test.txt; filename*=utf-8''test.txt\r\n\r\ndata\r\n--cea0a92a-94b2-4c5c-b3d9-da77d4220113--\r\n" } } ```
Author
Owner

@pmiossec commented on GitHub (Apr 2, 2019):

I'm not very used to mapping file but will I be able to modified it to look like below and that will still work?

"Body": {
  "Matcher": {
    "Name": "WildcardMatcher",
    "Pattern": "--*\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=test; filename=test.txt; filename*=utf-8''test.txt\r\n\r\ndata\r\n--*--\r\n"
  }
}

If yes, 👍
Perhaps there is also a something looking like ContainsMatcher that return true if the body contains the string passed?

@pmiossec commented on GitHub (Apr 2, 2019): I'm not very used to mapping file but will I be able to modified it to look like below and that will still work? ```json "Body": { "Matcher": { "Name": "WildcardMatcher", "Pattern": "--*\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=test; filename=test.txt; filename*=utf-8''test.txt\r\n\r\ndata\r\n--*--\r\n" } } ``` If yes, 👍 Perhaps there is also a something looking like `ContainsMatcher` that return true if the body contains the string passed?
Author
Owner

@StefH commented on GitHub (Apr 2, 2019):

You can indeed change the generated mapping to use the WildcardMatcher, this is essentially a contains-matcher if used correctly (in your example this is correct) ==> "*XXX*"

@StefH commented on GitHub (Apr 2, 2019): You can indeed change the generated mapping to use the `WildcardMatcher`, this is essentially a contains-matcher if used correctly (in your example this is correct) ==> `"*XXX*"`
Author
Owner

@StefH commented on GitHub (Apr 2, 2019):

@pmiossec
If you like, you can use this preview NuGet which includes this code.
https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net/1.0.12-ci-11179

@StefH commented on GitHub (Apr 2, 2019): @pmiossec If you like, you can use this preview NuGet which includes this code. https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net/1.0.12-ci-11179
Author
Owner

@pmiossec commented on GitHub (Apr 2, 2019):

I'll try to do that. Thanks a lot again (especially for your spontaneity!)

On Tue, 2 Apr 2019 at 15:02, Stef Heyenrath notifications@github.com
wrote:

@pmiossec https://github.com/pmiossec
If you like, you can use this preview NuGet which includes this code.

https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net/1.0.12-ci-11179


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/WireMock-Net/WireMock.Net/issues/263#issuecomment-478985260,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAcFpBZZj_p8Q2lx5bm2aEIsBZ-hscRJks5vc1T_gaJpZM4cVYcI
.

@pmiossec commented on GitHub (Apr 2, 2019): I'll try to do that. Thanks a lot again (especially for your spontaneity!) On Tue, 2 Apr 2019 at 15:02, Stef Heyenrath <notifications@github.com> wrote: > @pmiossec <https://github.com/pmiossec> > If you like, you can use this preview NuGet which includes this code. > > https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net/1.0.12-ci-11179 > > — > You are receiving this because you were mentioned. > Reply to this email directly, view it on GitHub > <https://github.com/WireMock-Net/WireMock.Net/issues/263#issuecomment-478985260>, > or mute the thread > <https://github.com/notifications/unsubscribe-auth/AAcFpBZZj_p8Q2lx5bm2aEIsBZ-hscRJks5vc1T_gaJpZM4cVYcI> > . >
Author
Owner

@StefH commented on GitHub (Apr 4, 2019):

@pmiossec Does that NuGet work correct for you?

@StefH commented on GitHub (Apr 4, 2019): @pmiossec Does that NuGet work correct for you?
Author
Owner

@pmiossec commented on GitHub (Apr 5, 2019):

@StefH I have tested it and it is working as expected.

Thank you very much!

@pmiossec commented on GitHub (Apr 5, 2019): @StefH I have tested it and it is working as expected. Thank you very much!
Author
Owner

@StefH commented on GitHub (Apr 5, 2019):

Today a new official NuGet will be released.

@StefH commented on GitHub (Apr 5, 2019): Today a new official NuGet will be released.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#171