Search code examples
google-chromehttp-headersspring-integration

Spring Integration fails at "Priority" HTTP header validation for HTTP/2


With the recent rollout of Chromium 124 to Chrome, a new "Priority" HTTP header has been introduced in the request header that supports the HTTP/2 and HTTP/3 protocols by default. More info about the new header can be found in the following link:

https://developer.chrome.com/release-notes/124#priority_http_request_header

However, the Spring Integration library hasn't seem to catch up with this change and is still expecting the Priority header in NUMBER format, whereas the actual header value is in such format as "u=5, i". More info on the format definition here:

https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-priority#name-the-priority-http-header-fi

This header validation is happening in IntegrationMessageHeaderAccessor in the spring-integration-core artifact:

https://github.com/spring-projects/spring-integration/blob/6.2.x/spring-integration-core/src/main/java/org/springframework/integration/IntegrationMessageHeaderAccessor.java

Here is the extract of the method where the validation is taking place, with the Priority validation logic in bold:

@Override
protected void verifyType(String headerName, Object headerValue) {
    if (headerName != null && headerValue != null) {
        super.verifyType(headerName, headerValue);
        if (IntegrationMessageHeaderAccessor.EXPIRATION_DATE.equals(headerName)) {
            Assert.isTrue(headerValue instanceof Date || headerValue instanceof Long,
                TYPE_VERIFY_MESSAGE_FUNCTION.apply(headerName, "' header value must be a Date or Long."));
        }
        else if (IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER.equals(headerName)
        || IntegrationMessageHeaderAccessor.SEQUENCE_SIZE.equals(headerName)
        || IntegrationMessageHeaderAccessor.PRIORITY.equals(headerName)) {
           Assert.isTrue( Number.class.isAssignableFrom(headerValue.getClass()), 
               TYPE_VERIFY_MESSAGE_FUNCTION.apply(headerName, "' header value must be a Number."));
        }
        else if (IntegrationMessageHeaderAccessor.ROUTING_SLIP.equals(headerName)) {        
            Assert.isTrue( Map.class.isAssignableFrom(headerValue.getClass()),
                TYPE_VERIFY_MESSAGE_FUNCTION.apply(headerName, "' header value must be a Map."));
        }
        else if (IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE.equals(headerName)) {
            Assert.isTrue( Boolean.class.isAssignableFrom(headerValue.getClass()),
                TYPE_VERIFY_MESSAGE_FUNCTION.apply(headerName, "' header value must be an Boolean."));
        }
    }
}

Is anyone aware of any patch to the Spring Integration code base with regard to this change? Please advise.

Thanks!

As a workaround currently, we intercepted the request and filter out the header before it reaches the validation point and that resolves the issue. But it feels more appropriate that this should be fixed in the Spring library level since the browser change is already official.


Solution

  • The priority in Spring Integration has nothing to do with that HTTP header. This priority in Spring Integration is about message handling internally or mapping to respective property of the target messaging system.

    It is just unfortunate that HTTP header was named same way, but comes with string value instead.

    It is not clear how you receive HTTP requests, but we definitely can look into DefaultHttpHeaderMapper to add some logic to map this HTTP Priority header into something like http_priority and back to avoid conflict with messaging priority header.

    Otherwise you are on your own and have to do that mapping (or filtering) manually. In other words that messaging priority header won't be fix to satisfy this new HTTP feature since priority in messaging was always a number.