aboutsummaryrefslogtreecommitdiffstats
path: root/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java
diff options
context:
space:
mode:
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.java69
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;
9import java.net.URI; 9import java.net.URI;
10import java.net.URISyntaxException; 10import java.net.URISyntaxException;
11import java.util.EnumSet; 11import java.util.EnumSet;
12import java.util.Optional;
12import java.util.Set; 13import java.util.Set;
13 14
14import org.eclipse.jetty.server.Server; 15import org.eclipse.jetty.server.Server;
@@ -22,24 +23,28 @@ import org.slf4j.LoggerFactory;
22 23
23import jakarta.servlet.DispatcherType; 24import jakarta.servlet.DispatcherType;
24import jakarta.servlet.SessionTrackingMode; 25import jakarta.servlet.SessionTrackingMode;
26import tools.refinery.language.web.xtext.XtextWebSocketServlet;
25 27
26public class ServerLauncher { 28public 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}