Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/transports/core/nhttp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@
<artifactId>log4j-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</dependency>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.axis2.transport.http.*;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.MessageProcessorSelector;
import org.apache.commons.compress.compressors.brotli.BrotliCompressorInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.protocol.HTTP;
Expand All @@ -39,6 +40,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
Expand Down Expand Up @@ -102,7 +104,7 @@ public OMElement getDocument(MessageContext msgCtx, InputStream in) throws

String contentType = (String) msgCtx.getProperty(Constants.Configuration.CONTENT_TYPE);
String _contentType = getContentType(contentType, msgCtx);
in = HTTPTransportUtils.handleGZip(msgCtx, in);
in = handleContentEncoding(msgCtx, in);

AxisConfiguration configuration = msgCtx.getConfigurationContext().getAxisConfiguration();
Parameter useFallbackParameter =
Expand Down Expand Up @@ -306,4 +308,22 @@ public static String getContentType(String contentType, MessageContext msgContex
}
return type;
}

private static InputStream handleContentEncoding(MessageContext msgContext, InputStream in) throws IOException {
if (checkContentEncodingMatches(msgContext, "br")) {
PushbackInputStream pushbackInputStream = new PushbackInputStream(in);
int bytesRead = pushbackInputStream.read();
if (bytesRead != -1) {
pushbackInputStream.unread(bytesRead);
return new BrotliCompressorInputStream(pushbackInputStream);
}
}
return HTTPTransportUtils.handleGZip(msgContext, in);
}

private static boolean checkContentEncodingMatches(MessageContext msgContext, String encoding) {
Map headers = (Map)msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
return headers != null && (encoding.equals(headers.get(HTTPConstants.HEADER_CONTENT_ENCODING))
|| encoding.equals(headers.get(HTTPConstants.HEADER_CONTENT_ENCODING_LOWERCASE)));
}
Comment on lines +324 to +328

@coderabbitai coderabbitai Bot Jun 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Match the Content-Encoding value case-insensitively.

checkContentEncodingMatches compares the header value with encoding.equals(...), which is case-sensitive. HTTP content-coding tokens are case-insensitive, so values such as BR, Br, or GZIP would not match and the body would be passed through undecoded, leading to a build/parse failure downstream. Consider normalizing the header value (e.g., trim + equalsIgnoreCase) before comparison.

♻️ Proposed adjustment
     private static boolean checkContentEncodingMatches(MessageContext msgContext, String encoding) {
         Map headers = (Map)msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
-        return headers != null && (encoding.equals(headers.get(HTTPConstants.HEADER_CONTENT_ENCODING))
-                || encoding.equals(headers.get(HTTPConstants.HEADER_CONTENT_ENCODING_LOWERCASE)));
+        if (headers == null) {
+            return false;
+        }
+        Object value = headers.get(HTTPConstants.HEADER_CONTENT_ENCODING);
+        if (value == null) {
+            value = headers.get(HTTPConstants.HEADER_CONTENT_ENCODING_LOWERCASE);
+        }
+        return value instanceof String && encoding.equalsIgnoreCase(((String) value).trim());
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private static boolean checkContentEncodingMatches(MessageContext msgContext, String encoding) {
Map headers = (Map)msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
return headers != null && (encoding.equals(headers.get(HTTPConstants.HEADER_CONTENT_ENCODING))
|| encoding.equals(headers.get(HTTPConstants.HEADER_CONTENT_ENCODING_LOWERCASE)));
}
private static boolean checkContentEncodingMatches(MessageContext msgContext, String encoding) {
Map headers = (Map)msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
if (headers == null) {
return false;
}
Object value = headers.get(HTTPConstants.HEADER_CONTENT_ENCODING);
if (value == null) {
value = headers.get(HTTPConstants.HEADER_CONTENT_ENCODING_LOWERCASE);
}
return value instanceof String && encoding.equalsIgnoreCase(((String) value).trim());
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/util/DeferredMessageBuilder.java`
around lines 326 - 330, The checkContentEncodingMatches method performs
case-sensitive string comparisons on HTTP Content-Encoding header values, which
violates HTTP specifications where content-coding tokens are case-insensitive.
Modify the method to normalize both the encoding parameter and the header value
retrieved from headers.get(HTTPConstants.HEADER_CONTENT_ENCODING) and
headers.get(HTTPConstants.HEADER_CONTENT_ENCODING_LOWERCASE) to lowercase and
trim any whitespace before performing the equality comparisons, allowing values
like BR, Br, or GZIP to correctly match their lowercase equivalents.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a behavioural change and may break existing flows.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SanojPunchihewa — The concern is understandable, but this particular direction of change is strictly additive. equalsIgnoreCase is a superset of equals: every value that matches today (e.g., br, gzip) will continue to match after the change. The only new matches would be mixed-case variants (BR, GZIP, Br, etc.) that currently fall through undecoded. No currently working flow would be broken because no currently matching value would stop matching.

Per RFC 7231 §3.1.2.2, content-coding token comparisons are specified as case-insensitive, so the current case-sensitive behavior is technically a spec deviation rather than an intentional design choice. That said, if you'd prefer to keep the scope of this PR minimal and address case normalization separately, that's also a reasonable call.

}
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,11 @@
<artifactId>swagger-parser</artifactId>
<version>${swagger.parser.v3.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.orbit.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<reporting>
Expand Down Expand Up @@ -1676,6 +1681,7 @@
<org.wso2.orbit.atlassian.oai.version>2.44.1.wso2v1</org.wso2.orbit.atlassian.oai.version>
<swagger.parser.v3.version>2.1.37.wso2v1</swagger.parser.v3.version>
<jaxen.version>2.0.0</jaxen.version>
<commons-compress.orbit.version>1.28.0.wso2v2</commons-compress.orbit.version>
</properties>
<developers>
<!-- If you are a committer and your name is not listed here, please include/edit -->
Expand Down
Loading