mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.6k stars 1.07k forks source link

Mock server returning 404 when proxy over https #839

Closed annayyagari closed 2 years ago

annayyagari commented 4 years ago

Describe the issue Mock server returning 404 when used as a proxy to HTTPS

What you are trying to do I'm using Mock server to forward requests to a host over HTTPS if no expectations are found.

MockServer version Installed it using Home brew

To Reproduce Steps to reproduce the issue:

  1. I've Mock server installed using Home brew
  2. Started it up like mockserver -logLevel DEBUG -serverPort 1080 -proxyRemotePort 443 -proxyRemoteHost www.google.com
  3. I was trying to access root path from Jmeter like https://localhost:1080/ and it is always returning 404.

Expected behaviour I was expecting it to return HTTP 200 response

MockServer Log 2020-09-08 09:08:50 5.11.1 INFO 1080 received request:

{ "method" : "GET", "path" : "/", "headers" : { "Connection" : [ "keep-alive" ], "Host" : [ "localhost:1080" ], "User-Agent" : [ "Apache-HttpClient/4.5.12 (Java/1.8.0_252)" ], "content-length" : [ "0" ] }, "keepAlive" : true, "secure" : true }

2020-09-08 09:08:50 5.11.1 INFO 1080 returning response:

{ "statusCode" : 404, "reasonPhrase" : "Not Found", "headers" : { "Content-Type" : [ "text/html; charset=UTF-8" ], "Referrer-Policy" : [ "no-referrer" ], "Content-Length" : [ "1561" ], "Date" : [ "Tue, 08 Sep 2020 08:08:50 GMT" ], "Alt-Svc" : [ "h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\"" ] }, "body" : "<!DOCTYPE html>\n\n \n <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">\n Error 404 (Not Found)!!1\n \n \n

404. That’s an error.\n

The requested URL / was not found on this server. That’s all we know.\n" }

for forwarded request

in json:

{ "method" : "GET", "path" : "/", "headers" : { "Connection" : [ "keep-alive" ], "Host" : [ "localhost:1080" ], "User-Agent" : [ "Apache-HttpClient/4.5.12 (Java/1.8.0_252)" ], "content-length" : [ "0" ] }, "keepAlive" : true, "secure" : true }

in curl:

curl -v 'https://localhost:1080/' -H 'Connection: keep-alive' -H 'Host: localhost:1080' -H 'User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_252)' -H 'content-length: 0'

annayyagari commented 4 years ago

Came across with the Issue 431 https://github.com/mock-server/mockserver/issues/431 My issue above listed is happening for same reason. Is it possible to update Mock server so that it passes proxyRemoteHost value as Host header instead of the source of the request?

jamesdbloom commented 4 years ago

The issue with overwriting the Host header is that not all consumers would want that behaviour. It is not possible to send the correct value for the Host header so that when the request is forwarded the Host head is correct?

Given MockServer in this case is acting as a pure reverse proxy your client should be able to set any header is needs to. If not can you please explain your use case so that I can understand how best to solve the problem.

annayyagari commented 4 years ago

We are using mock server as a mock and as a proxy to third-party application. We don't have any requirement to set Host header in the request. When we send request directly to third-party application with no host header, it works. But when we use Mock server as a proxy, request is failing because of incorrect host header being set on the request. Not sure if Mock server is setting host header in this case. For now, we found a work around to pass Host header by checking if it is not null or empty, so that we can leave it as blank for production and populate it with correct value for test only.

jamesdbloom commented 4 years ago

Yes I agree it does make sense when in reverse proxy mode to set the host header using the proxyRemotePort value.

I'll add this to the backlog and should be able to do this for the next release.

seeni-dev commented 3 years ago

While this issue is getting fixed, if someone wants a working solution, refer below gist. https://gist.github.com/Seenivasanseeni/5faff6dc88e052e31ac3a419b3b40b57

shaaraddalvi commented 3 years ago

+1, also not sure if this is specific to HTTPS, any web service that validates the value of host header would return 404 to the proxied requests

jamesdbloom commented 2 years ago

Changing the host header would not be valid for the majority of proxy cases. However, it is possible to get MockServer to do this using a forward overridden request as shown in the documentation here: https://mock-server.com/mock_server/creating_expectations.html#button_forward_overridden.

For example:

new MockServerClient("localhost", 1080)
    .when(
        request()
    )
    .forward(
        forwardOverriddenRequest(
            request()
                .withHeader(header("Host", "www.google.com"))
                .withSecure(true)
        )
    );

This will forward all request to that host using https.