From e888ee0d9ed651bc35797043e0da7a455dbdead6 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Tue, 23 Jan 2024 16:24:18 -0800 Subject: [PATCH 1/3] Support additional context paths - for the primary deployment, for redirecting, and for secondary static content --- server/configs/application.properties | 14 ++++ .../src/org/labkey/embedded/LabKeyServer.java | 77 ++++++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/server/configs/application.properties b/server/configs/application.properties index 6988270391..9f405cb8d7 100644 --- a/server/configs/application.properties +++ b/server/configs/application.properties @@ -32,6 +32,20 @@ context.validationQuery[0]=SELECT 1 #useLocalBuild#context.webAppLocation=@@pathToServer@@/build/deploy/labkeyWebapp context.encryptionKey=@@encryptionKey@@ + +# By default, we'll deploy to the root context path. However, some servers have historically used /labkey or even /cpas +#context.contextPath=/labkey + +# Using a legacy context path provides backwards compatibility with old deployments. A typical use case would be to +# deploy to the root context (the default) and configure /labkey as the legacy path. GETs will be redirected, and +# non-GETs will be handled server-side via a servlet forward. +#context.legacyContextPath=/labkey + +# Other webapps to be deployed, most commonly to deliver a set of static files. Additional +# webapps can be specified via additional indices. docBase should point at the root of the webapp's content +#webapps.contextPath[0]=/anotherWebapp +#webapps.docBase[0]=/my/webapp/path + #context.oldEncryptionKey= #context.requiredModules= #context.pipelineConfig=/path/to/pipeline/config/dir diff --git a/server/embedded/src/org/labkey/embedded/LabKeyServer.java b/server/embedded/src/org/labkey/embedded/LabKeyServer.java index d5ff140dab..f923697dfc 100644 --- a/server/embedded/src/org/labkey/embedded/LabKeyServer.java +++ b/server/embedded/src/org/labkey/embedded/LabKeyServer.java @@ -86,6 +86,12 @@ public JmsProperties jmsSource() return new JmsProperties(); } + @Bean + public WebappProperties additionalWebappSource() + { + return new WebappProperties(); + } + @Bean public CSPFilterProperties cspSource() { @@ -156,7 +162,7 @@ protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) } // set the root path to the context explicitly - context.setPath(""); + context.setPath(contextProperties.getContextPath()); // Push the JDBC connection for the primary DB into the context so that the LabKey webapp finds them getDataSourceResources(contextProperties, context).forEach(contextResource -> context.getNamingResources().addResource(contextResource)); @@ -183,6 +189,10 @@ protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) context.addParameter("OldEncryptionKey", contextProperties.getOldEncryptionKey()); } + if (contextProperties.getLegacyContextPath() != null) + { + context.addParameter("legacyContextPath", contextProperties.getLegacyContextPath()); + } if (contextProperties.getRequiredModules() != null) { context.addParameter("requiredModules", contextProperties.getRequiredModules()); @@ -222,6 +232,18 @@ protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) configureJsonAccessLogging(tomcat, logConfig); } + WebappProperties additionalWebapps = additionalWebappSource(); + if (additionalWebapps.getContextPath().size() != additionalWebapps.getDocBase().size()) + { + throw new IllegalArgumentException("Additional webapps must have paired contextPath and docBase properties"); + } + for (int i = 0; i < additionalWebapps.getContextPath().size(); i++) + { + String contextPath = additionalWebapps.getContextPath().get(i); + String docBase = additionalWebapps.getDocBase().get(i); + tomcat.addWebapp(contextPath, docBase); + } + return super.getTomcatWebServer(tomcat); } @@ -579,6 +601,35 @@ public void setConditionUnless(String conditionUnless) } } + @Configuration + @ConfigurationProperties("webapps") + public static class WebappProperties + { + private List contextPath = new ArrayList<>(); + + private List docBase = new ArrayList<>(); + + public List getContextPath() + { + return contextPath; + } + + public void setContextPath(List contextPath) + { + this.contextPath = contextPath; + } + + public List getDocBase() + { + return docBase; + } + + public void setDocBase(List docBase) + { + this.docBase = docBase; + } + } + @Validated @Configuration @ConfigurationProperties("context") @@ -600,6 +651,10 @@ public static class ContextProperties @NotNull (message = "Must provide encryptionKey") private String encryptionKey; private String oldEncryptionKey; + private String legacyContextPath; + + // Default to deploying to the root context path + private String contextPath = ""; private String pipelineConfig; private String requiredModules; private boolean bypass2FA = false; @@ -702,6 +757,26 @@ public void setOldEncryptionKey(String oldEncryptionKey) this.oldEncryptionKey = oldEncryptionKey; } + public String getLegacyContextPath() + { + return legacyContextPath; + } + + public void setLegacyContextPath(String legacyContextPath) + { + this.legacyContextPath = legacyContextPath; + } + + public String getContextPath() + { + return contextPath; + } + + public void setContextPath(String contextPath) + { + this.contextPath = contextPath; + } + public String getPipelineConfig() { return pipelineConfig; From 80a5d9228780256c128f66b3e2bd6abc5cfbfd10 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Wed, 24 Jan 2024 10:23:29 -0800 Subject: [PATCH 2/3] Code review suggestions --- server/embedded/src/org/labkey/embedded/LabKeyServer.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/embedded/src/org/labkey/embedded/LabKeyServer.java b/server/embedded/src/org/labkey/embedded/LabKeyServer.java index f923697dfc..aea302efba 100644 --- a/server/embedded/src/org/labkey/embedded/LabKeyServer.java +++ b/server/embedded/src/org/labkey/embedded/LabKeyServer.java @@ -191,6 +191,10 @@ protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) if (contextProperties.getLegacyContextPath() != null) { + if (contextProperties.getContextPath() != null && !contextProperties.getContextPath().isEmpty() && !contextProperties.getContextPath().equals("/")) + { + throw new IllegalArgumentException("contextPath.legacyContextPath is only intended for use when deploying the LabKey application to the root context path. Please update application.properties"); + } context.addParameter("legacyContextPath", contextProperties.getLegacyContextPath()); } if (contextProperties.getRequiredModules() != null) From 56d664a964d67d05c3bf6c8eb9a3c6e433115f9d Mon Sep 17 00:00:00 2001 From: Josh Eckels Date: Wed, 24 Jan 2024 15:34:31 -0800 Subject: [PATCH 3/3] Update server/embedded/src/org/labkey/embedded/LabKeyServer.java Co-authored-by: Susan Hert --- server/embedded/src/org/labkey/embedded/LabKeyServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/embedded/src/org/labkey/embedded/LabKeyServer.java b/server/embedded/src/org/labkey/embedded/LabKeyServer.java index aea302efba..2bb88a088a 100644 --- a/server/embedded/src/org/labkey/embedded/LabKeyServer.java +++ b/server/embedded/src/org/labkey/embedded/LabKeyServer.java @@ -193,7 +193,7 @@ protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { if (contextProperties.getContextPath() != null && !contextProperties.getContextPath().isEmpty() && !contextProperties.getContextPath().equals("/")) { - throw new IllegalArgumentException("contextPath.legacyContextPath is only intended for use when deploying the LabKey application to the root context path. Please update application.properties"); + throw new IllegalArgumentException("contextPath.legacyContextPath is only intended for use when deploying the LabKey application to the root context path. Please update application.properties."); } context.addParameter("legacyContextPath", contextProperties.getLegacyContextPath()); }