When respond with proxy requestMessage.Url is used, not AbsoluteUrl #268

Closed
opened 2025-12-29 15:19:26 +01:00 by adam · 10 comments
Owner

Originally created by @adatanasov on GitHub (Apr 28, 2020).

Hello,

I have the following working local setup in IIS:
website - wwwdev.company.com
web application - wwwdev.company.com/account
API - wwwdev.company.com/account/api

The web application calls the API with relative URL "/api/...".

I want to add tests for the web app which should call a mocked API and return the responses I want. All unmatched requests should be proxied to the 'real' API.

So, I create a new website, web app and API in IIS:
website - wwwmock.company.com
web application - wwwmock.company.com/account
API - wwwmock.company.com/account/api

For the mocked API I host a WireMock service on .NET Core 2.1, similar to the example 'WireMock.Net.WebApplication.NETCore2'.

This is the part where I setup the server:

var server = WireMockServer.Start(_settings);

server
	.Given(Request.Create().WithPath("/ping").UsingGet())
	.AtPriority(1)
	.RespondWith(Response.Create()
		.WithSuccess()
		.WithBodyAsJson(_settings, Encoding.UTF8, true));

server
	.Given(Request.Create().WithPath("/*"))
	.AtPriority(100)
	.RespondWith(Response.Create()
		.WithProxy(new ProxyAndRecordSettings
		{
			Url = "https://wwwdev.company.com/account/api",
			AllowAutoRedirect = true,
			WebProxySettings = new WebProxySettings
			{
				Address = "http://127.0.0.1:8888",
				UserName = "",
				Password = ""
			}
		}));

So, I want when I call GET https://wwwmock.company.com/account/api/ping to get the response from the mock API. This works.
I also want when I call GET https://wwwmock.company.com/account/api/v2/environments/current this to be redirected to https://wwwdev.company.com/account/api/v2/environments/current, but it gets redirected to https://wwwdev.company.com/v2/environments/current - without the '/account/api' part.

This is logged for the request:
"Url": "https://wwwmock.company.com/v2/environments/current",
"AbsoluteUrl": "https://wwwmock.company.com/account/api/v2/environments/current",

I think this is because of this part of the code in Response.cs

if (ProxyUrl != null && _httpClientForProxy != null)
{
    var requestUri = new Uri(requestMessage.Url);
    var proxyUri = new Uri(ProxyUrl);
    var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);

    return await HttpClientHelper.SendAsync(
        _httpClientForProxy, 
        requestMessage,
        proxyUriWithRequestPathAndQuery.AbsoluteUri,
        !settings.DisableJsonBodyParsing.GetValueOrDefault(false),
        !settings.DisableRequestBodyDecompressing.GetValueOrDefault(false)
    );
}

So the code gets the PathAndQuery from Url, which is "/v2/environments/current" and the baseUrl from ProxyUrl which is "https://wwwdev.company.com".

My question is can I do something, so without changing the IIS setup I get the desired result - https://wwwmock.company.com/account/api/v2/environments/current to be redirected to https://wwwdev.company.com/account/api/v2/environments/current?

Let me know if I can provide more info.

Originally created by @adatanasov on GitHub (Apr 28, 2020). Hello, I have the following working local setup in IIS: website - wwwdev.company.com web application - wwwdev.company.com/account API - wwwdev.company.com/account/api The web application calls the API with relative URL "/api/...". I want to add tests for the web app which should call a mocked API and return the responses I want. All unmatched requests should be proxied to the 'real' API. So, I create a new website, web app and API in IIS: website - wwwmock.company.com web application - wwwmock.company.com/account API - wwwmock.company.com/account/api For the mocked API I host a WireMock service on .NET Core 2.1, similar to the example 'WireMock.Net.WebApplication.NETCore2'. This is the part where I setup the server: ``` c# var server = WireMockServer.Start(_settings); server .Given(Request.Create().WithPath("/ping").UsingGet()) .AtPriority(1) .RespondWith(Response.Create() .WithSuccess() .WithBodyAsJson(_settings, Encoding.UTF8, true)); server .Given(Request.Create().WithPath("/*")) .AtPriority(100) .RespondWith(Response.Create() .WithProxy(new ProxyAndRecordSettings { Url = "https://wwwdev.company.com/account/api", AllowAutoRedirect = true, WebProxySettings = new WebProxySettings { Address = "http://127.0.0.1:8888", UserName = "", Password = "" } })); ``` So, I want when I call GET https://wwwmock.company.com/account/api/ping to get the response from the mock API. This works. I also want when I call GET https:\/\/www**mock**.company.com\/account\/api\/v2\/environments\/current this to be redirected to https:\/\/www**dev**.company.com\/account\/api\/v2\/environments\/current, but it gets redirected to https://wwwdev.company.com/v2/environments/current - without the '/account/api' part. This is logged for the request: "Url": "https://wwwmock.company.com/v2/environments/current", "AbsoluteUrl": "https://wwwmock.company.com/account/api/v2/environments/current", I think this is because of this part of the code in Response.cs ``` c# if (ProxyUrl != null && _httpClientForProxy != null) { var requestUri = new Uri(requestMessage.Url); var proxyUri = new Uri(ProxyUrl); var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery); return await HttpClientHelper.SendAsync( _httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri, !settings.DisableJsonBodyParsing.GetValueOrDefault(false), !settings.DisableRequestBodyDecompressing.GetValueOrDefault(false) ); } ``` So the code gets the PathAndQuery from Url, which is "/v2/environments/current" and the baseUrl from ProxyUrl which is "https://wwwdev.company.com". My question is can I do something, so without changing the IIS setup I get the desired result - https:\/\/www**mock**.company.com\/account\/api\/v2\/environments\/current to be redirected to https:\/\/www**dev**.company.com\/account\/api\/v2\/environments\/current? Let me know if I can provide more info.
adam added the bug label 2025-12-29 15:19:26 +01:00
adam closed this issue 2025-12-29 15:19:26 +01:00
Author
Owner

@StefH commented on GitHub (Apr 28, 2020):

I would expect that using this code:

var server = WireMockServer.Start(_settings);
server
	.Given(Request.Create().WithPath("/*"))
	.AtPriority(100)
	.RespondWith(Response.Create()
		.WithProxy(new ProxyAndRecordSettings
		{
			Url = "https://wwwdev.company.com",
			AllowAutoRedirect = true,
			WebProxySettings = new WebProxySettings
			{
				Address = "http://127.0.0.1:8888",
				UserName = "",
				Password = ""
			}
		}));

Any any request, like
https://wwwmock.company.com/anything/other/a/b/c

Would call the proxy as:
https://wwwdev.company.com/anything/other/a/b/c
?

@StefH commented on GitHub (Apr 28, 2020): I would expect that using this code: ``` c# var server = WireMockServer.Start(_settings); server .Given(Request.Create().WithPath("/*")) .AtPriority(100) .RespondWith(Response.Create() .WithProxy(new ProxyAndRecordSettings { Url = "https://wwwdev.company.com", AllowAutoRedirect = true, WebProxySettings = new WebProxySettings { Address = "http://127.0.0.1:8888", UserName = "", Password = "" } })); ``` Any any request, like `https://wwwmock.company.com/anything/other/a/b/c` Would call the proxy as: `https://wwwdev.company.com/anything/other/a/b/c` ?
Author
Owner

@adatanasov commented on GitHub (Apr 29, 2020):

Thank you for the quick response!
I've tried that, but it's the same. This is info from the logger:

    "Path": "/v2/environments/current",
    "AbsolutePath": "/account/api/v2/environments/current",
    "Url": "https://wwwmock.company.com/v2/environments/current",
    "AbsoluteUrl": "https://wwwmock.company.com/account/api/v2/environments/current"

I believe it's because my WireMock service is hosted under '/account/api' and that part is omitted later from the Url.

@adatanasov commented on GitHub (Apr 29, 2020): Thank you for the quick response! I've tried that, but it's the same. This is info from the logger: ``` "Path": "/v2/environments/current", "AbsolutePath": "/account/api/v2/environments/current", "Url": "https://wwwmock.company.com/v2/environments/current", "AbsoluteUrl": "https://wwwmock.company.com/account/api/v2/environments/current" ``` I believe it's because my WireMock service is hosted under '/account/api' and that part is omitted later from the Url.
Author
Owner

@StefH commented on GitHub (Apr 29, 2020):

Just an analyze how the code currently works.

The setup is like:

server
.Given(Request.Create()
  .UsingPost()
)
.RespondWith(Response.Create()
  .WithProxy(new ProxyAndRecordSettings { Url = "http://postman-echo.com" })
);
  1. Post request to http://{{wm_hostname}}/post
    image

  2. Post request to http://{{wm_hostname}}/post/x/y/z
    image

  3. Post request to http://{{wm_hostname}}/a/b/c
    image

The current logic from WireMock is that only the baseUrl from the ProxyUrl is used, so specifying "http://postman-echo.com/post" or in your case "https://wwwdev.company.com/account/api" does not work.

However I think you are right, and that there is actually wrong logic in WireMock.
So for option 3, the value from proxyUriWithRequestPathAndQuery should be set to "http://postman-echo.com/post/a/b/c".

What do you think?

@StefH commented on GitHub (Apr 29, 2020): Just an analyze how the code currently works. The setup is like: ``` c# server .Given(Request.Create() .UsingPost() ) .RespondWith(Response.Create() .WithProxy(new ProxyAndRecordSettings { Url = "http://postman-echo.com" }) ); ``` 1. Post request to `http://{{wm_hostname}}/post` ![image](https://user-images.githubusercontent.com/249938/80573555-74a7ab80-8a00-11ea-931b-6a695b9b24fb.png) 2. Post request to `http://{{wm_hostname}}/post/x/y/z` ![image](https://user-images.githubusercontent.com/249938/80573614-8e48f300-8a00-11ea-81da-2dbac98ea959.png) 3. Post request to `http://{{wm_hostname}}/a/b/c` ![image](https://user-images.githubusercontent.com/249938/80577842-dae3fc80-8a07-11ea-925c-b787cee44b4c.png) The current logic from WireMock is that only the **baseUrl** from the **ProxyUrl** is used, so specifying "http://postman-echo.com/post" or in your case "https://wwwdev.company.com/account/api" does not work. However I think you are right, and that there is actually wrong logic in WireMock. So for option 3, the value from `proxyUriWithRequestPathAndQuery` should be set to "http://postman-echo.com/post/a/b/c". What do you think?
Author
Owner

@adatanasov commented on GitHub (Apr 29, 2020):

Yep, this should solve my issue.
Also, it shouldn't break any existing apps/logic as you can set a base URL if you need to.

@adatanasov commented on GitHub (Apr 29, 2020): Yep, this should solve my issue. Also, it shouldn't break any existing apps/logic as you can set a base URL if you need to.
Author
Owner

@StefH commented on GitHub (Apr 29, 2020):

Yes it should be backwards compatible.

Proposal:

  1. proxyUrl = http://postman-echo.com/post, request = http://{{wm_hostname}}/post ==> proxyUriWithRequestPathAndQuery = http://postman-echo.com/post

  2. proxyUrl = http://postman-echo.com/post, request = http://{{wm_hostname}}/post/x/y/z ==> proxyUriWithRequestPathAndQuery = http://postman-echo.com/post/x/y/z

  3. proxyUrl = http://postman-echo.com, request = http://{{wm_hostname}}/post/x/y/z ==> proxyUriWithRequestPathAndQuery = http://postman-echo.com/post/x/y/z

  4. proxyUrl = http://postman-echo.com/other, request = http://{{wm_hostname}}/post/x/y/z ==> proxyUriWithRequestPathAndQuery = http://postman-echo.com/other/post/x/y/z

Correct?

@StefH commented on GitHub (Apr 29, 2020): Yes it should be backwards compatible. Proposal: 1. proxyUrl = `http://postman-echo.com/post`, request = `http://{{wm_hostname}}/post` ==> proxyUriWithRequestPathAndQuery = `http://postman-echo.com/post` 2. proxyUrl = `http://postman-echo.com/post`, request = `http://{{wm_hostname}}/post/x/y/z` ==> proxyUriWithRequestPathAndQuery = `http://postman-echo.com/post/x/y/z` 3. proxyUrl = `http://postman-echo.com`, request = `http://{{wm_hostname}}/post/x/y/z` ==> proxyUriWithRequestPathAndQuery = `http://postman-echo.com/post/x/y/z` 4. proxyUrl = `http://postman-echo.com/other`, request = `http://{{wm_hostname}}/post/x/y/z` ==> proxyUriWithRequestPathAndQuery = `http://postman-echo.com/other/post/x/y/z` Correct?
Author
Owner

@adatanasov commented on GitHub (Apr 29, 2020):

I agree.

@adatanasov commented on GitHub (Apr 29, 2020): I agree.
Author
Owner

@StefH commented on GitHub (Apr 29, 2020):

Can you try MyGet version : WireMock.Net.1.2.6-ci-13251.nupkg

@StefH commented on GitHub (Apr 29, 2020): Can you try MyGet version : WireMock.Net.1.2.6-ci-13251.nupkg
Author
Owner

@StefH commented on GitHub (Apr 29, 2020):

https://github.com/WireMock-Net/WireMock.Net/pull/461

@StefH commented on GitHub (Apr 29, 2020): https://github.com/WireMock-Net/WireMock.Net/pull/461
Author
Owner

@adatanasov commented on GitHub (Apr 29, 2020):

It works as agreed.
Thanks again for the quick reaction :)

@adatanasov commented on GitHub (Apr 29, 2020): It works as agreed. Thanks again for the quick reaction :)
Author
Owner

@StefH commented on GitHub (Apr 29, 2020):

I'll make a new official release tomorrow.

@StefH commented on GitHub (Apr 29, 2020): I'll make a new official release tomorrow.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net-wiremock#268