Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4c4f0e5
JAV-369 move implementation of HttpStatus and HttpStatusManager to fo…
Sep 21, 2017
c6fd037
JAV-369 create BodyBufferSupport to make get body from http simpler
Sep 21, 2017
2a6a760
JAV-369 create interface HttpServletRequestEx to aggragate HttpServle…
Sep 21, 2017
aad533f
JAV-369 change VertxToHttpServletRequest to VertxServerRequestToHttpS…
Sep 21, 2017
fff4132
JAV-369 create VertxClentRequestToHttpServletRequest
Sep 21, 2017
41773ab
JAV-369 wrap standard HttpServletRequest to HttpServletRequestEx, and…
Sep 21, 2017
4a738f7
JAV-369 create interface HttpServletResponseEx to aggragate HttpServl…
Sep 21, 2017
053ed4e
JAV-369 create VertxServerResponseToHttpServletResponse
Sep 21, 2017
76ef152
JAV-369 create VertxClientResponseToHttpServletResponse
Sep 21, 2017
e0a5986
JAV-369 create StandardHttpServletResponseEx
Sep 21, 2017
7a60c40
JAV-369 change ClientToHttpServletRequest to CommonToHttpServletRequest
Sep 21, 2017
e272fbc
JAV-369 change AbstractRestServer parameter to HttpServletRequestEx a…
Sep 21, 2017
bc923dc
JAV-369 ServletRestServer parameter change to HttpServletRequestEx an…
Sep 21, 2017
629ff0d
JAV-369 VertxRestServer parameter change to HttpServletRequestEx and …
Sep 21, 2017
a84548a
JAV-369 VertxHttpMethod use HttpServletRequestEx and HttpServletRespo…
Sep 21, 2017
dff18f2
JAV-369 HttpClientFilter and HttpServerFilter use new parameter
Sep 21, 2017
1cd532d
JAV-369 DefaultHttpClientFilter use new parameter
Sep 21, 2017
f3cc5b7
JAV-369 copy http header from restTemplate header to vertx http clien…
Sep 21, 2017
6148b8b
JAV-369 signature demo use new interface
Sep 21, 2017
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response.Status;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.Unpooled;
import io.servicecomb.common.rest.codec.RestCodec;
import io.servicecomb.common.rest.codec.produce.ProduceProcessor;
import io.servicecomb.common.rest.codec.produce.ProduceProcessorManager;
Expand All @@ -43,17 +44,20 @@
import io.servicecomb.core.invocation.InvocationFactory;
import io.servicecomb.foundation.common.utils.JsonUtils;
import io.servicecomb.foundation.common.utils.SPIServiceUtils;
import io.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import io.servicecomb.foundation.vertx.http.HttpServletResponseEx;
import io.servicecomb.foundation.vertx.stream.BufferOutputStream;
import io.servicecomb.serviceregistry.RegistryUtils;
import io.servicecomb.swagger.invocation.Response;
import io.servicecomb.swagger.invocation.exception.InvocationException;

public abstract class AbstractRestServer<HTTP_RESPONSE> {
public class AbstractRestServer {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRestServer.class);

// 所属的Transport
protected Transport transport;

protected List<HttpServerFilter> httpServerFilters = SPIServiceUtils.getSortedService(HttpServerFilter.class);;
protected List<HttpServerFilter> httpServerFilters = SPIServiceUtils.getSortedService(HttpServerFilter.class);

public AbstractRestServer() {
for (HttpServerFilter filter : httpServerFilters) {
Expand All @@ -65,8 +69,8 @@ public void setTransport(Transport transport) {
this.transport = transport;
}

protected void setContext(Invocation invocation, HttpServletRequest request) throws Exception {
String strCseContext = request.getHeader(Const.CSE_CONTEXT);
protected void setContext(Invocation invocation, HttpServletRequestEx requestEx) throws Exception {
String strCseContext = requestEx.getHeader(Const.CSE_CONTEXT);
if (StringUtils.isEmpty(strCseContext)) {
return;
}
Expand All @@ -76,62 +80,62 @@ protected void setContext(Invocation invocation, HttpServletRequest request) thr
invocation.setContext(cseContext);
}

protected void handleRequest(HttpServletRequest request, HTTP_RESPONSE httpResponse) {
protected void handleRequest(HttpServletRequestEx requestEx, HttpServletResponseEx responseEx) {
if (transport == null) {
transport = CseContext.getInstance().getTransportManager().findTransport(Const.RESTFUL);
}

try {
RestOperationMeta restOperation = findRestOperation(request);
RestOperationMeta restOperation = findRestOperation(requestEx);
OperationMeta operationMeta = restOperation.getOperationMeta();

operationMeta.getExecutor().execute(() -> {
try {
runOnExecutor(request, restOperation, httpResponse);
runOnExecutor(requestEx, restOperation, responseEx);
} catch (Exception e) {
LOGGER.error("rest server onRequest error", e);
sendFailResponse(null, request, httpResponse, e);
sendFailResponse(null, requestEx, responseEx, e);
}
});
} catch (Exception e) {
LOGGER.error("rest server onRequest error", e);
sendFailResponse(null, request, httpResponse, e);
sendFailResponse(null, requestEx, responseEx, e);
}
}

protected void runOnExecutor(HttpServletRequest request, RestOperationMeta restOperation,
HTTP_RESPONSE httpResponse) throws Exception {
String acceptType = request.getHeader("Accept");
protected void runOnExecutor(HttpServletRequestEx requestEx, RestOperationMeta restOperation,
HttpServletResponseEx responseEx) throws Exception {
String acceptType = requestEx.getHeader("Accept");
ProduceProcessor produceProcessor =
locateProduceProcessor(null, request, httpResponse, restOperation, acceptType);
locateProduceProcessor(null, requestEx, responseEx, restOperation, acceptType);
if (produceProcessor == null) {
// locateProduceProcessor内部已经应答了
return;
}

Object[] args = RestCodec.restToArgs(request, restOperation);
Object[] args = RestCodec.restToArgs(requestEx, restOperation);
Invocation invocation =
InvocationFactory.forProvider(transport.getEndpoint(),
restOperation.getOperationMeta(),
args);

this.setContext(invocation, request);
invocation.getHandlerContext().put(RestConst.REST_REQUEST, request);
this.setContext(invocation, requestEx);
invocation.getHandlerContext().put(RestConst.REST_REQUEST, requestEx);

for (HttpServerFilter filter : httpServerFilters) {
Response response = filter.afterReceiveRequest(invocation, request);
Response response = filter.afterReceiveRequest(invocation, requestEx);
if (response != null) {
sendResponse(invocation, request, httpResponse, produceProcessor, response);
sendResponse(invocation, requestEx, responseEx, produceProcessor, response);
return;
}
}

invocation.next(resp -> {
sendResponse(invocation, request, httpResponse, produceProcessor, resp);
sendResponse(invocation, requestEx, responseEx, produceProcessor, resp);
});
}

protected RestOperationMeta findRestOperation(HttpServletRequest request) {
protected RestOperationMeta findRestOperation(HttpServletRequestEx request) {
String targetMicroserviceName = request.getHeader(Const.TARGET_MICROSERVICE);
if (targetMicroserviceName == null) {
// for compatible
Expand All @@ -152,8 +156,8 @@ protected RestOperationMeta findRestOperation(HttpServletRequest request) {
}

// 找不到processor,则已经完成了应答,外界不必再处理
protected ProduceProcessor locateProduceProcessor(Invocation invocation, HttpServletRequest request,
HTTP_RESPONSE httpResponse,
protected ProduceProcessor locateProduceProcessor(Invocation invocation, HttpServletRequestEx requestEx,
HttpServletResponseEx responseEx,
RestOperationMeta restOperation, String acceptType) {
ProduceProcessor produceProcessor = restOperation.ensureFindProduceProcessor(acceptType);
if (produceProcessor != null) {
Expand All @@ -162,34 +166,63 @@ protected ProduceProcessor locateProduceProcessor(Invocation invocation, HttpSer

String msg = String.format("Accept %s is not supported", acceptType);
InvocationException exception = new InvocationException(Status.NOT_ACCEPTABLE, msg);
sendFailResponse(invocation, request, httpResponse, exception);
sendFailResponse(invocation, requestEx, responseEx, exception);
return null;
}

public void sendFailResponse(Invocation invocation, HttpServletRequest request, HTTP_RESPONSE httpResponse,
public void sendFailResponse(Invocation invocation, HttpServletRequestEx requestEx,
HttpServletResponseEx responseEx,
Throwable throwable) {
Response response = Response.createProducerFail(throwable);
sendResponse(invocation, request, httpResponse, ProduceProcessorManager.DEFAULT_PROCESSOR, response);
sendResponse(invocation, requestEx, responseEx, ProduceProcessorManager.DEFAULT_PROCESSOR, response);
}

// 成功、失败的统一应答处理,这里不能再出异常了,再出了异常也没办法处理
protected void sendResponse(Invocation invocation, HttpServletRequest request,
HTTP_RESPONSE httpServerResponse,
protected void sendResponse(Invocation invocation, HttpServletRequestEx requestEx,
HttpServletResponseEx responseEx,
ProduceProcessor produceProcessor, Response response) {
try {
doSendResponse(invocation, httpServerResponse, produceProcessor, response);
doSendResponse(invocation, responseEx, produceProcessor, response);
} catch (Throwable e) {
// 这只能是bug,没有办法再兜底了,只能记录日志
// 如果统一处理为500错误,也无法确定swagger中500对应的数据模型
// 并且本次调用本身可能就是500进来的
LOGGER.error("send response failed.", e);
} finally {
request.getAsyncContext().complete();
requestEx.getAsyncContext().complete();
}
}

// 成功、失败的统一应答处理
protected abstract void doSendResponse(Invocation invocation, HTTP_RESPONSE httpServerResponse,
@SuppressWarnings("deprecation")
protected void doSendResponse(Invocation invocation, HttpServletResponseEx responseEx,
ProduceProcessor produceProcessor,
Response response) throws Exception;
Response response) throws Exception {
responseEx.setStatus(response.getStatusCode(), response.getReasonPhrase());
responseEx.setContentType(produceProcessor.getName());

if (response.getHeaders().getHeaderMap() != null) {
for (Entry<String, List<Object>> entry : response.getHeaders().getHeaderMap().entrySet()) {
for (Object value : entry.getValue()) {
responseEx.addHeader(entry.getKey(), String.valueOf(value));
}
}
}

Object body = response.getResult();
if (response.isFailed()) {
body = ((InvocationException) body).getErrorData();
}

try (BufferOutputStream output = new BufferOutputStream(Unpooled.compositeBuffer())) {
produceProcessor.encodeResponse(output, body);

responseEx.setBodyBuffer(output.getBuffer());
for (HttpServerFilter filter : httpServerFilters) {
filter.beforeSendResponse(invocation, responseEx);
}

responseEx.flushBuffer();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ public final class RestConst {
private RestConst() {
}

public static final String CONFIG_COPY_REQUEST = "servicecomb.rest.copy-request";

public static final String REST_CLIENT_REQUEST_PATH = "rest-client-request-path";

public static final String SWAGGER_REST_OPERATION = "swaggerRestOperation";
Expand All @@ -43,4 +41,8 @@ private RestConst() {

// in producer invocation handler context
public static final String REST_REQUEST = "servicecomb-rest-request";

public static final String REST_RESPONSE = "servicecomb-rest-response";

public static final String CONSUMER_HEADER = "servicecomb-rest-consumer-header";
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,16 @@
package io.servicecomb.common.rest.filter;

import io.servicecomb.core.Invocation;
import io.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import io.servicecomb.foundation.vertx.http.HttpServletResponseEx;
import io.servicecomb.swagger.invocation.Response;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;

public interface HttpClientFilter {
int getOrder();

// bodyBytes maybe be null
void beforeSendRequest(Invocation invocation, HttpClientRequest clientRequest, Buffer requestBodyBuffer);
void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx);

// if finished, then return a none null response
// if return a null response, then sdk will call next filter.afterReceive
Response afterReceiveResponse(Invocation invocation, HttpClientResponse httpResponse, Buffer responseBodyBuffer)
throws Exception;
Response afterReceiveResponse(Invocation invocation, HttpServletResponseEx responseEx);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,23 @@

package io.servicecomb.common.rest.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import io.servicecomb.core.Invocation;
import io.servicecomb.core.definition.OperationMeta;
import io.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import io.servicecomb.foundation.vertx.http.HttpServletResponseEx;
import io.servicecomb.swagger.invocation.Response;

public interface HttpServerFilter {
int getOrder();

//if check failed, then return failed response
Response afterReceiveRequest(Invocation invocation, HttpServletRequest request);
default boolean needCacheRequest(OperationMeta operationMeta) {
return false;
}

// if finished, then return a none null response
// if return a null response, then sdk will call next filter.afterReceiveRequest
Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx);

// invocation maybe null
void beforeSendResponse(Invocation invocation, HttpServletResponse response, byte[] bodyBytes, int length);
void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx);
}
Loading