diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java index 13e7ca781866..4d7ef8dec3c5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java @@ -154,6 +154,21 @@ protected URI getCookieResourceUri() { return buildResourceUri(uriBuilder.replacePath(ROOT_PATH).build()); } + /** + * Generate a URI to an external UI. + * + * @param paths paths for the external UI + * @return the full external UI + */ + protected String generateExternalUiUri(final String... paths) { + final RequestUriBuilder builder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest, properties.getAllowedContextPathsAsList()); + + final String path = String.join("/", paths); + builder.path(path); + + return builder.build().toString(); + } + private URI buildResourceUri(final String... path) { final UriBuilder uriBuilder = uriInfo.getBaseUriBuilder(); return buildResourceUri(uriBuilder.segment(path).build()); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java index 7af1482d4d89..79ac0548e951 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java @@ -156,7 +156,7 @@ public ControllerServiceDTO populateRemainingControllerServiceContent(final Cont final List uiExtensions = uiExtensionMapping.getUiExtension(controllerService.getType(), bundle.getGroup(), bundle.getArtifact(), bundle.getVersion()); for (final UiExtension uiExtension : uiExtensions) { if (UiExtensionType.ControllerServiceConfiguration.equals(uiExtension.getExtensionType())) { - controllerService.setCustomUiUrl(uiExtension.getContextPath() + "/configure"); + controllerService.setCustomUiUrl(generateExternalUiUri(uiExtension.getContextPath(), "configure")); } } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java index 17bd5a47af24..37892bfb90d4 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java @@ -217,7 +217,7 @@ public ParameterProviderDTO populateRemainingParameterProviderContent(final Para final List uiExtensions = uiExtensionMapping.getUiExtension(parameterProvider.getType(), bundle.getGroup(), bundle.getArtifact(), bundle.getVersion()); for (final UiExtension uiExtension : uiExtensions) { if (UiExtensionType.ParameterProviderConfiguration.equals(uiExtension.getExtensionType())) { - parameterProvider.setCustomUiUrl(uiExtension.getContextPath() + "/configure"); + parameterProvider.setCustomUiUrl(generateExternalUiUri(uiExtension.getContextPath(), "configure")); } } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java index f29e303897ff..f70bd98b80bc 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java @@ -165,21 +165,15 @@ public ProcessorDTO populateRemainingProcessorContent(ProcessorDTO processor) { // get the config details and see if there is a custom ui for this processor type ProcessorConfigDTO config = processor.getConfig(); if (config != null) { - // consider legacy custom ui fist - String customUiUrl = servletContext.getInitParameter(processor.getType()); - if (StringUtils.isNotBlank(customUiUrl)) { - config.setCustomUiUrl(customUiUrl); - } else { - final BundleDTO bundle = processor.getBundle(); - - // see if this processor has any ui extensions - final UiExtensionMapping uiExtensionMapping = (UiExtensionMapping) servletContext.getAttribute("nifi-ui-extensions"); - if (uiExtensionMapping.hasUiExtension(processor.getType(), bundle.getGroup(), bundle.getArtifact(), bundle.getVersion())) { - final List uiExtensions = uiExtensionMapping.getUiExtension(processor.getType(), bundle.getGroup(), bundle.getArtifact(), bundle.getVersion()); - for (final UiExtension uiExtension : uiExtensions) { - if (UiExtensionType.ProcessorConfiguration.equals(uiExtension.getExtensionType())) { - config.setCustomUiUrl(uiExtension.getContextPath() + "/configure"); - } + final BundleDTO bundle = processor.getBundle(); + + // see if this processor has any ui extensions + final UiExtensionMapping uiExtensionMapping = (UiExtensionMapping) servletContext.getAttribute("nifi-ui-extensions"); + if (uiExtensionMapping.hasUiExtension(processor.getType(), bundle.getGroup(), bundle.getArtifact(), bundle.getVersion())) { + final List uiExtensions = uiExtensionMapping.getUiExtension(processor.getType(), bundle.getGroup(), bundle.getArtifact(), bundle.getVersion()); + for (final UiExtension uiExtension : uiExtensions) { + if (UiExtensionType.ProcessorConfiguration.equals(uiExtension.getExtensionType())) { + config.setCustomUiUrl(generateExternalUiUri(uiExtension.getContextPath(), "configure")); } } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java index d85609c4b889..bf900575b5a6 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java @@ -149,7 +149,7 @@ public ReportingTaskDTO populateRemainingReportingTaskContent(final ReportingTas final List uiExtensions = uiExtensionMapping.getUiExtension(reportingTask.getType(), bundle.getGroup(), bundle.getArtifact(), bundle.getVersion()); for (final UiExtension uiExtension : uiExtensions) { if (UiExtensionType.ReportingTaskConfiguration.equals(uiExtension.getExtensionType())) { - reportingTask.setCustomUiUrl(uiExtension.getContextPath() + "/configure"); + reportingTask.setCustomUiUrl(generateExternalUiUri(uiExtension.getContextPath(), "configure")); } } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestApplicationResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestApplicationResource.java index 036bade8b1bb..23cb92b2fd29 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestApplicationResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestApplicationResource.java @@ -38,16 +38,21 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class TestApplicationResource { private static final String PROXY_CONTEXT_PATH_PROP = NiFiProperties.WEB_PROXY_CONTEXT_PATH; - private static final String BASE_URI = "https://nifi.apache.org"; + private static final String SCHEME = "https"; + private static final String HOST = "nifi.apache.org"; + private static final int PORT = 8081; + private static final String BASE_URI = SCHEME + "://" + HOST; private static final String ALLOWED_PATH = "/some/context/path"; private static final String FORWARD_SLASH = "/"; + private static final String CUSTOM_UI_PATH = "/my-custom-ui-1.0.0"; private static final String ACTUAL_RESOURCE = "actualResource"; - private static final String EXPECTED_URI = BASE_URI + ":8081" + ALLOWED_PATH + FORWARD_SLASH + ACTUAL_RESOURCE; + private static final String EXPECTED_URI = BASE_URI + ":" + PORT + ALLOWED_PATH + FORWARD_SLASH + ACTUAL_RESOURCE; private static final String MULTIPLE_ALLOWED_PATHS = String.join(",", ALLOWED_PATH, "another/path", "a/third/path"); @Mock @@ -57,8 +62,12 @@ public class TestApplicationResource { @BeforeEach public void setUp(@Mock UriInfo uriInfo) throws Exception { - when(uriInfo.getBaseUriBuilder()).thenReturn(new JerseyUriBuilder().uri(new URI(BASE_URI + FORWARD_SLASH))); - when(request.getScheme()).thenReturn("https"); + // this stubbing is lenient because it is unnecessary in some tests + lenient().when(uriInfo.getBaseUriBuilder()).thenReturn(new JerseyUriBuilder().uri(new URI(BASE_URI + FORWARD_SLASH))); + + when(request.getScheme()).thenReturn(SCHEME); + when(request.getServerName()).thenReturn(HOST); + when(request.getServerPort()).thenReturn(PORT); resource = new MockApplicationResource(); resource.setHttpServletRequest(request); @@ -132,6 +141,19 @@ public void testGenerateUriShouldAllowForwardedPrefixHeaderIfElementInMultipleAl assertEquals(EXPECTED_URI, resource.generateResourceUri(ACTUAL_RESOURCE)); } + @Test + public void testGenerateExternalUiUri() { + assertEquals(SCHEME + "://" + HOST + ":" + PORT + CUSTOM_UI_PATH, resource.generateExternalUiUri(CUSTOM_UI_PATH)); + } + + @Test + public void testGenerateExternalUiUriWithProxy() { + when(request.getHeader(anyString())).thenAnswer(new RequestAnswer(ProxyHeader.FORWARDED_CONTEXT.getHeader())); + setNiFiProperties(Collections.singletonMap(PROXY_CONTEXT_PATH_PROP, ALLOWED_PATH)); + + assertEquals(SCHEME + "://" + HOST + ":" + PORT + ALLOWED_PATH + CUSTOM_UI_PATH, resource.generateExternalUiUri(CUSTOM_UI_PATH)); + } + private void setNiFiProperties(Map props) { resource.properties = new NiFiProperties(props); }