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 611de81d97 Rest bugfix (#14599)
611de81d97 is described below
commit 611de81d97132a30bbe5498462222493a8994c31
Author: Sean Yang <[email protected]>
AuthorDate: Wed Aug 28 15:26:03 2024 +0800
Rest bugfix (#14599)
---
.../src/main/resources/application.yml | 2 +-
.../protocol/tri/servlet/ServletStreamChannel.java | 24 +++++++++---
.../rpc/protocol/tri/servlet/TripleFilter.java | 45 ++++++++++++++++++++--
.../http12/h1/Http1ServerUnaryChannelObserver.java | 11 +++++-
.../apache/dubbo/remoting/http12/rest/Mapping.java | 44 +++++++++++++++++++++
.../apache/dubbo/remoting/http12/rest/Param.java | 30 ++++++++++++++-
.../GrpcHttp2ServerTransportListenerFactory.java | 3 +-
.../tri/h12/grpc/GrpcRequestHandlerMapping.java | 4 +-
.../dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java | 5 +++
.../h12/http2/Http2ServerUnaryChannelObserver.java | 11 +++++-
.../rpc/protocol/tri/h3/negotiation/Helper.java | 3 +-
.../support/basic/FallbackArgumentResolver.java | 6 ++-
.../rpc/protocol/tri/rest/util/RequestUtils.java | 4 +-
.../tri/rest/support/basic/RestProtocolTest.groovy | 12 ++++++
.../rpc/protocol/tri/test/MockH2StreamChannel.java | 6 ++-
.../DubboTriple3AutoConfiguration.java | 2 +-
.../DubboTripleAutoConfiguration.java | 2 +-
17 files changed, 188 insertions(+), 26 deletions(-)
diff --git
a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml
b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml
index e03758b7cc..f9628d8341 100644
---
a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml
+++
b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml
@@ -27,7 +27,7 @@ dubbo:
port: ${server.port}
triple:
servlet:
- enable: true
+ enabled: true
registry:
id: zk-registry
address: zookeeper://127.0.0.1:2181
diff --git
a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java
b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java
index 72168f3b3d..d45fb4a0f4 100644
---
a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java
+++
b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java
@@ -18,11 +18,11 @@ package org.apache.dubbo.rpc.protocol.tri.servlet;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.remoting.http12.HttpHeaderNames;
import org.apache.dubbo.remoting.http12.HttpHeaders;
import org.apache.dubbo.remoting.http12.HttpMetadata;
import org.apache.dubbo.remoting.http12.HttpOutputMessage;
-import org.apache.dubbo.remoting.http12.HttpVersion;
import org.apache.dubbo.remoting.http12.exception.HttpStatusException;
import org.apache.dubbo.remoting.http12.h2.H2StreamChannel;
import org.apache.dubbo.remoting.http12.h2.Http2Header;
@@ -130,7 +130,12 @@ final class ServletStreamChannel implements
H2StreamChannel {
@Override
public CompletableFuture<Void> writeHeader(HttpMetadata httpMetadata) {
- boolean endStream = ((Http2Header) httpMetadata).isEndStream();
+ boolean endStream = false;
+ boolean isHttp1 = true;
+ if (httpMetadata instanceof Http2Header) {
+ endStream = ((Http2Header) httpMetadata).isEndStream();
+ isHttp1 = false;
+ }
try {
HttpHeaders headers = httpMetadata.headers();
if (endStream) {
@@ -155,6 +160,11 @@ final class ServletStreamChannel implements
H2StreamChannel {
response.setStatus(Integer.parseInt(values.get(0)));
continue;
}
+ if (isHttp1
+ &&
HttpHeaderNames.TRANSFER_ENCODING.getName().equals(key)
+ && "chunked".equals(CollectionUtils.first(values))) {
+ continue;
+ }
if (values.size() == 1) {
response.setHeader(key, values.get(0));
} else {
@@ -175,13 +185,15 @@ final class ServletStreamChannel implements
H2StreamChannel {
@Override
public CompletableFuture<Void> writeMessage(HttpOutputMessage
httpOutputMessage) {
- boolean endStream = ((Http2OutputMessage)
httpOutputMessage).isEndStream();
+ boolean endStream = false;
+ if (httpOutputMessage instanceof Http2OutputMessage) {
+ endStream = ((Http2OutputMessage) httpOutputMessage).isEndStream();
+ } else if (httpOutputMessage == HttpOutputMessage.EMPTY_MESSAGE) {
+ endStream = true;
+ }
try {
ByteArrayOutputStream bos = (ByteArrayOutputStream)
httpOutputMessage.getBody();
ServletOutputStream out = response.getOutputStream();
- if
(!HttpVersion.HTTP2.getProtocol().equals(request.getProtocol())) {
- response.setContentLength(bos.size());
- }
bos.writeTo(out);
out.flush();
} catch (Throwable t) {
diff --git
a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java
b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java
index c95f177b57..c7d456b2fb 100644
---
a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java
+++
b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java
@@ -19,6 +19,9 @@ package org.apache.dubbo.rpc.protocol.tri.servlet;
import org.apache.dubbo.common.io.StreamUtils;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.remoting.http12.HttpVersion;
+import org.apache.dubbo.remoting.http12.h1.Http1InputMessage;
+import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListener;
import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame;
import org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory;
import org.apache.dubbo.remoting.http12.h2.Http2TransportListener;
@@ -31,6 +34,7 @@ import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum;
import org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcHeaderNames;
import
org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcHttp2ServerTransportListener;
import org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcUtils;
+import
org.apache.dubbo.rpc.protocol.tri.h12.http1.DefaultHttp11ServerTransportListenerFactory;
import
org.apache.dubbo.rpc.protocol.tri.h12.http2.GenericHttp2ServerTransportListenerFactory;
import
org.apache.dubbo.rpc.protocol.tri.rest.mapping.DefaultRequestMappingRegistry;
import org.apache.dubbo.rpc.protocol.tri.rest.mapping.RequestMappingRegistry;
@@ -75,11 +79,23 @@ public class TripleFilter implements Filter {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
- if (!hasGrpcMapping(request) &&
!mappingRegistry.exists(request.getRequestURI(), request.getMethod())) {
- chain.doFilter(request, response);
- return;
+ boolean isHttp2 =
HttpVersion.HTTP2.getProtocol().equals(request.getProtocol());
+ if (isHttp2) {
+ if (hasGrpcMapping(request) ||
mappingRegistry.exists(request.getRequestURI(), request.getMethod())) {
+ handleHttp2(request, response);
+ return;
+ }
+ } else {
+ if (mappingRegistry.exists(request.getRequestURI(),
request.getMethod())) {
+ handleHttp1(request, response);
+ return;
+ }
}
+ chain.doFilter(request, response);
+ }
+
+ private void handleHttp2(HttpServletRequest request, HttpServletResponse
response) {
AsyncContext context = request.startAsync(request, response);
ServletStreamChannel channel = new ServletStreamChannel(request,
response, context);
try {
@@ -101,14 +117,37 @@ public class TripleFilter implements Filter {
}
}
+ private void handleHttp1(HttpServletRequest request, HttpServletResponse
response) {
+ AsyncContext context = request.startAsync(request, response);
+ ServletStreamChannel channel = new ServletStreamChannel(request,
response, context);
+ try {
+ Http1ServerTransportListener listener =
DefaultHttp11ServerTransportListenerFactory.INSTANCE.newInstance(
+ channel, ServletExchanger.getUrl(),
FrameworkModel.defaultModel());
+ channel.setGrpc(false);
+ context.setTimeout(resolveTimeout(request, false));
+ listener.onMetadata(new HttpMetadataAdapter(request));
+ ServletInputStream is = request.getInputStream();
+ listener.onData(new Http1InputMessage(
+ is.available() == 0 ? StreamUtils.EMPTY : new
ByteArrayInputStream(StreamUtils.readBytes(is))));
+ } catch (Throwable t) {
+ LOGGER.info("Failed to process request", t);
+ channel.writeError(Code.UNKNOWN.code, t);
+ }
+ }
+
@Override
public void destroy() {}
private boolean hasGrpcMapping(HttpServletRequest request) {
+ if (!GrpcUtils.isGrpcRequest(request.getContentType())) {
+ return false;
+ }
+
RequestPath path = RequestPath.parse(request.getRequestURI());
if (path == null) {
return false;
}
+
String group =
request.getHeader(TripleHeaderEnum.SERVICE_GROUP.getHeader());
String version =
request.getHeader(TripleHeaderEnum.SERVICE_VERSION.getHeader());
return pathResolver.resolve(path.getPath(), group, version) != null;
diff --git
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerUnaryChannelObserver.java
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerUnaryChannelObserver.java
index 8cb2a36edd..32c93c13aa 100644
---
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerUnaryChannelObserver.java
+++
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerUnaryChannelObserver.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.remoting.http12.h1;
+import org.apache.dubbo.common.logger.FluentLogger;
import org.apache.dubbo.remoting.http12.HttpChannel;
import org.apache.dubbo.remoting.http12.HttpHeaderNames;
import org.apache.dubbo.remoting.http12.HttpMetadata;
@@ -27,6 +28,8 @@ import io.netty.buffer.ByteBufOutputStream;
public class Http1ServerUnaryChannelObserver extends
Http1ServerChannelObserver {
+ private static final FluentLogger LOGGER =
FluentLogger.of(Http1ServerUnaryChannelObserver.class);
+
public Http1ServerUnaryChannelObserver(HttpChannel httpChannel) {
super(httpChannel);
}
@@ -42,7 +45,13 @@ public class Http1ServerUnaryChannelObserver extends
Http1ServerChannelObserver
protected void doOnError(Throwable throwable) throws Throwable {
String statusCode = resolveStatusCode(throwable);
Object data = buildErrorResponse(statusCode, throwable);
- HttpOutputMessage httpOutputMessage = buildMessage(data);
+ HttpOutputMessage httpOutputMessage;
+ try {
+ httpOutputMessage = buildMessage(data);
+ } catch (Throwable t) {
+ LOGGER.internalError("Failed to build message", t);
+ httpOutputMessage = encodeHttpOutputMessage(data);
+ }
sendHeader(buildMetadata(statusCode, data, httpOutputMessage));
sendMessage(httpOutputMessage);
}
diff --git
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Mapping.java
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Mapping.java
index 3832333142..f42e11768f 100644
---
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Mapping.java
+++
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Mapping.java
@@ -24,24 +24,68 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * Annotation for mapping Dubbo services to Rest endpoints.
+ *
+ * <p>
+ * Example usage:
+ * <pre>
+ * @Mapping(value = "/example", method = HttpMethods.GET, produces =
"application/json")
+ * String handleExample();
+ * </pre>
+ * @see <a
href="https://dubbo-next.staged.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/protocol/tripe-rest-manual/#Q6XyG">Tripe
Rest Manual</a>
+ */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Mapping {
+ /**
+ * Alias for {@link #path()}.
+ * The path patterns to be mapped.
+ * If not specified, the method or class name is used as the default.
+ */
String[] value() default {};
+ /**
+ * Specifies the path patterns to be mapped.
+ * If not specified, the method or class name is used as the default.
+ */
String[] path() default {};
+ /**
+ * Defines the HTTP methods supported by the mapped handler.
+ * Supports values like GET, POST, etc.
+ */
HttpMethods[] method() default {};
+ /**
+ * Specifies the request parameters that must be present for this mapping
to be invoked.
+ * Example: "param1=value1", "param2".
+ */
String[] params() default {};
+ /**
+ * Specifies the request headers that must be present for this mapping to
be invoked.
+ * Example: "content-type=application/json".
+ */
String[] headers() default {};
+ /**
+ * Specifies the media types that the mapped handler consumes.
+ * Example: "application/json", "text/plain".
+ */
String[] consumes() default {};
+ /**
+ * Specifies the media types that the mapped handler produces.
+ * Example: "application/json", "text/html".
+ */
String[] produces() default {};
+ /**
+ * Indicates whether the mapping is enabled.
+ * Defaults to {@code true}. If set to {@code false}, the mapping will be
ignored.
+ */
boolean enabled() default true;
}
diff --git
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Param.java
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Param.java
index 2ff94d4d32..108dfd44db 100644
---
a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Param.java
+++
b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/rest/Param.java
@@ -22,6 +22,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * Annotation for defining parameters on Dubbo service method parameters.
+ * Provides metadata such as parameter type, default value, and whether the
parameter is required.
+ *
+ * <p>Example usage:</p>
+ * <pre>
+ * @Param(value = "x-version", type = ParamType.Header, required = false)
String version
+ * </pre>
+ * @see <a
href="https://dubbo-next.staged.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/protocol/tripe-rest-manual/#kmCzf">Tripe
Rest Manual</a>
+ */
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@@ -29,11 +39,27 @@ public @interface Param {
String DEFAULT_NONE = "\n\t\t\n\t\t\n_DEFAULT_NONE_\n\t\t\t\t\n";
- ParamType type() default ParamType.Param;
-
+ /**
+ * The name of the parameter.
+ * If not specified, the parameter name is derived from the method
signature or field name.
+ */
String value() default "";
+ /**
+ * The type of the parameter, such as query, header, or path variable.
+ * Defaults to {@link ParamType#Param}.
+ */
+ ParamType type() default ParamType.Param;
+
+ /**
+ * Indicates whether the parameter is required.
+ * Defaults to {@code true}. If set to {@code false}, the parameter is
optional.
+ */
boolean required() default true;
+ /**
+ * Specifies a default value for the parameter.
+ * Defaults to {@link #DEFAULT_NONE}, indicating that there is no default
value.
+ */
String defaultValue() default DEFAULT_NONE;
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java
index a80131dc9e..c488204e90 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java
@@ -21,7 +21,6 @@ import org.apache.dubbo.remoting.http12.h2.H2StreamChannel;
import org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory;
import org.apache.dubbo.remoting.http12.h2.Http2TransportListener;
import org.apache.dubbo.rpc.model.FrameworkModel;
-import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum;
public class GrpcHttp2ServerTransportListenerFactory implements
Http2ServerTransportListenerFactory {
@@ -32,6 +31,6 @@ public class GrpcHttp2ServerTransportListenerFactory
implements Http2ServerTrans
@Override
public boolean supportContentType(String contentType) {
- return contentType != null &&
contentType.startsWith(TripleHeaderEnum.APPLICATION_GRPC.getHeader());
+ return GrpcUtils.isGrpcRequest(contentType);
}
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcRequestHandlerMapping.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcRequestHandlerMapping.java
index b5467f2d50..6038a3b839 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcRequestHandlerMapping.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcRequestHandlerMapping.java
@@ -23,7 +23,6 @@ import org.apache.dubbo.remoting.http12.HttpResponse;
import org.apache.dubbo.remoting.http12.HttpStatus;
import org.apache.dubbo.remoting.http12.exception.HttpStatusException;
import org.apache.dubbo.remoting.http12.message.HttpMessageCodec;
-import org.apache.dubbo.remoting.http12.message.MediaType;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.PathResolver;
import org.apache.dubbo.rpc.model.FrameworkModel;
@@ -49,8 +48,7 @@ public final class GrpcRequestHandlerMapping implements
RequestHandlerMapping {
@Override
public RequestHandler getRequestHandler(URL url, HttpRequest request,
HttpResponse response) {
- String contentType = request.contentType();
- if (contentType == null ||
!contentType.startsWith(MediaType.APPLICATION_GRPC.getName())) {
+ if (!GrpcUtils.isGrpcRequest(request.contentType())) {
return null;
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java
index 889b387071..a6ba31f462 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.rpc.protocol.tri.h12.grpc;
import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum;
import java.util.concurrent.TimeUnit;
@@ -48,4 +49,8 @@ public class GrpcUtils {
return null;
}
}
+
+ public static boolean isGrpcRequest(String contentType) {
+ return contentType != null &&
contentType.startsWith(TripleHeaderEnum.APPLICATION_GRPC.getHeader());
+ }
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerUnaryChannelObserver.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerUnaryChannelObserver.java
index 14df1bbb4e..f37974c23e 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerUnaryChannelObserver.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerUnaryChannelObserver.java
@@ -16,12 +16,15 @@
*/
package org.apache.dubbo.rpc.protocol.tri.h12.http2;
+import org.apache.dubbo.common.logger.FluentLogger;
import org.apache.dubbo.remoting.http12.HttpOutputMessage;
import org.apache.dubbo.remoting.http12.h2.H2StreamChannel;
import org.apache.dubbo.rpc.model.FrameworkModel;
public class Http2ServerUnaryChannelObserver extends
Http2ServerCallToObserverAdapter {
+ private static final FluentLogger LOGGER =
FluentLogger.of(Http2ServerUnaryChannelObserver.class);
+
public Http2ServerUnaryChannelObserver(FrameworkModel frameworkModel,
H2StreamChannel h2StreamChannel) {
super(frameworkModel, h2StreamChannel);
}
@@ -37,7 +40,13 @@ public class Http2ServerUnaryChannelObserver extends
Http2ServerCallToObserverAd
protected void doOnError(Throwable throwable) throws Throwable {
String statusCode = resolveStatusCode(throwable);
Object data = buildErrorResponse(statusCode, throwable);
- HttpOutputMessage httpOutputMessage = buildMessage(data);
+ HttpOutputMessage httpOutputMessage;
+ try {
+ httpOutputMessage = buildMessage(data);
+ } catch (Throwable t) {
+ LOGGER.internalError("Failed to build message", t);
+ httpOutputMessage = encodeHttpOutputMessage(data);
+ }
sendHeader(buildMetadata(statusCode, data, httpOutputMessage));
sendMessage(httpOutputMessage);
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h3/negotiation/Helper.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h3/negotiation/Helper.java
index 0cc705272c..f981048943 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h3/negotiation/Helper.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h3/negotiation/Helper.java
@@ -21,7 +21,6 @@ import org.apache.dubbo.remoting.ChannelHandler;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient;
import org.apache.dubbo.remoting.exchange.PortUnificationExchanger;
-import
org.apache.dubbo.remoting.transport.netty4.AbstractNettyConnectionClient;
import org.apache.dubbo.remoting.transport.netty4.NettyHttp3ConnectionClient;
import org.apache.dubbo.rpc.protocol.tri.ExceptionUtils;
@@ -33,7 +32,7 @@ public class Helper {
return new AutoSwitchConnectionClient(url,
PortUnificationExchanger.connect(url, handler));
}
- public static AbstractNettyConnectionClient createHttp3Client(URL url,
ChannelHandler handler) {
+ public static AbstractConnectionClient createHttp3Client(URL url,
ChannelHandler handler) {
try {
return new NettyHttp3ConnectionClient(url, handler);
} catch (RemotingException e) {
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java
index 4402c30c04..35c40c881e 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java
@@ -82,7 +82,11 @@ public class FallbackArgumentResolver extends
AbstractArgumentResolver {
try {
Object body = RequestUtils.decodeBody(request,
meta.genericType());
if (body != null) {
- return body;
+ if (body != RequestUtils.EMPTY_BODY) {
+ return body;
+ }
+ Object value = single ? request.parameter(meta.name())
: request.parameterValues(meta.name());
+ return value == null ? body : value;
}
} catch (DecodeException ignored) {
}
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/RequestUtils.java
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/RequestUtils.java
index 45d4cde2f0..bb152cc7a6 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/RequestUtils.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/RequestUtils.java
@@ -42,6 +42,8 @@ import java.util.StringTokenizer;
public final class RequestUtils {
+ public static final String EMPTY_BODY = "";
+
private RequestUtils() {}
public static boolean isMultiPart(HttpRequest request) {
@@ -185,7 +187,7 @@ public final class RequestUtils {
if (type instanceof Class) {
Class<?> clazz = (Class<?>) type;
if (clazz == String.class) {
- return StringUtils.EMPTY_STRING;
+ return EMPTY_BODY;
}
if (clazz == byte[].class) {
return new byte[0];
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 572adc6f09..3466cb775e 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
@@ -41,6 +41,18 @@ class RestProtocolTest extends BaseServiceTest {
'/hello.yml?name=world' | 'hello world'
}
+ def "hello world by post"() {
+ expect:
+ runner.post(path, body) == output
+ where:
+ path | body | output
+ '/hello?name=world' | null | 'hello world'
+ '/hello' | '' | 'hello '
+ '/hello?name=world' | '' | 'hello world'
+ '/hello' | '"world"' | 'hello world'
+ '/hello?name=world' | '"galaxy"' | 'hello galaxy'
+ }
+
def "argument test"() {
expect:
runner.post(path, body) == output
diff --git
a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/test/MockH2StreamChannel.java
b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/test/MockH2StreamChannel.java
index d6a31e6e41..b81ef4992d 100644
---
a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/test/MockH2StreamChannel.java
+++
b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/test/MockH2StreamChannel.java
@@ -35,7 +35,11 @@ public class MockH2StreamChannel implements H2StreamChannel {
@Override
public CompletableFuture<Void> writeHeader(HttpMetadata httpMetadata) {
- this.httpMetadata = httpMetadata;
+ if (this.httpMetadata == null) {
+ this.httpMetadata = httpMetadata;
+ } else {
+ this.httpMetadata.headers().putAll(httpMetadata.headers());
+ }
return CompletableFuture.completedFuture(null);
}
diff --git
a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java
b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java
index 81ef0b0582..6b03e6be7d 100644
---
a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java
+++
b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java
@@ -39,7 +39,7 @@ public class DubboTriple3AutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Filter.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
- @ConditionalOnProperty(prefix = PREFIX, name = "enable")
+ @ConditionalOnProperty(prefix = PREFIX, name = "enabled")
public static class TripleServletConfiguration {
@Bean
diff --git
a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java
b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java
index c750552f68..16f21dfef8 100644
---
a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java
+++
b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java
@@ -40,7 +40,7 @@ public class DubboTripleAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Filter.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
- @ConditionalOnProperty(prefix = PREFIX, name = "enable")
+ @ConditionalOnProperty(prefix = PREFIX, name = "enabled")
public static class TripleServletConfiguration {
@Bean