// // ======================================================================== // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.server.handler; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.LifeCycle; import org.junit.Assert; import org.junit.Test; public class ShutdownHandlerTest { private Server server; private ServerConnector connector; private String shutdownToken = "asdlnsldgnklns"; public void start(HandlerWrapper wrapper) throws Exception { server = new Server(); connector = new ServerConnector(server); server.addConnector(connector); Handler shutdown = new ShutdownHandler(shutdownToken); Handler handler = shutdown; if (wrapper != null) { wrapper.setHandler(shutdown); handler = wrapper; } server.setHandler(handler); server.start(); } @Test public void testShutdownServerWithCorrectTokenAndIP() throws Exception { start(null); CountDownLatch stopLatch = new CountDownLatch(1); server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() { @Override public void lifeCycleStopped(LifeCycle event) { stopLatch.countDown(); } }); HttpTester.Response response = shutdown(shutdownToken); Assert.assertEquals(HttpStatus.OK_200, response.getStatus()); Assert.assertTrue(stopLatch.await(5, TimeUnit.SECONDS)); Assert.assertEquals(AbstractLifeCycle.STOPPED, server.getState()); } @Test public void testWrongToken() throws Exception { start(null); HttpTester.Response response = shutdown("wrongToken"); Assert.assertEquals(HttpStatus.UNAUTHORIZED_401, response.getStatus()); Thread.sleep(1000); Assert.assertEquals(AbstractLifeCycle.STARTED, server.getState()); } @Test public void testShutdownRequestNotFromLocalhost() throws Exception { start(new HandlerWrapper() { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setRemoteAddr(new InetSocketAddress("192.168.0.1", 12345)); super.handle(target, baseRequest, request, response); } }); HttpTester.Response response = shutdown(shutdownToken); Assert.assertEquals(HttpStatus.UNAUTHORIZED_401, response.getStatus()); Thread.sleep(1000); Assert.assertEquals(AbstractLifeCycle.STARTED, server.getState()); } private HttpTester.Response shutdown(String shutdownToken) throws IOException { try (Socket socket = new Socket("localhost", connector.getLocalPort())) { String request = "" + "POST /shutdown?token=" + shutdownToken + " HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n"; OutputStream output = socket.getOutputStream(); output.write(request.getBytes(StandardCharsets.UTF_8)); output.flush(); HttpTester.Input input = HttpTester.from(socket.getInputStream()); return HttpTester.parseResponse(input); } } }