This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.3 by this push:
new b9a2f194f0 Fix memory leak in HttpPostRequestDecoder (#14741)
b9a2f194f0 is described below
commit b9a2f194f044c07532715e212ab2e72155be9bad
Author: Sean Yang <[email protected]>
AuthorDate: Wed Oct 2 10:16:24 2024 +0800
Fix memory leak in HttpPostRequestDecoder (#14741)
---
.../java/org/apache/dubbo/remoting/http12/HttpUtils.java | 12 +++++++++++-
.../tri/h12/AbstractServerTransportListener.java | 16 +++++++++++++++-
.../tri/rest/support/basic/RestProtocolTest.groovy | 14 ++++++++++++++
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpUtils.java
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpUtils.java
index 22e16fb20f..488242d921 100644
---
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpUtils.java
+++
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpUtils.java
@@ -29,8 +29,11 @@ import java.util.List;
import java.util.Locale;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
+import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;
+import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
@@ -51,6 +54,7 @@ import
io.netty.handler.codec.http.multipart.InterfaceHttpData;
public final class HttpUtils {
+ public static final ByteBufAllocator HEAP_ALLOC = new
UnpooledByteBufAllocator(false, false);
public static final HttpDataFactory DATA_FACTORY = new
DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);
public static final String CHARSET_PREFIX = "charset=";
@@ -164,7 +168,13 @@ public final class HttpUtils {
if (canMark) {
inputStream.mark(Integer.MAX_VALUE);
}
- data = Unpooled.wrappedBuffer(StreamUtils.readBytes(inputStream));
+ if (inputStream.available() == 0) {
+ data = Unpooled.EMPTY_BUFFER;
+ } else {
+ data = HEAP_ALLOC.buffer();
+ ByteBufOutputStream os = new ByteBufOutputStream(data);
+ StreamUtils.copy(inputStream, os);
+ }
} catch (IOException e) {
throw new DecodeException("Error while reading post data: " +
e.getMessage(), e);
} finally {
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java
index 871b9aa46b..a6944a3510 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.common.logger.FluentLogger;
import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
import org.apache.dubbo.common.threadpool.serial.SerializingExecutor;
import org.apache.dubbo.common.utils.MethodUtils;
+import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.remoting.http12.HttpChannel;
import org.apache.dubbo.remoting.http12.HttpInputMessage;
import org.apache.dubbo.remoting.http12.HttpStatus;
@@ -278,14 +279,27 @@ public abstract class
AbstractServerTransportListener<HEADER extends RequestMeta
if (consumerAppName != null) {
inv.put(TripleHeaderEnum.CONSUMER_APP_NAME_KEY, consumerAppName);
}
+
// customizer RpcInvocation
- headerFilters.forEach(f -> f.invoke(invoker, inv));
+ HeaderFilter[] headerFilters =
+ UrlUtils.computeServiceAttribute(invoker.getUrl(),
HEADER_FILTERS_CACHE, this::loadHeaderFilters);
+ for (HeaderFilter headerFilter : headerFilters) {
+ headerFilter.invoke(invoker, inv);
+ }
initializeAltSvc(url);
return onBuildRpcInvocationCompletion(inv);
}
+ private HeaderFilter[] loadHeaderFilters(URL url) {
+ List<HeaderFilter> headerFilters = frameworkModel
+ .getExtensionLoader(HeaderFilter.class)
+ .getActivateExtension(url, CommonConstants.HEADER_FILTER_KEY);
+ LOGGER.info("Header filters for [{}] loaded: {}", url, headerFilters);
+ return headerFilters.toArray(new HeaderFilter[0]);
+ }
+
protected RpcInvocation onBuildRpcInvocationCompletion(RpcInvocation
invocation) {
String timeoutString =
httpMetadata.header(TripleHeaderEnum.SERVICE_TIMEOUT.getKey());
try {
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
b/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
index 4a2da172b9..430a646d01 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
+++
b/dubbo-rpc/dubbo-rpc-triple/src/test/groovy/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/RestProtocolTest.groovy
@@ -174,6 +174,20 @@ class RestProtocolTest extends BaseServiceTest {
'/argTest' | 'Sam is 8 years old'
}
+ def "urlEncodeForm body test"() {
+ given:
+ def request = new TestRequest(
+ path: path,
+ contentType: MediaType.APPLICATION_FROM_URLENCODED,
+ body: body
+ )
+ expect:
+ runner.post(request) == output
+ where:
+ path | body | output
+ '/argTest' | 'name=Sam&age=8' | 'Sam is 8 years old'
+ }
+
def "override mapping test"() {
expect:
runner.get(path) == output