Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
adatanasov opened this issue Apr 28, 2020 · 10 comments
Closed
Labels

Comments

@adatanasov
Copy link

adatanasov commented 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:https://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.

@StefH
Copy link
Collaborator

StefH commented 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:https://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
?

@adatanasov
Copy link
Author

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.

@StefH
Copy link
Collaborator

StefH commented 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:https://postman-echo.com" })
);
  1. Post request to http:https://{{wm_hostname}}/post
    image

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

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

The current logic from WireMock is that only the baseUrl from the ProxyUrl is used, so specifying "http:https://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:https://postman-echo.com/post/a/b/c".

What do you think?

@adatanasov
Copy link
Author

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.

@StefH
Copy link
Collaborator

StefH commented Apr 29, 2020

Yes it should be backwards compatible.

Proposal:

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

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

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

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

Correct?

@adatanasov
Copy link
Author

I agree.

@StefH StefH added the bug label Apr 29, 2020
@StefH
Copy link
Collaborator

StefH commented Apr 29, 2020

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

@StefH
Copy link
Collaborator

StefH commented Apr 29, 2020

#461

@adatanasov
Copy link
Author

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

@StefH
Copy link
Collaborator

StefH commented Apr 29, 2020

I'll make a new official release tomorrow.

@StefH StefH closed this as completed Apr 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants