From e7fa74beb9aff0ce3ddd01f12a93b4d1618b8d1d Mon Sep 17 00:00:00 2001 From: suncairong163 <105478245+suncairong163@users.noreply.github.com> Date: Mon, 7 Aug 2023 14:54:13 +0800 Subject: [PATCH] Feature/dubbo3.2 resteasy response context result support (#12854) * resteasy response context result support * some detail --------- Co-authored-by: suncr --- .../resteasy/filter/DubboBuiltResponse.java | 54 +++++++++++++++++++ ...esteasyResponseContainerFilterAdapter.java | 13 ++--- .../rest/filter/ServiceInvokeRestFilter.java | 6 ++- .../rest/handler/NettyHttpHandler.java | 6 +-- .../rest/netty/NettyHttpResponse.java | 22 ++++++++ 5 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/DubboBuiltResponse.java diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/DubboBuiltResponse.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/DubboBuiltResponse.java new file mode 100644 index 0000000000..1a034c2891 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/DubboBuiltResponse.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.rest.extension.resteasy.filter; + +import org.jboss.resteasy.specimpl.BuiltResponse; + +/** + * wrapper resteasy BuiltResponse + */ +public class DubboBuiltResponse extends BuiltResponse { + + // user reset entity + private boolean resetEntity; + + public DubboBuiltResponse(Object entity, int status, Class entityClass) { + + this.entity = entity; + this.entityClass = entityClass; + this.status = status; + } + + + @Override + public void setEntity(Object entity) { + if (entity == null) { + return; + } + + if (entity.equals(this.entity)) { + return; + } + // reset entity true + this.resetEntity = true; + super.setEntity(entity); + } + + public boolean isResetEntity() { + return resetEntity; + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java index bdee7cd9b2..c6af847ece 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java @@ -24,7 +24,6 @@ import org.apache.dubbo.rpc.protocol.rest.filter.RestResponseFilter; import org.apache.dubbo.rpc.protocol.rest.filter.context.RestFilterContext; import org.apache.dubbo.rpc.protocol.rest.netty.NettyHttpResponse; import org.apache.dubbo.rpc.protocol.rest.request.RequestFacade; -import org.jboss.resteasy.specimpl.BuiltResponse; import org.jboss.resteasy.spi.HttpResponse; import javax.ws.rs.container.ContainerResponseFilter; @@ -50,16 +49,18 @@ public class ResteasyResponseContainerFilterAdapter implements RestResponseFilte // response filter entity first - // empty jaxrsResponse - BuiltResponse jaxrsResponse = new BuiltResponse(); + // build jaxrsResponse from rest netty response + DubboBuiltResponse dubboBuiltResponse = new DubboBuiltResponse(response.getResponseBody(), response.getStatus(), response.getEntityClass()); // NettyHttpResponse wrapper HttpResponse httpResponse = new ResteasyNettyHttpResponse(response); - DubboContainerResponseContextImpl containerResponseContext = createContainerResponseContext(requestFacade, httpResponse, jaxrsResponse, containerRequestFilters.toArray(new ContainerResponseFilter[0])); + DubboContainerResponseContextImpl containerResponseContext = createContainerResponseContext(requestFacade, httpResponse, dubboBuiltResponse, containerRequestFilters.toArray(new ContainerResponseFilter[0])); containerResponseContext.filter(); - if (jaxrsResponse.getEntity() != null) { + + // user reset entity + if (dubboBuiltResponse.hasEntity() && dubboBuiltResponse.isResetEntity()) { // clean output stream data restOutputStream(response); - writeResteasyResponse(url, requestFacade, response, jaxrsResponse); + writeResteasyResponse(url, requestFacade, response, dubboBuiltResponse); } addResponseHeaders(response, httpResponse.getOutputHeaders()); diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java index 0381b911bd..2704db0781 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java @@ -106,6 +106,9 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { // execute business method invoke Result result = invoker.invoke(rpcInvocation); + // set raw response + nettyHttpResponse.setResponseBody(result.getValue()); + if (result.hasException()) { Throwable exception = result.getException(); logger.error("", exception.getMessage(), "", "dubbo rest protocol provider Invoker invoke error", exception); @@ -150,7 +153,8 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { public static void writeResult(NettyHttpResponse nettyHttpResponse, URL url, Object value, Class returnType, MediaType mediaType) throws Exception { MessageCodecResultPair booleanMediaTypePair = HttpMessageCodecManager.httpMessageEncode(nettyHttpResponse.getOutputStream(), value, url, mediaType, returnType); - + // reset raw response result + nettyHttpResponse.setResponseBody(value); nettyHttpResponse.addOutputHeaders(RestHeaderEnum.CONTENT_TYPE.getHeader(), booleanMediaTypePair.getMediaType().value); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java index 839015ba6a..db4f2d21f1 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java @@ -113,7 +113,7 @@ public class NettyHttpHandler implements HttpHandler restFilters) throws Exception { RestFilterContext restFilterContext = new RestFilterContext(url, requestFacade, nettyHttpResponse, serviceDeployer); - for (RestFilter restResponseFilter : restFilters) { - restResponseFilter.filter(restFilterContext); + for (RestFilter restFilter : restFilters) { + restFilter.filter(restFilterContext); if (restFilterContext.complete()) { break; } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/NettyHttpResponse.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/NettyHttpResponse.java index c092907f3f..9cb6a38f18 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/NettyHttpResponse.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/NettyHttpResponse.java @@ -54,6 +54,10 @@ public class NettyHttpResponse implements HttpResponse { private boolean committed; private boolean keepAlive; private HttpMethod method; + // raw response body + private Object responseBody; + // raw response class + private Class entityClass; public NettyHttpResponse(final ChannelHandlerContext ctx, final boolean keepAlive) { this(ctx, keepAlive, null); @@ -105,6 +109,7 @@ public class NettyHttpResponse implements HttpResponse { @Override public void sendError(int status, String message) throws IOException { setStatus(status); + setResponseBody(message); if (message != null) { getOutputStream().write(message.getBytes(StandardCharsets.UTF_8)); } @@ -211,4 +216,21 @@ public class NettyHttpResponse implements HttpResponse { } } + + public Object getResponseBody() { + return responseBody; + } + + public void setResponseBody(Object responseBody) { + + this.responseBody = responseBody; + + if (responseBody != null) { + this.entityClass = responseBody.getClass(); + } + } + + public Class getEntityClass() { + return entityClass; + } }