This is an automated email from the ASF dual-hosted git repository.
pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 4d7c1b5a68 NIFI-14379 Fixed frontend HTTP redirect for paths without
trailing slash
4d7c1b5a68 is described below
commit 4d7c1b5a68d157112835bd5056b2c5e665aba8ae
Author: exceptionfactory <[email protected]>
AuthorDate: Tue Mar 18 20:19:08 2025 -0500
NIFI-14379 Fixed frontend HTTP redirect for paths without trailing slash
- Added Redirect Pattern Rule for frontend path without trailing slash
- Updated default Redirect Pattern Rule to use frontend path with trailing
slash
Signed-off-by: Pierre Villard <[email protected]>
This closes #9811.
---
.../nifi/web/server/StandardServerProvider.java | 17 ++++++++---
.../web/server/StandardServerProviderTest.java | 34 +++++++++++++++++++++-
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/StandardServerProvider.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/StandardServerProvider.java
index 492ea6071e..9d7d50fb66 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/StandardServerProvider.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/StandardServerProvider.java
@@ -51,6 +51,8 @@ class StandardServerProvider implements ServerProvider {
private static final String FRONTEND_CONTEXT_PATH = "/nifi";
+ private static final String FRONTEND_CONTEXT_PATH_DIRECTORY = "/nifi/";
+
private final SSLContext sslContext;
StandardServerProvider(final SSLContext sslContext) {
@@ -69,10 +71,7 @@ class StandardServerProvider implements ServerProvider {
final Handler standardHandler = getStandardHandler();
server.setHandler(standardHandler);
- final RewriteHandler defaultRewriteHandler = new RewriteHandler();
- final List<String> allowedContextPaths =
properties.getAllowedContextPathsAsList();
- final RedirectPatternRule redirectDefault = new
ContextPathRedirectPatternRule(ALL_PATHS_PATTERN, FRONTEND_CONTEXT_PATH,
allowedContextPaths);
- defaultRewriteHandler.addRule(redirectDefault);
+ final RewriteHandler defaultRewriteHandler =
getDefaultRewriteHandler(properties);
server.setDefaultHandler(defaultRewriteHandler);
final String requestLogFormat =
properties.getProperty(NiFiProperties.WEB_REQUEST_LOG_FORMAT);
@@ -83,6 +82,16 @@ class StandardServerProvider implements ServerProvider {
return server;
}
+ private RewriteHandler getDefaultRewriteHandler(final NiFiProperties
properties) {
+ final RewriteHandler defaultRewriteHandler = new RewriteHandler();
+ final List<String> allowedContextPaths =
properties.getAllowedContextPathsAsList();
+ final RedirectPatternRule redirectFrontend = new
ContextPathRedirectPatternRule(FRONTEND_CONTEXT_PATH,
FRONTEND_CONTEXT_PATH_DIRECTORY, allowedContextPaths);
+ defaultRewriteHandler.addRule(redirectFrontend);
+ final RedirectPatternRule redirectDefault = new
ContextPathRedirectPatternRule(ALL_PATHS_PATTERN,
FRONTEND_CONTEXT_PATH_DIRECTORY, allowedContextPaths);
+ defaultRewriteHandler.addRule(redirectDefault);
+ return defaultRewriteHandler;
+ }
+
private void addConnectors(final Server server, final NiFiProperties
properties, final SSLContext sslContext) {
final FrameworkServerConnectorFactory serverConnectorFactory = new
FrameworkServerConnectorFactory(server, properties);
if (properties.isHTTPSConfigured()) {
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
index f0d9b193cb..7087b15592 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
@@ -22,6 +22,7 @@ import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.server.handler.HeaderWriterHandler;
+import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.rewrite.handler.RewriteHandler;
import org.eclipse.jetty.server.Connector;
@@ -47,6 +48,7 @@ import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.util.List;
+import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@@ -84,6 +86,10 @@ class StandardServerProviderTest {
private static final String ALLOW_RESTRICTED_HEADERS_PROPERTY =
"jdk.httpclient.allowRestrictedHeaders";
+ private static final String FRONTEND_PATH = "/nifi";
+
+ private static final String FRONTEND_PATH_TRAILING_SLASH = "/nifi/";
+
private static SSLContext sslContext;
@BeforeAll
@@ -195,12 +201,37 @@ class StandardServerProviderTest {
) {
final URI localhostUri =
UriComponentsBuilder.fromUri(serverUri).host(LOCALHOST_NAME).build().toUri();
+ assertFrontendRedirectRequestsCompleted(httpClient, localhostUri);
assertRedirectRequestsCompleted(httpClient, localhostUri);
assertBadRequestsCompleted(httpClient, localhostUri);
assertMisdirectedRequestsCompleted(httpClient, localhostUri);
}
}
+ void assertFrontendRedirectRequestsCompleted(final HttpClient httpClient,
final URI localhostUri) throws IOException, InterruptedException {
+ final HttpRequest localhostRequest =
HttpRequest.newBuilder(localhostUri)
+ .version(HttpClient.Version.HTTP_2)
+ .build();
+ final HttpResponse<Void> localhostResponse =
assertResponseStatusCode(httpClient, localhostRequest,
HttpStatus.MOVED_TEMPORARILY_302);
+ final Optional<String> localhostLocationFound =
localhostResponse.headers().firstValue(HttpHeader.LOCATION.lowerCaseName());
+ assertTrue(localhostLocationFound.isPresent());
+
+ final String localhostLocation = localhostLocationFound.get();
+ assertEquals(FRONTEND_PATH_TRAILING_SLASH, localhostLocation);
+
+ final URI frontendPathUri =
UriComponentsBuilder.fromUri(localhostUri).path(FRONTEND_PATH).build().toUri();
+
+ final HttpRequest frontendPathRequest =
HttpRequest.newBuilder(frontendPathUri)
+ .version(HttpClient.Version.HTTP_2)
+ .build();
+ final HttpResponse<Void> frontendPathResponse =
assertResponseStatusCode(httpClient, frontendPathRequest,
HttpStatus.MOVED_TEMPORARILY_302);
+ final Optional<String> frontendPathLocationFound =
frontendPathResponse.headers().firstValue(HttpHeader.LOCATION.lowerCaseName());
+ assertTrue(frontendPathLocationFound.isPresent());
+
+ final String frontendPathLocation = frontendPathLocationFound.get();
+ assertEquals(FRONTEND_PATH_TRAILING_SLASH, frontendPathLocation);
+ }
+
void assertRedirectRequestsCompleted(final HttpClient httpClient, final
URI localhostUri) throws IOException, InterruptedException {
final HttpRequest localhostRequest =
HttpRequest.newBuilder(localhostUri)
.version(HttpClient.Version.HTTP_2)
@@ -236,9 +267,10 @@ class StandardServerProviderTest {
assertResponseStatusCode(httpClient, localhostPortRequest,
HttpStatus.MISDIRECTED_REQUEST_421);
}
- void assertResponseStatusCode(final HttpClient httpClient, final
HttpRequest request, final int statusCodeExpected) throws IOException,
InterruptedException {
+ HttpResponse<Void> assertResponseStatusCode(final HttpClient httpClient,
final HttpRequest request, final int statusCodeExpected) throws IOException,
InterruptedException {
final HttpResponse<Void> response = httpClient.send(request,
HttpResponse.BodyHandlers.discarding());
assertEquals(statusCodeExpected, response.statusCode());
+ return response;
}
void assertHttpConnectorFound(final Server server) {