How can send Postbacks based on a path? #537

Closed
opened 2025-12-29 08:29:39 +01:00 by adam · 15 comments
Owner

Originally created by @mastrauckas on GitHub (Jul 25, 2023).

Originally assigned to: @StefH on GitHub.

Is there a way to receive a request, respond to the client with a status code and body, and a minute later send a post back to a URL with information from the original client request body? If possible, maybe even send multiple postbacks at different times.

I thought I could do like this

server = WireMockServer.Start(9333);
server.Given(Request.Create().WithPath("/mypath").UsingGet() )
  .RespondWith(Response.Create()
     .WithStatusCode(200)
     .WithBody("Hello WireMock.Net World!")
   )
.Delay(1m)
 .WithPostback(Request.Create().WithBody(originalBody => "Sending Data {originalBody}")
.Delay(1m)
 .WithPostback(Request.Create().WithBody(originalBody => "Sending Data {originalBody}");

The last part is obviously made up, but I was wondering if there is a feature that I can accomplish this?

Thanks

Originally created by @mastrauckas on GitHub (Jul 25, 2023). Originally assigned to: @StefH on GitHub. Is there a way to receive a request, respond to the client with a status code and body, and a minute later send a post back to a URL with information from the original client request body? If possible, maybe even send multiple postbacks at different times. I thought I could do like this ```c# server = WireMockServer.Start(9333); server.Given(Request.Create().WithPath("/mypath").UsingGet() ) .RespondWith(Response.Create() .WithStatusCode(200) .WithBody("Hello WireMock.Net World!") ) .Delay(1m) .WithPostback(Request.Create().WithBody(originalBody => "Sending Data {originalBody}") .Delay(1m) .WithPostback(Request.Create().WithBody(originalBody => "Sending Data {originalBody}"); ``` The last part is obviously made up, but I was wondering if there is a feature that I can accomplish this? Thanks
adam added the question label 2025-12-29 08:29:39 +01:00
adam closed this issue 2025-12-29 08:29:39 +01:00
Author
Owner

@StefH commented on GitHub (Jul 25, 2023):

  1. You can use .WithCallback(...) (https://github.com/WireMock-Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs)

  2. It's not yet possible to delay the callback or send multiple callbacks at different times. --> Why would you need this?

@StefH commented on GitHub (Jul 25, 2023): 1. You can use `.WithCallback(...)` (https://github.com/WireMock-Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs) 2. It's not yet possible to delay the callback or send multiple callbacks at different times. --> Why would you need this?
Author
Owner

@mastrauckas commented on GitHub (Jul 25, 2023):

@StefH ,

Thanks for your quick reply.

You can use .WithCallback(...) (https://github.com/WireMock->Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs)

So I experimented with some of the code below.

_server
          .Given(Request
                .Create()
                .WithPath("/mypath")
                .WithBody(b => CheckWantToHandleBody(b))
                .UsingPost()
          )
          .RespondWith(Response
                .Create()
                .WithStatusCode(200)
                .WithBody(request => GetResponseBody(request))
                .WithCallback(r => GetCallbackResponse(r))
           );

public ResponseMessage GetCallbackResponse(IRequestMessage request)
   return new ResponseMessage()
        {
            BodyDestination = "https://blah.com/api/myendpoint",
            BodyData = new WireMock.Util.BodyData
            {
                BodyAsJson = request.BodyAsJson
            }
        };
  1. The first hurdle is when I use WithCallback after WithBody, the WithBody method never gets called so the body never gets sent to the client. If I switch WithBody and WithCallback, then the WithCallback never gets called. So I haven't found a way for both methods to get triggered.
  2. When calling WithCallback, I'm not able to get the response information returned from the HTTP server listening on BodyDestination. To tell you the truth, I'm not even sure the URL in BodyDestination ever got called.

I'm sure I just don't know the correct way to use the API.

It's not yet possible to delay the callback or send multiple callbacks at different times. --> Why would you need this?

I am trying to emulate receiving a request from a client and sending back an immediate status code and body for the request and later sending partial updates via postbacks to a URL based on the original request the client sent me.

I hope that makes sense.

@mastrauckas commented on GitHub (Jul 25, 2023): @StefH , Thanks for your quick reply. > You can use .WithCallback(...) (https://github.com/WireMock->Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs) So I experimented with some of the code below. ```c# _server .Given(Request .Create() .WithPath("/mypath") .WithBody(b => CheckWantToHandleBody(b)) .UsingPost() ) .RespondWith(Response .Create() .WithStatusCode(200) .WithBody(request => GetResponseBody(request)) .WithCallback(r => GetCallbackResponse(r)) ); public ResponseMessage GetCallbackResponse(IRequestMessage request) return new ResponseMessage() { BodyDestination = "https://blah.com/api/myendpoint", BodyData = new WireMock.Util.BodyData { BodyAsJson = request.BodyAsJson } }; ``` 1. The first hurdle is when I use `WithCallback` after `WithBody`, the `WithBody` method never gets called so the body never gets sent to the client. If I switch `WithBody` and `WithCallback`, then the `WithCallback` never gets called. So I haven't found a way for both methods to get triggered. 2. When calling `WithCallback`, I'm not able to get the response information returned from the HTTP server listening on `BodyDestination`. To tell you the truth, I'm not even sure the URL in `BodyDestination ` ever got called. I'm sure I just don't know the correct way to use the API. > It's not yet possible to delay the callback or send multiple callbacks at different times. --> Why would you need this? I am trying to emulate receiving a request from a client and sending back an immediate status code and body for the request and later sending partial updates via postbacks to a URL based on the original request the client sent me. I hope that makes sense.
Author
Owner

@StefH commented on GitHub (Jul 25, 2023):

@mastrauckas
Sorry.

I provided the wrong answer.

You should use WithWebhook

-->

/// <summary>
    /// Add (multiple) Webhook(s) to call after the response has been generated.
    /// </summary>
    /// <param name="webhooks">The Webhooks</param>
    /// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
    IRespondWithAProvider WithWebhook(params IWebhook[] webhooks);

    /// <summary>
    /// Support FireAndForget for any configured Webhooks
    /// </summary>
    /// <param name="useWebhooksFireAndForget"></param>
    /// <returns></returns>
    IRespondWithAProvider WithWebhookFireAndForget(bool useWebhooksFireAndForget);

    /// <summary>
    /// Add a Webhook to call after the response has been generated.
    /// </summary>
    /// <param name="url">The Webhook Url</param>
    /// <param name="method">The method to use. [optional]</param>
    /// <param name="headers">The Headers to send. [optional]</param>
    /// <param name="body">The body (as string) to send. [optional]</param>
    /// <param name="useTransformer">Use Transformer. [optional]</param>
    /// <param name="transformerType">The transformer type. [optional]</param>
    /// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
    IRespondWithAProvider WithWebhook(
        string url,
        string method = "post",
        IDictionary<string, WireMockList<string>>? headers = null,
        string? body = null,
        bool useTransformer = true,
        TransformerType transformerType = TransformerType.Handlebars
    );

@StefH commented on GitHub (Jul 25, 2023): @mastrauckas Sorry. I provided the wrong answer. You should use **WithWebhook** --> ``` /// <summary> /// Add (multiple) Webhook(s) to call after the response has been generated. /// </summary> /// <param name="webhooks">The Webhooks</param> /// <returns>The <see cref="IRespondWithAProvider"/>.</returns> IRespondWithAProvider WithWebhook(params IWebhook[] webhooks); /// <summary> /// Support FireAndForget for any configured Webhooks /// </summary> /// <param name="useWebhooksFireAndForget"></param> /// <returns></returns> IRespondWithAProvider WithWebhookFireAndForget(bool useWebhooksFireAndForget); /// <summary> /// Add a Webhook to call after the response has been generated. /// </summary> /// <param name="url">The Webhook Url</param> /// <param name="method">The method to use. [optional]</param> /// <param name="headers">The Headers to send. [optional]</param> /// <param name="body">The body (as string) to send. [optional]</param> /// <param name="useTransformer">Use Transformer. [optional]</param> /// <param name="transformerType">The transformer type. [optional]</param> /// <returns>The <see cref="IRespondWithAProvider"/>.</returns> IRespondWithAProvider WithWebhook( string url, string method = "post", IDictionary<string, WireMockList<string>>? headers = null, string? body = null, bool useTransformer = true, TransformerType transformerType = TransformerType.Handlebars ); ```
Author
Owner

@mastrauckas commented on GitHub (Jul 25, 2023):

@StefH,

Ok, so I made some tweaks as shown below:

_server
          .Given(Request
                .Create()
                .WithPath("/mypath")
                .WithBody(b => CheckWantToHandleBody(b))
                .UsingPost()
          )
          .WithWebhook(GetWebhook())
          .RespondWith(Response
                .Create()
                .WithStatusCode(200)
                .WithBody(request => GetResponseBody(request))
           );

    public IWebhook[] GetWebhook()
    {
        var webhooks = new Webhook[1];
        Webhook webhook = new();
        WebhookRequest request = new();
        request.Method = "post";
        request.Delay = 1000;
        request.Headers = new Dictionary<string, WireMock.Types.WireMockList<string>>();

        request.Headers.Add("content-type", "application/json");
        request.Url = "https://blah.com/api/myendpoint";
        request.BodyData = new WireMock.Util.BodyData
        {
            BodyAsJson = "[]"
        };
        webhook.Request = request;
        webhooks[0] = webhook;
        return webhooks;
    }

I now send the response to the client with .WithBody(request => GetResponseBody(request)), but once again I'm not getting a postback from the information passed into .WithWebhook(GetWebhook()).

Even if I did get a postback from the information passed into .WithWebhook(GetWebhook()), I don't have the original request to use when crafting the postback request body. I also don't seem to be able to get the response information from that postback server.

@mastrauckas commented on GitHub (Jul 25, 2023): @StefH, Ok, so I made some tweaks as shown below: ```c# _server .Given(Request .Create() .WithPath("/mypath") .WithBody(b => CheckWantToHandleBody(b)) .UsingPost() ) .WithWebhook(GetWebhook()) .RespondWith(Response .Create() .WithStatusCode(200) .WithBody(request => GetResponseBody(request)) ); public IWebhook[] GetWebhook() { var webhooks = new Webhook[1]; Webhook webhook = new(); WebhookRequest request = new(); request.Method = "post"; request.Delay = 1000; request.Headers = new Dictionary<string, WireMock.Types.WireMockList<string>>(); request.Headers.Add("content-type", "application/json"); request.Url = "https://blah.com/api/myendpoint"; request.BodyData = new WireMock.Util.BodyData { BodyAsJson = "[]" }; webhook.Request = request; webhooks[0] = webhook; return webhooks; } ``` I now send the response to the client with ` .WithBody(request => GetResponseBody(request))`, but once again I'm not getting a postback from the information passed into ` .WithWebhook(GetWebhook())`. Even if I did get a postback from the information passed into ` .WithWebhook(GetWebhook())`, I don't have the original request to use when crafting the postback request body. I also don't seem to be able to get the response information from that postback server.
Author
Owner

@StefH commented on GitHub (Jul 25, 2023):

You can use Handlebars templating to access the request.

See this : https://github.com/WireMock-Net/WireMock.Net/wiki/Webhook

image

https://github.com/WireMock-Net/WireMock.Net/wiki/Response-Templating

@StefH commented on GitHub (Jul 25, 2023): You can use Handlebars templating to access the request. See this : https://github.com/WireMock-Net/WireMock.Net/wiki/Webhook ![image](https://github.com/WireMock-Net/WireMock.Net/assets/249938/110ffada-7adb-41d9-b944-20971ec60dcb) https://github.com/WireMock-Net/WireMock.Net/wiki/Response-Templating
Author
Owner

@mastrauckas commented on GitHub (Jul 25, 2023):

Thanks. I will give that a tryout a little later.

@mastrauckas commented on GitHub (Jul 25, 2023): Thanks. I will give that a tryout a little later.
Author
Owner

@StefH commented on GitHub (Jul 31, 2023):

@mastrauckas
Did you have time to test this?

@StefH commented on GitHub (Jul 31, 2023): @mastrauckas Did you have time to test this?
Author
Owner

@StefH commented on GitHub (Aug 21, 2023):

@mastrauckas
Did you have time to test this?

@StefH commented on GitHub (Aug 21, 2023): @mastrauckas Did you have time to test this?
Author
Owner

@StefH commented on GitHub (Sep 4, 2023):

@mastrauckas
Did you have time to test this?

@StefH commented on GitHub (Sep 4, 2023): @mastrauckas Did you have time to test this?
Author
Owner

@Excommunicated commented on GitHub (Sep 28, 2023):

So I'm not OP, But I did test using the Webhook Json mapping as documented with one additional tweak

{
    "Guid": "755384f9-2252-433d-ae8b-445b9f1cc729",
    "Priority": 0,
    "Request": {
        "Path": {
            "Matchers": [
                {
                    "Name": "WildcardMatcher",
                    "Pattern": "/wh"
                }
            ]
        },
        "Methods": [
            "POST"
        ]
    },
    "Response": {
        "Body": "<xml>ok</xml>",
        "StatusCode": 201,
        "Headers": {
            "Content-Type": "application/xml"
        }
    },
    "Webhook": {
        "Request": {
            "Url": "https://any-endpoint.com",
            "Method": "POST",
            "Headers": {
                "x": "x-value"
            },
            "Body": "ok - RequestPath used = {{request.path}}, RESP = {{response.StatusCode}}",
            "Delay": 20000,
            "UseTransformer": true
        }
    }
}

I added in the Delay parameter for the webhook, and was expecting to get a result back, and then see the webhook publish 20 seconds later, but instead it takes 20 seconds to send the webhook request, then returns the response body to my request. so my actualt mocked request takes 21 seconds and I get the webhook call, before I get the response to my original request.

@Excommunicated commented on GitHub (Sep 28, 2023): So I'm not OP, But I did test using the Webhook Json mapping as documented with one additional tweak ```json { "Guid": "755384f9-2252-433d-ae8b-445b9f1cc729", "Priority": 0, "Request": { "Path": { "Matchers": [ { "Name": "WildcardMatcher", "Pattern": "/wh" } ] }, "Methods": [ "POST" ] }, "Response": { "Body": "<xml>ok</xml>", "StatusCode": 201, "Headers": { "Content-Type": "application/xml" } }, "Webhook": { "Request": { "Url": "https://any-endpoint.com", "Method": "POST", "Headers": { "x": "x-value" }, "Body": "ok - RequestPath used = {{request.path}}, RESP = {{response.StatusCode}}", "Delay": 20000, "UseTransformer": true } } } ``` I added in the Delay parameter for the webhook, and was expecting to get a result back, and then see the webhook publish 20 seconds later, but instead it takes 20 seconds to send the webhook request, then returns the response body to my request. so my actualt mocked request takes 21 seconds and I get the webhook call, before I get the response to my original request.
Author
Owner

@Excommunicated commented on GitHub (Sep 28, 2023):

I apologise, I missed the UseWebhooksFireAndForget element in the mapping that solves this issue.

@Excommunicated commented on GitHub (Sep 28, 2023): I apologise, I missed the `UseWebhooksFireAndForget` element in the mapping that solves this issue.
Author
Owner

@StefH commented on GitHub (Sep 29, 2023):

@mastrauckas
Did you have time to test this?

@StefH commented on GitHub (Sep 29, 2023): @mastrauckas Did you have time to test this?
Author
Owner

@StefH commented on GitHub (Oct 14, 2023):

@mastrauckas / @Excommunicated

Is all clear? Can I close this issue?

@StefH commented on GitHub (Oct 14, 2023): @mastrauckas / @Excommunicated Is all clear? Can I close this issue?
Author
Owner

@Excommunicated commented on GitHub (Oct 14, 2023):

I’m good. It all worked for me as expected.

Get Outlook for iOShttps://aka.ms/o0ukef


From: Stef Heyenrath @.>
Sent: Saturday, October 14, 2023 9:27:34 AM
To: WireMock-Net/WireMock.Net @.
>
Cc: Excommunicated @.>; Mention @.>
Subject: Re: [WireMock-Net/WireMock.Net] How can send Postbacks based on a path? (Issue #982)

@mastrauckashttps://github.com/mastrauckas / @Excommunicatedhttps://github.com/Excommunicated

Is all clear? Can I close this issue?


Reply to this email directly, view it on GitHubhttps://github.com/WireMock-Net/WireMock.Net/issues/982#issuecomment-1762896329, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AA2VR2RGSN4RYDBY23BU75TX7KHMNAVCNFSM6AAAAAA2WKHIYKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONRSHA4TMMZSHE.
You are receiving this because you were mentioned.Message ID: @.***>

@Excommunicated commented on GitHub (Oct 14, 2023): I’m good. It all worked for me as expected. Get Outlook for iOS<https://aka.ms/o0ukef> ________________________________ From: Stef Heyenrath ***@***.***> Sent: Saturday, October 14, 2023 9:27:34 AM To: WireMock-Net/WireMock.Net ***@***.***> Cc: Excommunicated ***@***.***>; Mention ***@***.***> Subject: Re: [WireMock-Net/WireMock.Net] How can send Postbacks based on a path? (Issue #982) @mastrauckas<https://github.com/mastrauckas> / @Excommunicated<https://github.com/Excommunicated> Is all clear? Can I close this issue? — Reply to this email directly, view it on GitHub<https://github.com/WireMock-Net/WireMock.Net/issues/982#issuecomment-1762896329>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AA2VR2RGSN4RYDBY23BU75TX7KHMNAVCNFSM6AAAAAA2WKHIYKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONRSHA4TMMZSHE>. You are receiving this because you were mentioned.Message ID: ***@***.***>
Author
Owner

@StefH commented on GitHub (Oct 20, 2023):

closing...

@StefH commented on GitHub (Oct 20, 2023): closing...
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#537