Embedded jetty and guice Handler servlet upon request domain(vhost)

923 Views Asked by At

In details, I am using one single jetty server by java embedding that will handle multiple request. I am injecting the event listener and the security filter with guice. But i need to server servlet upon the request domian. I am trying with virtual host, but as i am not using xml based configuration there is not much documentation to get help of.

So i am trying is that -

If domain a.b.c -> handler AHandler and filter applied AFilter,

If domain b.b.c -> handler BHandler and filter applied BFilter.

My Contex initialization is like this:

getHandler(server) {
        ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        handler.setVirtualHosts(new String[]{HOST});
        handler.setClassLoader(Thread.currentThread().getContextClassLoader());
        handler.setServer(server);
        handler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
        handler.setContextPath("/");
        handler.addEventListener(new ServerContextListener());
}

Listener class

class ServerContextListener extends GuiceServletContextListener {
  private ServletContext servletContext;

  public ServletContext getServletContext() {
    return servletContext;
  }

  @Override
  public void contextInitialized(ServletContextEvent servletContextEvent) {
    this.servletContext = checkNotNull(servletContextEvent.getServletContext(), "servletContext");
    super.contextInitialized(servletContextEvent);
  }

  @Override
  protected Injector getInjector() {
    return Guice.createInjector(getModules());
  }

  private Iterable<Module> getModules() {
    return ImmutableList.of(
        new SecurityModule(getServletContext()),
        new ResourceModule());
  }
}

Security Module:

class SecurityModule extends ShiroWebModule {

  public SecurityModule(ServletContext servletContext) {
    super(servletContext);
  }

  @SuppressWarnings("unchecked")
  @Override
  protected void configureShiroWeb() {
    addFilterChain("/**", AUTHC_BASIC);
  }
}


class ResourceModule extends ServletModule {

  @Override
  protected void configureServlets() {
    serve("/*").with(AServlet.class);
  }
}

And the in the server like this :

Server server = new Server(new InetSocketAddress("0.0.0.0", 8585));

HandlerCollection handler = new HandlerCollection();
handler.addHandler(AContext.getHandler(server));
handler.addHandler(BContext.getHandler(server));

server.setHandler(handler);
server.start();

and the AServlet and BServlet are regular servlet with get post put methods.

But my implementaion is not working as expected. It sends all request to the last handler registered.

Need some help to accomplish what I need. Where I am doing things wrong?

1

There are 1 best solutions below

3
On

Whatever the Handler implementation is returned for these 2 calls...

handler.addHandler(AContext.getHandler(server));
handler.addHandler(BContext.getHandler(server));

They should have a ContextHandler wrapping them, as that's how Virtual Hosts are configured and controlled for a specific Handler implementation.

Added VirtualHostsExample.java to jetty-project/embedded-jetty-cookbook.

package org.eclipse.jetty.cookbook;

import java.io.IOException;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.IO;

public class VirtualHostsExample
{
    public static void main(String[] args)
    {
        VirtualHostsExample example = new VirtualHostsExample();
        try
        {
            example.startServer();
            example.testRequest("a.company.com","/hello");
            example.testRequest("b.company.com","/hello");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            example.stopServer();
        }
    }

    private Server server;

    private void stopServer()
    {
        try { server.stop(); }
        catch (Exception ignore) { }
    }

    private void startServer() throws Exception
    {
        server = new Server(8080);
        HandlerCollection handlers = new HandlerCollection();
        server.setHandler(handlers);

        handlers.addHandler(createContext("/", "a.company.com"));
        handlers.addHandler(createContext("/", "b.company.com"));

        server.start();
    }

    private ContextHandler createContext(String contextPath, final String host)
    {
        ServletContextHandler context = new ServletContextHandler();
        context.setContextPath(contextPath);
        @SuppressWarnings("serial")
        ServletHolder helloholder = new ServletHolder(new HttpServlet()
        {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
            {
                resp.setContentType("text/plain");
                resp.getWriter().printf("Hello from [%s] context%n",host);
            }
        });
        context.addServlet(helloholder, "/hello");
        context.addServlet(DefaultServlet.class,"/");
        ContextHandler vhwrapper = new ContextHandler();
        vhwrapper.setHandler(context);
        vhwrapper.setVirtualHosts(new String[]{host});
        return vhwrapper;
    }

    private void testRequest(String host, String path)
    {
        try(Socket client = new Socket("localhost",8080);)
        {
            System.out.printf("-- testRequest [%s] [%s] --%n",host,path);
            String req = String.format("GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",path,host);
            System.out.print(req);
            client.getOutputStream().write(req.getBytes(StandardCharsets.UTF_8));
            String response = IO.toString(client.getInputStream());
            System.out.print(response);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

With output like this ...

2016-02-13 08:33:29.142:INFO::main: Logging initialized @130ms
2016-02-13 08:33:29.197:INFO:oejs.Server:main: jetty-9.3.7.v20160115
2016-02-13 08:33:29.221:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@12bb4df8{/,null,AVAILABLE}
2016-02-13 08:33:29.221:INFO:oejsh.ContextHandler:main: Started o.e.j.s.h.ContextHandler@4cc77c2e{/,null,AVAILABLE,a.company.com}
2016-02-13 08:33:29.221:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@71bc1ae4{/,null,AVAILABLE}
2016-02-13 08:33:29.222:INFO:oejsh.ContextHandler:main: Started o.e.j.s.h.ContextHandler@6ed3ef1{/,null,AVAILABLE,b.company.com}
2016-02-13 08:33:29.233:INFO:oejs.ServerConnector:main: Started ServerConnector@1babf7a6{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2016-02-13 08:33:29.234:INFO:oejs.Server:main: Started @225ms
-- testRequest [a.company.com] [/hello] --
GET /hello HTTP/1.1
Host: a.company.com
Connection: close

HTTP/1.1 200 OK
Date: Sat, 13 Feb 2016 15:33:29 GMT
Content-Type: text/plain;charset=iso-8859-1
Connection: close
Server: Jetty(9.3.7.v20160115)

Hello from [a.company.com] context
-- testRequest [b.company.com] [/hello] --
GET /hello HTTP/1.1
Host: b.company.com
Connection: close

HTTP/1.1 200 OK
Date: Sat, 13 Feb 2016 15:33:29 GMT
Content-Type: text/plain;charset=iso-8859-1
Connection: close
Server: Jetty(9.3.7.v20160115)

Hello from [b.company.com] context
2016-02-13 08:33:29.340:INFO:oejs.ServerConnector:main: Stopped ServerConnector@1babf7a6{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2016-02-13 08:33:29.342:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.ServletContextHandler@71bc1ae4{/,null,UNAVAILABLE}
2016-02-13 08:33:29.342:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.h.ContextHandler@6ed3ef1{/,null,UNAVAILABLE,b.company.com}
2016-02-13 08:33:29.342:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.ServletContextHandler@12bb4df8{/,null,UNAVAILABLE}
2016-02-13 08:33:29.342:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.h.ContextHandler@4cc77c2e{/,null,UNAVAILABLE,a.company.com}