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 6841aa6e99 NIFI-12047 Added HTTP/2 to Default Application Protocols
6841aa6e99 is described below

commit 6841aa6e99ab794a61164712e0936914b4e96f79
Author: exceptionfactory <exceptionfact...@apache.org>
AuthorDate: Mon Sep 11 16:57:13 2023 -0500

    NIFI-12047 Added HTTP/2 to Default Application Protocols
    
    - Changed default value of nifi.web.https.application.protocols to include 
both h2 and http/1.1
    - Changed default value of nifi.registry.web.https.application.protocols to 
include both h2 and http/1.1
    - Updated HostHeaderHandler logging
    
    Signed-off-by: Pierre Villard <pierre.villard...@gmail.com>
    
    This closes #7684.
---
 .../java/org/apache/nifi/util/NiFiProperties.java  |  4 +-
 .../nifi-framework/nifi-resources/pom.xml          |  2 +-
 .../apache/nifi/web/server/HostHeaderHandler.java  | 81 ++++++----------------
 .../connector/FrameworkServerConnectorFactory.java |  4 ++
 .../nifi/web/server/HostHeaderHandlerTest.java     | 22 ------
 .../FrameworkServerConnectorFactoryTest.java       |  5 +-
 nifi-registry/nifi-registry-assembly/pom.xml       |  2 +-
 .../properties/NiFiRegistryProperties.java         |  4 +-
 8 files changed, 32 insertions(+), 92 deletions(-)

diff --git 
a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
 
b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
index 92cfde96d1..9c4763b0b6 100644
--- 
a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
+++ 
b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
@@ -350,7 +350,7 @@ public class NiFiProperties extends ApplicationProperties {
     public static final String DEFAULT_AUTHORIZER_CONFIGURATION_FILE = 
"conf/authorizers.xml";
     public static final String 
DEFAULT_LOGIN_IDENTITY_PROVIDER_CONFIGURATION_FILE = 
"conf/login-identity-providers.xml";
     public static final Integer DEFAULT_REMOTE_INPUT_PORT = null;
-    private static final String DEFAULT_WEB_HTTPS_APPLICATION_PROTOCOLS = 
"http/1.1";
+    private static final String DEFAULT_WEB_HTTPS_APPLICATION_PROTOCOLS = "h2 
http/1.1";
     public static final int DEFAULT_WEB_THREADS = 200;
     public static final String DEFAULT_WEB_MAX_HEADER_SIZE = "16 KB";
     public static final String DEFAULT_WEB_WORKING_DIR = "./work/jetty";
@@ -725,7 +725,7 @@ public class NiFiProperties extends ApplicationProperties {
     }
 
     /**
-     * Get Web HTTPS Application Protocols defaults to HTTP/1.1
+     * Get Web HTTPS Application Protocols defaults to HTTP/2 and HTTP/1.1
      *
      * @return Set of configured HTTPS Application Protocols
      */
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
index 723f2eee4a..5c430f5aef 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
@@ -127,7 +127,7 @@
         <nifi.web.https.host>127.0.0.1</nifi.web.https.host>
         <nifi.web.https.port>8443</nifi.web.https.port>
         <nifi.web.https.network.interface.default />
-        
<nifi.web.https.application.protocols>http/1.1</nifi.web.https.application.protocols>
+        <nifi.web.https.application.protocols>h2 
http/1.1</nifi.web.https.application.protocols>
         <nifi.jetty.work.dir>./work/jetty</nifi.jetty.work.dir>
         <nifi.web.jetty.threads>200</nifi.web.jetty.threads>
         <nifi.web.max.header.size>16 KB</nifi.web.max.header.size>
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/HostHeaderHandler.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/HostHeaderHandler.java
index 5cc917ff52..62348bb53b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/HostHeaderHandler.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/HostHeaderHandler.java
@@ -47,52 +47,13 @@ public class HostHeaderHandler extends ScopedHandler {
     private final int serverPort;
     private final List<String> validHosts;
 
-    /**
-     * Instantiates a handler with a given server name and port 0.
-     *
-     * @param serverName the {@code serverName} to set on the request (the 
{@code serverPort} will not be set)
-     * @deprecated Use {@link #HostHeaderHandler(NiFiProperties)} which 
accepts a {@link NiFiProperties} object to allow for custom network interface 
binding.
-     */
-    public HostHeaderHandler(String serverName) {
-        this(serverName, 0);
-    }
-
-    /**
-     * Instantiates a handler with a given server name and port.
-     *
-     * @param serverName the {@code serverName} to set on the request
-     * @param serverPort the {@code serverPort} to set on the request
-     * @deprecated Use {@link #HostHeaderHandler(NiFiProperties)} which 
accepts a {@link NiFiProperties} object to allow for custom network interface 
binding.
-     */
-    public HostHeaderHandler(String serverName, int serverPort) {
-        this.serverName = Objects.requireNonNull(serverName);
-        this.serverPort = serverPort;
-
-        validHosts = generateDefaultHostnames(null);
-        validHosts.add(serverName.toLowerCase());
-        validHosts.add(serverName.toLowerCase() + ":" + serverPort);
-        // Sometimes the hostname is left empty but the port is always 
populated
-        validHosts.add("localhost");
-        validHosts.add("localhost:" + serverPort);
-        // Different from customizer -- empty is ok here
-        validHosts.add("");
-        try {
-            
validHosts.add(InetAddress.getLocalHost().getHostName().toLowerCase());
-            
validHosts.add(InetAddress.getLocalHost().getHostName().toLowerCase() + ":" + 
serverPort);
-        } catch (final Exception e) {
-            logger.warn("Failed to determine local hostname.", e);
-        }
-
-        logger.info("Created " + this.toString());
-    }
-
     /**
      * Instantiates a handler which accepts incoming requests with a host 
header that is empty or contains one of the
      * valid hosts. See the Apache NiFi Admin Guide for instructions on how to 
set valid hostnames and IP addresses.
      *
      * @param niFiProperties the NiFiProperties
      */
-    public HostHeaderHandler(NiFiProperties niFiProperties) {
+    public HostHeaderHandler(final NiFiProperties niFiProperties) {
         this.serverName = 
Objects.requireNonNull(determineServerHostname(niFiProperties));
         this.serverPort = determineServerPort(niFiProperties);
 
@@ -110,9 +71,7 @@ public class HostHeaderHandler extends ScopedHandler {
         hosts.add("");
 
         this.validHosts = uniqueList(hosts);
-        logger.info("Determined {} valid hostnames and IP addresses for 
incoming headers: {}", new Object[]{validHosts.size(), 
StringUtils.join(validHosts, ", ")});
-
-        logger.debug("Created " + this.toString());
+        logger.info("{} valid values for HTTP Request Host Header: {}", 
validHosts.size(), StringUtils.join(validHosts, ", "));
     }
 
     /**
@@ -145,7 +104,7 @@ public class HostHeaderHandler extends ScopedHandler {
 
         customHostnames.addAll(portlessHostnames);
         if (logger.isDebugEnabled()) {
-            logger.debug("Parsed {} custom hostnames from nifi.web.proxy.host: 
{}", new Object[]{customHostnames.size(), StringUtils.join(customHostnames, ", 
")});
+            logger.debug("Parsed {} custom hostnames from nifi.web.proxy.host: 
{}", customHostnames.size(), StringUtils.join(customHostnames, ", "));
         }
         return uniqueList(customHostnames);
     }
@@ -164,7 +123,6 @@ public class HostHeaderHandler extends ScopedHandler {
      * Returns true if the provided address is an IPv6 address (or could be 
interpreted as one). This method is more
      * lenient than {@link InetAddressUtils#isIPv6Address(String)} because of 
different interpretations of IPv4-mapped
      * IPv6 addresses.
-     *
      * See RFC 5952 Section 4 for more information on textual representation 
of the IPv6 addresses.
      *
      * @param address the address in text form
@@ -178,8 +136,6 @@ public class HostHeaderHandler extends ScopedHandler {
         // If the last two hextets are written in IPv4 form, treat it as an 
IPv6 address as well
         String everythingAfterLastColon = 
StringUtils.substringAfterLast(address, ":");
         boolean isIPv4 = 
InetAddressUtils.isIPv4Address(everythingAfterLastColon);
-        boolean isIPv4Mapped = 
InetAddressUtils.isIPv4MappedIPv64Address(everythingAfterLastColon);
-        boolean isCompressable = address.contains("0:0") && 
!address.contains("::");
 
         return isNormalIPv6 || isIPv4;
     }
@@ -197,14 +153,18 @@ public class HostHeaderHandler extends ScopedHandler {
     }
 
     @Override
-    public void doScope(String target, Request baseRequest, HttpServletRequest 
request, HttpServletResponse response)
-            throws IOException, ServletException {
-        logger.debug("HostHeaderHandler#doScope on " + 
request.getRequestURI());
+    public void doScope(String target, Request baseRequest, HttpServletRequest 
request, HttpServletResponse response) throws IOException, ServletException {
         nextScope(target, baseRequest, request, response);
     }
 
-    boolean hostHeaderIsValid(String hostHeader) {
-        return validHosts.contains(hostHeader.toLowerCase().trim());
+    /**
+     * Host Header Valid status checks against valid hosts
+     *
+     * @param hostHeader Host header value
+     * @return Valid status
+     */
+    boolean hostHeaderIsValid(final String hostHeader) {
+        return hostHeader != null && 
validHosts.contains(hostHeader.toLowerCase().trim());
     }
 
     @Override
@@ -222,21 +182,20 @@ public class HostHeaderHandler extends ScopedHandler {
      * @param response    the current response
      */
     @Override
-    public void doHandle(String target, Request baseRequest, 
HttpServletRequest request, HttpServletResponse response) throws IOException, 
ServletException {
+    public void doHandle(String target, Request baseRequest, 
HttpServletRequest request, HttpServletResponse response) throws IOException {
         final String hostHeader = request.getHeader("Host");
-        logger.debug("Received request [" + request.getRequestURI() + "] with 
host header: " + hostHeader);
+        final String requestUri = request.getRequestURI();
+        logger.debug("Request URI [{}] Host Header [{}]", requestUri, 
hostHeader);
+
         if (!hostHeaderIsValid(hostHeader)) {
-            logger.warn("Request host header [" + hostHeader + "] different 
from web hostname [" +
-                    serverName + "(:" + serverPort + ")]. Overriding to [" + 
serverName + ":" +
-                    serverPort + request.getRequestURI() + "]");
+            logger.warn("Request URI [{}] Host Header [{}] not valid", 
requestUri, hostHeader);
 
             response.setContentType("text/html; charset=utf-8");
             response.setStatus(HttpServletResponse.SC_OK);
 
-            PrintWriter out = response.getWriter();
+            final PrintWriter out = response.getWriter();
 
             out.println("<h1>System Error</h1>");
-            // TODO: Change to org.apache.commons.text.StringEscapeUtils
             out.println("<h2>The request contained an invalid host header 
[<code>" + StringEscapeUtils.escapeHtml4(hostHeader) +
                     "</code>] in the request [<code>" + 
StringEscapeUtils.escapeHtml4(request.getRequestURI()) +
                     "</code>]. Check for request manipulation or third-party 
intercept.</h2>");
@@ -308,7 +267,7 @@ public class HostHeaderHandler extends ScopedHandler {
         // Dedupe but maintain order
         final List<String> uniqueHosts = uniqueList(validHosts);
         if (logger.isDebugEnabled()) {
-            logger.debug("Determined {} valid default hostnames and IP 
addresses for incoming headers: {}", new Object[]{uniqueHosts.size(), 
StringUtils.join(uniqueHosts, ", ")});
+            logger.debug("Determined {} valid default hostnames and IP 
addresses for incoming headers: {}", uniqueHosts.size(), 
StringUtils.join(uniqueHosts, ", "));
         }
         return uniqueHosts;
     }
@@ -333,7 +292,7 @@ public class HostHeaderHandler extends ScopedHandler {
                 try {
                     NetworkInterface ni = 
NetworkInterface.getByName(networkInterfaceName);
                     List<String> ipAddresses = 
Collections.list(ni.getInetAddresses()).stream().map(inetAddress -> 
inetAddress.getHostAddress().toLowerCase()).collect(Collectors.toList());
-                    logger.debug("Resolved the following IP addresses for 
network interface {}: {}", new Object[]{networkInterfaceName, 
StringUtils.join(ipAddresses, ", ")});
+                    logger.debug("Resolved the following IP addresses for 
network interface {}: {}", networkInterfaceName, StringUtils.join(ipAddresses, 
", "));
                     allIPAddresses.addAll(ipAddresses);
                 } catch (SocketException e) {
                     logger.warn("Cannot resolve network interface named " + 
networkInterfaceName);
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
index 829a5578f6..78766780f1 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
@@ -28,6 +28,7 @@ import org.apache.nifi.security.util.TlsPlatform;
 import org.apache.nifi.util.FormatUtils;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.web.server.util.StoreScanner;
+import org.eclipse.jetty.server.HostHeaderCustomizer;
 import org.eclipse.jetty.server.HttpConfiguration;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
@@ -124,6 +125,9 @@ public class FrameworkServerConnectorFactory extends 
StandardServerConnectorFact
         httpConfiguration.setResponseHeaderSize(headerSize);
         httpConfiguration.setIdleTimeout(idleTimeout);
 
+        // Add HostHeaderCustomizer to set Host Header for HTTP/2 and 
HostHeaderHandler
+        httpConfiguration.addCustomizer(new HostHeaderCustomizer());
+
         return httpConfiguration;
     }
 
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/HostHeaderHandlerTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/HostHeaderHandlerTest.java
index 579ad4c2e3..417fd70135 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/HostHeaderHandlerTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/HostHeaderHandlerTest.java
@@ -49,14 +49,12 @@ public class HostHeaderHandlerTest {
             "FFFF:129.144.52.38",
             "::FFFF:129.144.52.38");
 
-    private static List<String> defaultHostsAndPorts150;
     private static List<String> defaultHostsAndPorts;
 
     @BeforeAll
     public static void setUpOnce() throws Exception {
         String actualHostname = 
InetAddress.getLocalHost().getHostName().toLowerCase();
         List<String> defaultHosts150 = Arrays.asList(DEFAULT_HOSTNAME, 
"localhost", actualHostname);
-        defaultHostsAndPorts150 = buildHostsWithPorts(defaultHosts150, 
DEFAULT_PORT);
         String actualIp = InetAddress.getLocalHost().getHostAddress();
         String loopbackIp = InetAddress.getLoopbackAddress().getHostAddress();
         List<String> defaultHosts = new ArrayList<>(defaultHosts150);
@@ -65,26 +63,6 @@ public class HostHeaderHandlerTest {
         defaultHostsAndPorts = buildHostsWithPorts(defaultHosts, DEFAULT_PORT);
     }
 
-    @SuppressWarnings("deprecation")
-    @Test
-    public void testConstructorShouldAcceptSingleValues() {
-        HostHeaderHandler handler = new HostHeaderHandler(DEFAULT_HOSTNAME, 
DEFAULT_PORT);
-
-        assertTrue(handler.hostHeaderIsValid(DEFAULT_HOSTNAME));
-        assertTrue(handler.hostHeaderIsValid(DEFAULT_HOSTNAME + ":" + 
DEFAULT_PORT));
-    }
-
-    /**
-     * The feature was introduced in Apache NiFi 1.5.0 but the behavior was 
changed following that release to include the actual IP address of the server, 
IPv6 ::1, and 127.0.0.1.
-     */
-    @SuppressWarnings("deprecation")
-    @Test
-    public void testShouldHandle_1_5_0_DefaultValues() {
-        HostHeaderHandler handler = new HostHeaderHandler(DEFAULT_HOSTNAME, 
DEFAULT_PORT);
-
-        defaultHostsAndPorts150.forEach(host -> 
assertTrue(handler.hostHeaderIsValid(host)));
-    }
-
     @Test
     public void testNewConstructorShouldHandleCurrentDefaultValues() {
         HostHeaderHandler handler = new 
HostHeaderHandler(getNifiProperties(null));
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java
index f4119f76aa..17e5858763 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java
@@ -36,7 +36,6 @@ import java.util.Properties;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -110,7 +109,7 @@ class FrameworkServerConnectorFactoryTest {
         assertHttpConnectionFactoryFound(serverConnector);
         final SslConnectionFactory sslConnectionFactory = 
assertSslConnectionFactoryFound(serverConnector);
 
-        final SslContextFactory.Server sslContextFactory = 
(SslContextFactory.Server) sslConnectionFactory.getSslContextFactory();
+        final SslContextFactory.Server sslContextFactory = 
sslConnectionFactory.getSslContextFactory();
         assertTrue(sslContextFactory.getNeedClientAuth());
         assertFalse(sslContextFactory.getWantClientAuth());
 
@@ -118,7 +117,7 @@ class FrameworkServerConnectorFactoryTest {
         assertAutoReloadEnabled(serverConnector);
 
         final HTTP2ServerConnectionFactory http2ServerConnectionFactory = 
serverConnector.getConnectionFactory(HTTP2ServerConnectionFactory.class);
-        assertNull(http2ServerConnectionFactory);
+        assertNotNull(http2ServerConnectionFactory);
     }
 
     @Test
diff --git a/nifi-registry/nifi-registry-assembly/pom.xml 
b/nifi-registry/nifi-registry-assembly/pom.xml
index f382f8db6b..dd3d009b8d 100644
--- a/nifi-registry/nifi-registry-assembly/pom.xml
+++ b/nifi-registry/nifi-registry-assembly/pom.xml
@@ -164,7 +164,7 @@
         <nifi.registry.web.https.host />
         <nifi.registry.web.https.port />
         <nifi.registry.web.https.network.interface.default />
-        
<nifi.registry.web.https.application.protocols>http/1.1</nifi.registry.web.https.application.protocols>
+        <nifi.registry.web.https.application.protocols>h2 
http/1.1</nifi.registry.web.https.application.protocols>
         
<nifi.registry.jetty.work.dir>./work/jetty</nifi.registry.jetty.work.dir>
         <nifi.registry.web.jetty.threads>200</nifi.registry.web.jetty.threads>
         
<nifi.registry.web.should.send.server.version>true</nifi.registry.web.should.send.server.version>
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
index d72acd058b..12df974c13 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
@@ -123,7 +123,7 @@ public class NiFiRegistryProperties extends 
ApplicationProperties {
 
     // Defaults
     public static final String DEFAULT_WEB_WORKING_DIR = "./work/jetty";
-    public static final String DEFAULT_WEB_HTTPS_APPLICATION_PROTOCOLS = 
"http/1.1";
+    public static final String DEFAULT_WEB_HTTPS_APPLICATION_PROTOCOLS = "h2 
http/1.1";
     public static final String DEFAULT_WAR_DIR = "./lib";
     public static final String DEFAULT_PROVIDERS_CONFIGURATION_FILE = 
"./conf/providers.xml";
     public static final String DEFAULT_REGISTRY_ALIAS_CONFIGURATION_FILE = 
"./conf/registry-aliases.xml";
@@ -235,7 +235,7 @@ public class NiFiRegistryProperties extends 
ApplicationProperties {
     }
 
     /**
-     * Get Web HTTPS Application Protocols defaults to HTTP/1.1
+     * Get Web HTTPS Application Protocols defaults to HTTP/2 and HTTP/1.1
      *
      * @return Set of configured HTTPS Application Protocols
      */

Reply via email to