diff options
Diffstat (limited to 'language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java')
-rw-r--r-- | language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java b/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java index c253422b..0942b680 100644 --- a/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java +++ b/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java | |||
@@ -9,6 +9,7 @@ import java.net.InetSocketAddress; | |||
9 | import java.net.URI; | 9 | import java.net.URI; |
10 | import java.net.URISyntaxException; | 10 | import java.net.URISyntaxException; |
11 | import java.util.EnumSet; | 11 | import java.util.EnumSet; |
12 | import java.util.Optional; | ||
12 | import java.util.Set; | 13 | import java.util.Set; |
13 | 14 | ||
14 | import org.eclipse.jetty.server.Server; | 15 | import org.eclipse.jetty.server.Server; |
@@ -22,24 +23,28 @@ import org.slf4j.LoggerFactory; | |||
22 | 23 | ||
23 | import jakarta.servlet.DispatcherType; | 24 | import jakarta.servlet.DispatcherType; |
24 | import jakarta.servlet.SessionTrackingMode; | 25 | import jakarta.servlet.SessionTrackingMode; |
26 | import tools.refinery.language.web.xtext.XtextWebSocketServlet; | ||
25 | 27 | ||
26 | public class ServerLauncher { | 28 | public class ServerLauncher { |
27 | public static final String DEFAULT_LISTEN_ADDRESS = "localhost"; | 29 | public static final String DEFAULT_LISTEN_ADDRESS = "localhost"; |
28 | 30 | ||
29 | public static final int DEFAULT_LISTEN_PORT = 1312; | 31 | public static final int DEFAULT_LISTEN_PORT = 1312; |
30 | 32 | ||
31 | // Use this cookie name for load balancing. | 33 | public static final int DEFAULT_PUBLIC_PORT = 443; |
32 | public static final String SESSION_COOKIE_NAME = "JSESSIONID"; | 34 | |
35 | public static final int HTTP_DEFAULT_PORT = 80; | ||
36 | |||
37 | public static final int HTTPS_DEFAULT_PORT = 443; | ||
33 | 38 | ||
34 | private static final Logger LOG = LoggerFactory.getLogger(ServerLauncher.class); | 39 | private static final Logger LOG = LoggerFactory.getLogger(ServerLauncher.class); |
35 | 40 | ||
36 | private final Server server; | 41 | private final Server server; |
37 | 42 | ||
38 | public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource) { | 43 | public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource, Optional<String[]> allowedOrigins) { |
39 | server = new Server(bindAddress); | 44 | server = new Server(bindAddress); |
40 | var handler = new ServletContextHandler(); | 45 | var handler = new ServletContextHandler(); |
41 | addSessionHandler(handler); | 46 | addSessionHandler(handler); |
42 | addProblemServlet(handler); | 47 | addProblemServlet(handler, allowedOrigins); |
43 | if (baseResource != null) { | 48 | if (baseResource != null) { |
44 | handler.setBaseResource(baseResource); | 49 | handler.setBaseResource(baseResource); |
45 | handler.setWelcomeFiles(new String[] { "index.html" }); | 50 | handler.setWelcomeFiles(new String[] { "index.html" }); |
@@ -52,12 +57,20 @@ public class ServerLauncher { | |||
52 | private void addSessionHandler(ServletContextHandler handler) { | 57 | private void addSessionHandler(ServletContextHandler handler) { |
53 | var sessionHandler = new SessionHandler(); | 58 | var sessionHandler = new SessionHandler(); |
54 | sessionHandler.setSessionTrackingModes(Set.of(SessionTrackingMode.COOKIE)); | 59 | sessionHandler.setSessionTrackingModes(Set.of(SessionTrackingMode.COOKIE)); |
55 | sessionHandler.setSessionCookie(SESSION_COOKIE_NAME); | ||
56 | handler.setSessionHandler(sessionHandler); | 60 | handler.setSessionHandler(sessionHandler); |
57 | } | 61 | } |
58 | 62 | ||
59 | private void addProblemServlet(ServletContextHandler handler) { | 63 | private void addProblemServlet(ServletContextHandler handler, Optional<String[]> allowedOrigins) { |
60 | handler.addServlet(ProblemServlet.class, "/xtext-service/*"); | 64 | var problemServletHolder = new ServletHolder(ProblemWebSocketServlet.class); |
65 | if (allowedOrigins.isEmpty()) { | ||
66 | LOG.warn("All WebSocket origins are allowed! This setting should not be used in production!"); | ||
67 | } else { | ||
68 | var allowedOriginsString = String.join(XtextWebSocketServlet.ALLOWED_ORIGINS_SEPARATOR, | ||
69 | allowedOrigins.get()); | ||
70 | problemServletHolder.setInitParameter(XtextWebSocketServlet.ALLOWED_ORIGINS_INIT_PARAM, | ||
71 | allowedOriginsString); | ||
72 | } | ||
73 | handler.addServlet(problemServletHolder, "/xtext-service/*"); | ||
61 | } | 74 | } |
62 | 75 | ||
63 | private void addDefaultServlet(ServletContextHandler handler) { | 76 | private void addDefaultServlet(ServletContextHandler handler) { |
@@ -80,7 +93,8 @@ public class ServerLauncher { | |||
80 | try { | 93 | try { |
81 | var bindAddress = getBindAddress(); | 94 | var bindAddress = getBindAddress(); |
82 | var baseResource = getBaseResource(); | 95 | var baseResource = getBaseResource(); |
83 | var serverLauncher = new ServerLauncher(bindAddress, baseResource); | 96 | var allowedOrigins = getAllowedOrigins(); |
97 | var serverLauncher = new ServerLauncher(bindAddress, baseResource, allowedOrigins); | ||
84 | serverLauncher.start(); | 98 | serverLauncher.start(); |
85 | } catch (Exception exception) { | 99 | } catch (Exception exception) { |
86 | LOG.error("Fatal server error", exception); | 100 | LOG.error("Fatal server error", exception); |
@@ -132,4 +146,43 @@ public class ServerLauncher { | |||
132 | // Fall back to just serving a 404. | 146 | // Fall back to just serving a 404. |
133 | return null; | 147 | return null; |
134 | } | 148 | } |
149 | |||
150 | private static String getPublicHost() { | ||
151 | var publicHost = System.getenv("PUBLIC_HOST"); | ||
152 | if (publicHost != null) { | ||
153 | return publicHost.toLowerCase(); | ||
154 | } | ||
155 | return null; | ||
156 | } | ||
157 | |||
158 | private static int getPublicPort() { | ||
159 | var portStr = System.getenv("PUBLIC_PORT"); | ||
160 | if (portStr != null) { | ||
161 | return Integer.parseInt(portStr); | ||
162 | } | ||
163 | return DEFAULT_LISTEN_PORT; | ||
164 | } | ||
165 | |||
166 | private static Optional<String[]> getAllowedOrigins() { | ||
167 | var allowedOrigins = System.getenv("ALLOWED_ORIGINS"); | ||
168 | if (allowedOrigins != null) { | ||
169 | return Optional.of(allowedOrigins.split(XtextWebSocketServlet.ALLOWED_ORIGINS_SEPARATOR)); | ||
170 | } | ||
171 | return getAllowedOriginsFromPublicHostAndPort(); | ||
172 | } | ||
173 | |||
174 | private static Optional<String[]> getAllowedOriginsFromPublicHostAndPort() { | ||
175 | var publicHost = getPublicHost(); | ||
176 | if (publicHost == null) { | ||
177 | return Optional.empty(); | ||
178 | } | ||
179 | int publicPort = getPublicPort(); | ||
180 | var scheme = publicPort == HTTPS_DEFAULT_PORT ? "https" : "http"; | ||
181 | var urlWithPort = String.format("%s://%s:%d", scheme, publicHost, publicPort); | ||
182 | if (publicPort == HTTPS_DEFAULT_PORT || publicPort == HTTP_DEFAULT_PORT) { | ||
183 | var urlWithoutPort = String.format("%s://%s", scheme, publicHost); | ||
184 | return Optional.of(new String[] { urlWithPort, urlWithoutPort }); | ||
185 | } | ||
186 | return Optional.of(new String[] { urlWithPort }); | ||
187 | } | ||
135 | } | 188 | } |