Feature/dubbo3.2 resteasy response context result support (#12854)
* resteasy response context result support * some detail --------- Co-authored-by: suncr <suncairong@moresec.cn>
This commit is contained in:
parent
b39a1e82e1
commit
e7fa74beb9
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public class NettyHttpHandler implements HttpHandler<NettyRequestFacade, NettyHt
|
|||
|
||||
|
||||
/**
|
||||
* execute response filters
|
||||
* execute rest filters
|
||||
*
|
||||
* @param url
|
||||
* @param requestFacade
|
||||
|
|
@ -123,8 +123,8 @@ public class NettyHttpHandler implements HttpHandler<NettyRequestFacade, NettyHt
|
|||
public void executeFilters(URL url, RequestFacade requestFacade, NettyHttpResponse nettyHttpResponse, ServiceDeployer serviceDeployer, List<RestFilter> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue