Uploaded image for project: 'XWiki Platform'
  1. XWiki Platform
  2. XWIKI-25202

The page tabs (Comments, Attachments, Information) and other dynamically loaded content fail to load when XWiki is accessed over HTTP/2

    XMLWordPrintable

Details

    • Unknown

    Description

      Description

      When the browser talks HTTP/2 to the servlet container (directly, or through a proxy that forwards the backend's HTTP/2 headers), the AJAX requests that load the page tabs at the bottom of a page fail:

      • Firefox reports NS_ERROR_NET_HTTP2_SENT_GOAWAY. The GOAWAY closes the whole HTTP/2 connection, so other requests in flight at the same moment fail too (NS_BINDING_ABORTED, NS_ERROR_NET_PARTIAL_TRANSFER, e.g. on JavaScript files), which can break unrelated parts of the page.
      • Chrome reports net::ERR_HTTP2_PROTOCOL_ERROR.

      The Comments request is sent on every page view, so in Firefox every page view is affected, even for guests. Clicking the Attachments or Information tab leaves an empty pane. Other features that set this header through the same Velocity macro are very likely affected as well when they need two or more skin extensions (e.g. in-place editing of properties, CKEditor macro/image dialogs, required rights dialogs); only the page tabs were verified.

      Reported setup: XWiki 17.10.13 on Tomcat behind HAProxy, with HTTP/2 between Firefox and HAProxy. Reproduced on Tomcat 11.0.26 without any proxy, with Firefox 157 and Chrome 154.

      Cause

      These responses carry the X-XWIKI-HTML-HEAD header, which lists the skin extensions (CSS/JS) the client has to add to the page. Its value contains line breaks (one HTML tag per line). Line breaks are forbidden in HTTP/2 header values (RFC 9113, section 8.2.1), so browsers treat the response as malformed.

      Over HTTP/1.1 nobody notices: Tomcat replaces control characters in header values by spaces when writing HTTP/1.1 (and AJP) responses. Its HTTP/2 implementation sends them unchanged. Proxies only see a clean header if they talk HTTP/1.1 to Tomcat.

      Why this is a regression: since XWIKI-23634 (17.10.3, 18.0.0RC1), #getRequiredSkinExtensions in display_macros.vm joins the tags of all skin extension plugins with a newline. Before, the value only contained a line break when a single plugin (e.g. jsfx) had more than one tag, so e.g. the Comments tab (one CSS and one JS file) was not affected. Now every response with two or more skin extensions contains a line break.

      The same applies to the other producers of this header: DefaultRequiredSkinExtensionsRecorder (joins with a newline) and AsyncRendererResourceReferenceHandler (async rendering, the skin extensions' import strings end with a newline). The fix is to never put CR/LF in the header value: the client parses it as an HTML fragment, so a space works as separator.

      Steps to reproduce

      Requirements: XWiki Standard 17.10.3 or later (e.g. 17.10.13) installed on Tomcat 10.1 or 11 as usual, Firefox (or Chrome).

      1. Stop Tomcat.
      2. Create a self-signed certificate in Tomcat's conf directory (adapt CATALINA_HOME; keytool comes with the JDK):
        keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -validity 30 -dname CN=localhost \
          -storetype PKCS12 -keystore "$CATALINA_HOME/conf/localhost.p12" -storepass changeit -keypass changeit
        
      3. In $CATALINA_HOME/conf/server.xml, add an HTTPS connector with HTTP/2 next to the existing HTTP connector on port 8080 (the default server.xml contains a commented-out example of this "SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2"):
        <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   SSLEnabled="true" maxThreads="150">
          <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
          <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost.p12"
                         certificateKeystorePassword="changeit" type="RSA" />
          </SSLHostConfig>
        </Connector>
        
      4. Start Tomcat.
      5. In Firefox, open https://localhost:8443/xwiki/ and accept the certificate warning (Advanced > Accept the Risk and Continue). Log in.
      6. Open the developer tools (F12), Network tab. Right-click a column header and enable the "Protocol" column. Reload the page and check that the requests use HTTP/2.
      7. View any page, e.g. Sandbox.WebHome, scroll to the tabs at the bottom of the page and click the "Attachments" tab, then the "Information" tab.

      Expected: the tabs display the list of attachments and the page information, and all requests in the Network tab succeed.

      Actual: the tab panes stay empty (see attached screenshot). In the Network tab, the requests .../get/Sandbox/WebHome?xpage=xpart&vm=attachmentsinline.vm... and ...vm=informationinline.vm..., and the ...vm=commentsinline.vm... request sent when loading the page, fail with NS_ERROR_NET_HTTP2_SENT_GOAWAY. Other requests running at the same time may fail with NS_BINDING_ABORTED. In Chrome, the same requests fail with net::ERR_HTTP2_PROTOCOL_ERROR.

      Over http://localhost:8080/xwiki/ (HTTP/1.1) the same steps work. With curl, curl -vk --http2 'https://localhost:8443/xwiki/bin/get/Sandbox/WebHome?xpage=xpart&vm=attachmentsinline.vm' shows Ignoring received invalid HTTP header field ... name: [x-xwiki-html-head]: curl drops the header instead of failing, so use a browser to check the fix.

      Workaround

      Don't use HTTP/2 between Tomcat and the next hop. With a reverse proxy, talk HTTP/1.1 to Tomcat (e.g. for HAProxy, remove proto h2 or alpn h2 from the server line); the proxy can still use HTTP/2 towards the browser, since Tomcat then replaces the line breaks by spaces.

      Attachments

        1. attachments-tab-h2.png
          14 kB
          Michael Hamann
        2. attachments-tab-h2-fixed.png
          38 kB
          Michael Hamann

        Issue Links

          Activity

            People

              MichaelHamann Michael Hamann
              MichaelHamann Michael Hamann
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated: