1

I need to build a (standalone Java) restlet-based service that only listens on localhost, i.e. no requests from network are allowed.

I was trying to do the obvious:

Server srv = new Server(Protocol.HTTPS, "localhost", httpsPort); 
component.getServers().add(srv);

But the service still listens on 0.0.0.0. :-(

I went into the code and found that HttpsServerHelper ignores the hostname when creating the service:

this.server = HttpsServer.create(new InetSocketAddress(getHelped().getPort()), 0);

Similar code exists in plain HTTP's HttpServerHelper, where it is even more clear.

My question then is this:

How can I configure Restlet component/service to only listen on localhost?

Vladimir Dyuzhev
  • 17,603
  • 9
  • 45
  • 61

2 Answers2

3

I don't know which server you use under the hood within your standalone Restlet application. You should use a server connector other than the default one and I recommend you to use the Jetty one.

To do that, simply put the jar of the extension org.restlet.ext.jetty in your classpath.

In this case, using the following code should correspond to your needs:

component.getServers().add(Protocol.HTTP, "localhost", 8182);

Here is the corresponding trace at application startup:

2015-09-03 09:47:22.180:INFO::jetty-7.1.6.v20100715
2015-09-03 09:47:22.211:INFO::Started SelectChannelConnector@localhost:8182

In addition, here is the link in the Restlet documentation regarding Restlet connectors: http://restlet.com/technical-resources/restlet-framework/guide/2.3/core/base/connectors.

Hope it helps you, Thierry

Thierry Templier
  • 182,931
  • 35
  • 372
  • 339
  • Thank you, that was the culprit. I was using the internal web server (because in another packaging variant I have to deploy to Weblogic), and the internal web server apparently simply ignores the listen host specification. When I added Jetty, the existing code worked immediately without changes. – Vladimir Dyuzhev Sep 08 '15 at 02:25
  • P.S. May be the internal web server should log a warning if the code tries to specify the host. Costed me like 2 days of head-banging :-) – Vladimir Dyuzhev Sep 08 '15 at 02:28
  • You're welcome! Yes, agreed with you for the warning! – Thierry Templier Sep 08 '15 at 06:43
2

The easier way to achieve that is to use virtual hosts. Virtual hosts are the first routing barrier when handling a request, especially it helps routing on a domain.

Here is a sample code that illustrates this:

    Component c = new Component();
    c.getServers().add(Protocol.HTTP, 8182);

    VirtualHost host = new VirtualHost();
    host.setHostDomain("localhost");
    c.getHosts().add(host);
    host.attach(new Restlet() {
        @Override
        public void handle(Request request, Response response) {
            response.setEntity("hello, world", MediaType.TEXT_PLAIN);
        }
    });

    c.start();

Usually, applications are attached on the default host of a component. This default host does nothing, except routing requests based on the context path of the attached application:

    c.getDefaultHost().attach("/contextPath1", new Test1Application());
    c.getDefaultHost().attach("/contextPath2", new Test2Application());

When you would like to filter calls based on other data than the request's path, virtual host may be the solution.

Here is a diagram that may help you:

http://restlet.com/technical-resources/restlet-framework/tutorials/2.3#part05

Thierry Boileau
  • 856
  • 5
  • 8
  • Thank you for the educational post, I learned quite a lot about virtual hosts. One comment for your code: the new VirtualHost() should take c.getContext(), otherwise I'm getting NPE at attach step. – Vladimir Dyuzhev Sep 08 '15 at 02:27