0

I am using https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-consumer-junit, which uses MockServer, which uses Netty.

The launched Netty listens on loopback only (netstat -tulpn output:)

tcp 0 0 127.0.0.1:21221 0.0.0.0:* LISTEN 27681/java

, but I want it to listen to "the outside world". I want the launched Netty to accept connections on my LAN-IP address (192.168.x.y:21221 as local address, for example), or even every incoming connection to the Netty-port (0.0.0.0:21221 as local address). As my framework chain somehow makes Netty-configuration, well, far away, I would like to do that when starting my application, using a System property. Something like

    System.setProperty("io.netty.listenAddress", "0.0.0.0");

Is this somehow possible?

Markus Schulte
  • 4,171
  • 3
  • 47
  • 58
  • What do you mean by all interfaces? you want it to listen to eth*? How many interfaces do you have? What's the use case? Please try to explain your situation fully. Cheers. – J_A_X Apr 08 '17 at 10:22
  • Ah gotcha, sorry for the confusion. We could have it do that, sure, but my question to you would be this; do you think that this is the responsibility for pact? Seems to me that it's a bit outside the realm of responsibility for pact. I understand that you have a particular use case, but I think you would be better if you relied on another tool specifically made for your situation and you can then tailor it to your use case. – J_A_X Apr 09 '17 at 23:01
  • I don't think it's the responsibility for Pact right know, I think, it's Netty. In the first place, I would like to know, if my requirement is possible with Netty. Hopefully/maybe later, a discovered or new Netty-configuration could be documented/used/integrated in https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-consumer-junit – Markus Schulte Apr 10 '17 at 07:42
  • Yeah, can't help too much with that since my knowledge of Netty is limited, but I do recommend that you look for something external to point to the pact mock service. – J_A_X Apr 10 '17 at 23:28
  • 1
    I got already a workaround. After stating (Pact->MockServer->)Netty, I am starting a ReverseProxy, using https://github.com/adamfisk/LittleProxy – Markus Schulte Apr 11 '17 at 06:46
  • great! Please detail your answer on your own question and accept it :) – J_A_X Apr 11 '17 at 06:51
  • I will do that, but well, more as a help for others, less as an answer to my question. – Markus Schulte Apr 11 '17 at 07:19
  • Maybe I can achieve my requirement using PactProviderRule, but not right now, see https://github.com/DiUS/pact-jvm/issues/404 – Markus Schulte Apr 11 '17 at 15:16

1 Answers1

0

You can achieve your requirement by placing a ReverseProxy in front of your (Pact->MockServer->)Netty.

Here is a full example. For having a ReverseProxy, LittleProxy is used. This example uses, as mentioned, pact-jvm-consumer-junit, and for doing HTTP-calls, HtmlUnit.

import au.com.dius.pact.consumer.Pact;
import au.com.dius.pact.consumer.PactProviderRule;
import au.com.dius.pact.consumer.PactVerification;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.model.MockProviderConfig;
import au.com.dius.pact.model.PactFragment;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.littleshoot.proxy.ChainedProxyAdapter;
import org.littleshoot.proxy.ChainedProxyManager;
import org.littleshoot.proxy.HttpProxyServer;
import org.littleshoot.proxy.impl.DefaultHttpProxyServer;

public class HelloIT {

  private static final String PROVIDER_SERVICE_PATH = "/provider-endpoint";

  @Rule
  public PactProviderRule pactProviderServiceMock
    = new PactProviderRule("provider-service", this);

  private final String providerServiceReverseProxyUrl;

  private static HttpProxyServer createReverseProxy(final MockProviderConfig mockProviderConfig) {
    final String ip = mockProviderConfig.getHostname();
    final int port = mockProviderConfig.getPort();

    final ChainedProxyManager cpm = (httpRequest, chainedProxies) -> {
      final ChainedProxyAdapter chainedProxy = new ChainedProxyAdapter() {
        @Override
        public InetSocketAddress getChainedProxyAddress() {
          return new InetSocketAddress(ip, port);
        }
      };
      chainedProxies.add(chainedProxy);
    };

    return DefaultHttpProxyServer.bootstrap()
      .withChainProxyManager(cpm)
      .withPort(0)
      .withAllowLocalOnly(false)
      .withAllowRequestToOriginServer(true)
      .start();
  }

  {
    /*
     * Pact-mock for provider-service listens on loopback only. Using reverse proxy for interaction
     * between consumer-service and provider-service on external IP.
     */
    final HttpProxyServer providerServiceReverseProxy
      = HelloIT.createReverseProxy(pactProviderServiceMock.getConfig());

    this.providerServiceReverseProxyUrl
      = "http://<your-external-IP>:" + providerServiceReverseProxy.getListenAddress().getPort();
  }

  @Pact(consumer = "consumer-service")
  public PactFragment createFragment(final PactDslWithProvider builder) {
    return builder
      .uponReceiving("Some request")
      .path(PROVIDER_SERVICE_PATH)
      .method("GET")
      .willRespondWith()
      .status(200)
      .toFragment();
  }

  @Test
  @PactVerification
  public void index() throws IOException {
    final Page page
      = new WebClient().getPage(this.providerServiceReverseProxyUrl + PROVIDER_SERVICE_PATH);
    Assert.assertEquals(200, page.getWebResponse().getStatusCode());
  }
}
Markus Schulte
  • 4,171
  • 3
  • 47
  • 58