package com.softwaremill.common.testserver; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.ssl.SslContextFactory; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import static org.eclipse.jetty.util.security.Constraint.__BASIC_AUTH; /** * @author Maciej Bilas * @author Paweł Stawicki * @since 7/11/12 0:21 */ public class TestServer { private final static int JETTY_PORT = 18182; private final static int JETTY_HTTPS_PORT = 18183; private final int port; private final int httpsPort; private Server server; private ConstraintSecurityHandler securityHandler = null; private List<Responder> responders = new ArrayList<Responder>(); public TestServer() { this(JETTY_PORT, JETTY_HTTPS_PORT); } public TestServer(int port) { this(port, JETTY_HTTPS_PORT); } public TestServer(int port, int httpsPort) { this.port = port; this.httpsPort = httpsPort; } public void addResponder(Responder responder) { responders.add(responder); } public void start() throws Exception { server = new Server(port); buildSecurityHandlerIfNecessary(); securityHandler.setHandler(createRespondersHandler()); server.setHandler(securityHandler); ServerConnector sslConnector = createSslConnector(); server.addConnector(sslConnector); server.start(); } private ServerConnector createSslConnector() { SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(getClass().getResource("/dummy.keystore").toExternalForm()); sslContextFactory.setKeyStorePassword("qwerty"); sslContextFactory.setKeyManagerPassword("qwerty"); SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()); HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory(); ServerConnector connector = new ServerConnector(server, sslConnectionFactory, httpConnectionFactory); connector.setPort(httpsPort); return connector; } private Handler createRespondersHandler() { return new AbstractHandler() { @Override public void handle(String s, Request request, HttpServletRequest httpRequest, HttpServletResponse response) throws IOException, ServletException { for(Responder responder : responders) { if (responder.canRespond(httpRequest)) { request.setHandled(true); responder.respond(request, response); return; } } response.setContentType("text/plain;charset=utf-8"); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); PrintWriter responseWriter = response.getWriter(); try { responseWriter.print("No responder could handle this request"); } finally { responseWriter.close(); } } }; } public void secure(String path, String username, String password) { buildSecurityHandlerIfNecessary(); addConstraint(path, username, password); } private void buildSecurityHandlerIfNecessary() { if (securityHandler == null) { HashLoginService l = new HashLoginService(); l.setName("realm"); ConstraintSecurityHandler csh = new ConstraintSecurityHandler(); csh.setAuthenticator(new BasicAuthenticator()); csh.setRealmName("realm"); csh.setLoginService(l); securityHandler = csh; } } private void addConstraint(String path, String username, String password) { /* Bad, evil casting :/ */ HashLoginService l = (HashLoginService) securityHandler.getLoginService(); l.putUser(username, Credential.getCredential(password), new String[]{"user"}); org.eclipse.jetty.util.security.Constraint constraint = new org.eclipse.jetty.util.security.Constraint(); constraint.setName(__BASIC_AUTH); constraint.setRoles(new String[]{"user"}); constraint.setAuthenticate(true); ConstraintMapping cm = new ConstraintMapping(); cm.setConstraint(constraint); cm.setPathSpec(path); securityHandler.addConstraintMapping(cm); } public void stop() throws Exception { server.stop(); } public void clearResponders() { responders.clear(); } }