/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.nifi.websocket.example; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.eclipse.jetty.websocket.api.WebSocketListener; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; import org.eclipse.jetty.websocket.servlet.WebSocketCreator; import org.eclipse.jetty.websocket.servlet.WebSocketServlet; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * This is a WebSocket server example testcase. */ @Ignore public class WebSocketServerExample { private static Logger logger = LoggerFactory.getLogger(WebSocketServerExample.class); private static Server server; private static ServletHandler servletHandler; private static ServletHolder servletHolder; private static ServerConnector httpConnector; private static ServerConnector sslConnector; private static final Map<Integer, WebSocketServerExample> portToController = new HashMap<>(); private Map<String, WebSocketListener> listeners = new HashMap<>(); public class SocketListener extends WebSocketAdapter { public SocketListener() { logger.info("New instance is created: {}", this); } @Override public void onWebSocketConnect(Session session) { logger.info("Connected, {}, {}", session.getLocalAddress(), session.getRemoteAddress()); super.onWebSocketConnect(session); session.getUpgradeRequest().getRequestURI(); } @Override public void onWebSocketText(String message) { logger.info("Received: {}", message); final String resultMessage; if (message.startsWith("add-servlet")) { // Is it possible to add servlet mapping?? final String path = message.split(":")[1].trim(); servletHandler.addServletWithMapping(servletHolder, path); resultMessage = "Deployed new servlet under: " + path; } else { resultMessage = "Got message: " + message; } try { getSession().getRemote().sendString(resultMessage); } catch (IOException e) { logger.error("Failed to send a message back to remote.", e); } } } public WebSocketServerExample() { this.listeners.put("/test", new SocketListener()); portToController.put(httpConnector.getPort(), this); portToController.put(sslConnector.getPort(), this); } public static class WSServlet extends WebSocketServlet implements WebSocketCreator { @Override public void configure(WebSocketServletFactory webSocketServletFactory) { webSocketServletFactory.setCreator(this); } @Override public Object createWebSocket(ServletUpgradeRequest servletUpgradeRequest, ServletUpgradeResponse servletUpgradeResponse) { final WebSocketServerExample testWebSocket = portToController.get(servletUpgradeRequest.getLocalPort()); return testWebSocket.listeners.get(servletUpgradeRequest.getRequestURI().getPath()); } } public static class ConnectionCheckServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/plain"); resp.setStatus(HttpServletResponse.SC_OK); resp.getWriter().println("Ok :)"); } } @BeforeClass public static void setup() throws Exception { server = new Server(0); final ContextHandlerCollection handlerCollection = new ContextHandlerCollection(); final ServletContextHandler contextHandler = new ServletContextHandler(); servletHandler = new ServletHandler(); contextHandler.insertHandler(servletHandler); handlerCollection.setHandlers(new Handler[]{contextHandler}); server.setHandler(handlerCollection); httpConnector = new ServerConnector(server); httpConnector.setPort(50010); final SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath("src/test/resources/certs/localhost-ks.jks"); sslContextFactory.setKeyStorePassword("localtest"); sslContextFactory.setKeyStoreType("JKS"); final HttpConfiguration https = new HttpConfiguration(); https.addCustomizer(new SecureRequestCustomizer()); sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), new HttpConnectionFactory(https)); sslConnector.setPort(50011); server.setConnectors(new Connector[]{httpConnector, sslConnector}); servletHolder = servletHandler.addServletWithMapping(WSServlet.class, "/test"); servletHolder = servletHandler.addServletWithMapping(ConnectionCheckServlet.class, "/check"); server.start(); logger.info("Starting server on port {} for HTTP, and {} for HTTPS", httpConnector.getLocalPort(), sslConnector.getLocalPort()); } @AfterClass public static void teardown() throws Exception { logger.info("Stopping server."); try { server.stop(); } catch (Exception e) { logger.error("Failed to stop Jetty server due to " + e, e); } } @Test public void test() throws Exception { logger.info("Waiting for a while..."); Thread.sleep(1000_000); } }