网关逻辑调整
This commit is contained in:
parent
3af1185522
commit
e80cd14064
@ -76,6 +76,7 @@
|
||||
<groupId>com.smarterFramework</groupId>
|
||||
<artifactId>sf-service</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -9,12 +9,10 @@ import com.sf.service.index.utils.AppUtils;
|
||||
import com.sf.service.gateway.domain.*;
|
||||
import com.sf.service.gateway.domain.dto.QueryGatewayServerDTO;
|
||||
import com.sf.service.gateway.domain.dto.UpdateDataStatusDTO;
|
||||
import com.sf.service.gateway.domain.vo.GatewayInterfaceInfoListVO;
|
||||
import com.sf.service.gateway.domain.vo.GatewayServerDetailedVO;
|
||||
import com.sf.service.gateway.domain.vo.GatewayServerListVO;
|
||||
import com.sf.service.gateway.domain.vo.GatewayStrategyListVO;
|
||||
import com.sf.service.gateway.enums.GatewayDataStatus;
|
||||
import com.sf.service.gateway.enums.GatewayServiceModel;
|
||||
import com.sf.vertx.enums.GatewayServiceModel;
|
||||
import com.sf.service.gateway.service.IGatewayInterfaceInfoService;
|
||||
import com.sf.service.gateway.service.IGatewayRouteService;
|
||||
import com.sf.service.gateway.service.IGatewayServerService;
|
||||
|
@ -2,7 +2,7 @@ package com.sf.service.gateway.domain.dto;
|
||||
|
||||
import com.sf.common.annotation.Excel;
|
||||
import com.sf.service.gateway.domain.GatewayRoute;
|
||||
import com.sf.service.gateway.enums.GatewayRouteType;
|
||||
import com.sf.vertx.enums.GatewayRouteType;
|
||||
import com.sf.service.gateway.enums.RequestProtocol;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
@ -3,14 +3,10 @@ package com.sf.service.gateway.domain.vo;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.sf.common.annotation.Excel;
|
||||
import com.sf.service.gateway.domain.GatewayRoute;
|
||||
import com.sf.service.gateway.enums.GatewayRouteType;
|
||||
import com.sf.service.gateway.enums.RequestProtocol;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
|
@ -2,7 +2,7 @@ package com.sf.service.gateway.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.sf.service.gateway.domain.*;
|
||||
import com.sf.service.gateway.enums.GatewayServiceModel;
|
||||
import com.sf.vertx.enums.GatewayServiceModel;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
@ -1,17 +1,12 @@
|
||||
package com.sf.service.gateway.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.sf.common.annotation.Excel;
|
||||
import com.sf.common.core.domain.BaseEntity;
|
||||
import com.sf.service.gateway.domain.GatewayRoute;
|
||||
import com.sf.service.gateway.domain.GatewayServer;
|
||||
import com.sf.service.gateway.enums.GatewayServiceModel;
|
||||
import com.sf.vertx.enums.GatewayServiceModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
|
@ -1,45 +0,0 @@
|
||||
package com.sf.service.gateway.enums;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 网关路由类型
|
||||
*
|
||||
* @author zoukun
|
||||
*/
|
||||
public enum GatewayRouteType
|
||||
{
|
||||
WEIGHT_ROUTE("WEIGHT_ROUTE", "权重路由策略"),
|
||||
HEADER_ROUTE("HEADER_ROUTE", "请求头路由策略"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
GatewayRouteType(String code, String info)
|
||||
{
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo()
|
||||
{
|
||||
return info;
|
||||
}
|
||||
|
||||
public static GatewayRouteType getByCode(String code){
|
||||
if (StringUtils.hasText(code)) {
|
||||
for (GatewayRouteType value : GatewayRouteType.values()) {
|
||||
if (value.code.equals(code)){
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.sf.service.gateway.enums;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 网关服务模式
|
||||
*
|
||||
* @author zoukun
|
||||
*/
|
||||
public enum GatewayServiceModel
|
||||
{
|
||||
NORMAL("NORMAL", "普通模式"),
|
||||
ROUTE("ROUTE", "路由模式"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
GatewayServiceModel(String code, String info)
|
||||
{
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo()
|
||||
{
|
||||
return info;
|
||||
}
|
||||
|
||||
public static GatewayServiceModel getByCode(String code){
|
||||
if (StringUtils.hasText(code)) {
|
||||
for (GatewayServiceModel value : GatewayServiceModel.values()) {
|
||||
if (value.code.equals(code)){
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.sf.service.gateway.enums;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 网关服务类型
|
||||
*
|
||||
* @author zoukun
|
||||
*/
|
||||
public enum GatewayServiceType
|
||||
{
|
||||
SAC("SAC", "SAC规范服务"),
|
||||
OPEN("OPEN", "开放服务"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
GatewayServiceType(String code, String info)
|
||||
{
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo()
|
||||
{
|
||||
return info;
|
||||
}
|
||||
|
||||
public static GatewayServiceType getByCode(String code){
|
||||
if (StringUtils.hasText(code)) {
|
||||
for (GatewayServiceType value : GatewayServiceType.values()) {
|
||||
if (value.code.equals(code)){
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ import com.sf.common.utils.SecurityUtils;
|
||||
import com.sf.service.gateway.domain.*;
|
||||
import com.sf.service.gateway.enums.EncryptionAlgorithm;
|
||||
import com.sf.service.gateway.enums.GatewayDataStatus;
|
||||
import com.sf.service.gateway.enums.GatewayServiceModel;
|
||||
import com.sf.vertx.enums.GatewayServiceModel;
|
||||
import com.sf.service.gateway.enums.GatewayStrategyType;
|
||||
import com.sf.service.gateway.mapper.GatewayConfigMapper;
|
||||
import com.sf.service.gateway.service.*;
|
||||
|
@ -17,6 +17,8 @@ import com.sf.service.gateway.enums.*;
|
||||
import com.sf.service.gateway.mapper.GatewayRouteMapper;
|
||||
import com.sf.service.gateway.service.IGatewayRouteService;
|
||||
import com.sf.service.gateway.service.IGatewayServerService;
|
||||
import com.sf.vertx.enums.GatewayRouteType;
|
||||
import com.sf.vertx.enums.GatewayServiceModel;
|
||||
import com.sf.vertx.enums.MatchType;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -10,8 +10,8 @@ import com.sf.common.utils.URLUtils;
|
||||
import com.sf.service.gateway.domain.GatewayInterfaceInfo;
|
||||
import com.sf.service.gateway.domain.GatewayServer;
|
||||
import com.sf.service.gateway.enums.GatewayDataStatus;
|
||||
import com.sf.service.gateway.enums.GatewayServiceModel;
|
||||
import com.sf.service.gateway.enums.GatewayServiceType;
|
||||
import com.sf.vertx.enums.GatewayServiceModel;
|
||||
import com.sf.vertx.enums.GatewayServiceType;
|
||||
import com.sf.vertx.enums.RequestMethod;
|
||||
import com.sf.service.gateway.mapper.GatewayServerMapper;
|
||||
import com.sf.service.gateway.service.IGatewayInterfaceInfoService;
|
||||
|
119
sf-vertx-api/src/main/java/com/sf/vertx/enums/GatewayError.java
Normal file
119
sf-vertx-api/src/main/java/com/sf/vertx/enums/GatewayError.java
Normal file
@ -0,0 +1,119 @@
|
||||
package com.sf.vertx.enums;
|
||||
|
||||
/**
|
||||
* VertX网关错误
|
||||
*
|
||||
* @author zoukun
|
||||
*/
|
||||
public enum GatewayError {
|
||||
// CLIENT ERROR
|
||||
BAD_REQUEST(400, "Bad Request", ErrorType.CLIENT_ERROR),
|
||||
UNAUTHORIZED(401, "Unauthorized", ErrorType.CLIENT_ERROR),
|
||||
FORBIDDEN(403, "Forbidden", ErrorType.CLIENT_ERROR),
|
||||
NOT_FOUND(404, "Not Found", ErrorType.CLIENT_ERROR),
|
||||
METHOD_NOT_ALLOWED(405, "Method Not Allowed", ErrorType.CLIENT_ERROR),
|
||||
NOT_ACCEPTABLE(406, "Not Acceptable", ErrorType.CLIENT_ERROR),
|
||||
PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required", ErrorType.CLIENT_ERROR),
|
||||
REQUEST_TIMEOUT(408, "Request Timeout", ErrorType.CLIENT_ERROR),
|
||||
CONFLICT(409, "Conflict", ErrorType.CLIENT_ERROR),
|
||||
GONE(410, "Gone", ErrorType.CLIENT_ERROR),
|
||||
LENGTH_REQUIRED(411, "Length Required", ErrorType.CLIENT_ERROR),
|
||||
PRECONDITION_FAILED(412, "Precondition Failed", ErrorType.CLIENT_ERROR),
|
||||
PAYLOAD_TOO_LARGE(413, "Payload Too Large", ErrorType.CLIENT_ERROR),
|
||||
URI_TOO_LONG(414, "URI Too Long", ErrorType.CLIENT_ERROR),
|
||||
UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type", ErrorType.CLIENT_ERROR),
|
||||
REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested range not satisfiable", ErrorType.CLIENT_ERROR),
|
||||
EXPECTATION_FAILED(417, "Expectation Failed", ErrorType.CLIENT_ERROR),
|
||||
UNPROCESSABLE_ENTITY(422, "Unprocessable Entity", ErrorType.CLIENT_ERROR),
|
||||
LOCKED(423, "Locked", ErrorType.CLIENT_ERROR),
|
||||
FAILED_DEPENDENCY(424, "Failed Dependency", ErrorType.CLIENT_ERROR),
|
||||
TOO_EARLY(425, "Too Early", ErrorType.CLIENT_ERROR),
|
||||
UPGRADE_REQUIRED(426, "Upgrade Required", ErrorType.CLIENT_ERROR),
|
||||
PRECONDITION_REQUIRED(428, "Precondition Required", ErrorType.CLIENT_ERROR),
|
||||
TOO_MANY_REQUESTS(429, "Too Many Requests", ErrorType.CLIENT_ERROR),
|
||||
REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large", ErrorType.CLIENT_ERROR),
|
||||
UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons", ErrorType.CLIENT_ERROR),
|
||||
|
||||
// SERVER_ERROR
|
||||
INTERNAL_SERVER_ERROR(500, "Internal Server Error", ErrorType.SERVER_ERROR),
|
||||
NOT_IMPLEMENTED(501, "Not Implemented", ErrorType.SERVER_ERROR),
|
||||
BAD_GATEWAY(502, "Bad Gateway", ErrorType.SERVER_ERROR),
|
||||
SERVICE_UNAVAILABLE(503, "Service Unavailable", ErrorType.SERVER_ERROR),
|
||||
GATEWAY_TIMEOUT(504, "Gateway Timeout", ErrorType.SERVER_ERROR),
|
||||
HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version not supported", ErrorType.SERVER_ERROR),
|
||||
INSUFFICIENT_STORAGE(507, "Insufficient Storage", ErrorType.SERVER_ERROR),
|
||||
NOT_EXTENDED(510, "Not Extended", ErrorType.SERVER_ERROR),
|
||||
NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required", ErrorType.SERVER_ERROR),
|
||||
|
||||
// SERVICE_ERROR
|
||||
DEFAULT_SERVICE_ERROR(10000, "Service request failed, please try again later", ErrorType.SERVICE_ERROR), // 默认业务错误提示
|
||||
APP_ACCESS_PROHIBITED(10001, "应用禁止访问,请联系管理员", ErrorType.SERVICE_ERROR),
|
||||
APP_SERVICE_NOT_FOUND(10002, "APP service not found", ErrorType.SERVICE_ERROR),
|
||||
API_SERVICE_NOT_FOUND(10003, "API service not found", ErrorType.SERVICE_ERROR),
|
||||
PARAMETER_TRANSFER_ERROR(10010, "参数传递错误", ErrorType.SERVICE_ERROR),
|
||||
UNABLE_TO_FIND_ROUTING_ADDRESS(10011, "无法找到路由地址", ErrorType.SERVICE_ERROR),
|
||||
UNABLE_TO_FIND_MATCHING_ENCRYPTION_ALGORITHM(10012, "无法找到匹配的加解密算法", ErrorType.SERVICE_ERROR),
|
||||
UNABLE_TO_FIND_MATCHING_CIRCUIT_BREAKER_STRATEGY(10013, "无法找到匹配的熔断策略", ErrorType.SERVICE_ERROR),
|
||||
REVERSE_PROXY_EXECUTION_ERROR(10014, "反向代理执行错误", ErrorType.SERVICE_ERROR),
|
||||
REQUEST_URL_RESTRICTED_BY_FLOW(10015, "请求url被限流", ErrorType.SERVICE_ERROR),
|
||||
REQUEST_URL_IS_BROKEN(10016, "请求url被熔断", ErrorType.SERVICE_ERROR),
|
||||
APP_REQUEST_URL_RESTRICTED_BY_FLOW(10017, "应用请求url被限流", ErrorType.SERVICE_ERROR),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
private final String reasonPhrase;
|
||||
|
||||
private final ErrorType errorType;
|
||||
|
||||
GatewayError(int code, String reasonPhrase, ErrorType errorType) {
|
||||
this.code = code;
|
||||
this.reasonPhrase = reasonPhrase;
|
||||
this.errorType = errorType;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public ErrorType getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public String getReasonPhrase() {
|
||||
return reasonPhrase;
|
||||
}
|
||||
|
||||
public static GatewayError getByCode(int code) {
|
||||
for (GatewayError value : GatewayError.values()) {
|
||||
if (value.code == code) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 网关错误类型
|
||||
*/
|
||||
public enum ErrorType {
|
||||
|
||||
CLIENT_ERROR(4),
|
||||
SERVER_ERROR(5),
|
||||
/**
|
||||
* 业务错误,建议业务错误返回HTTP状态码为200,业务码放在返回信息当中。
|
||||
*/
|
||||
SERVICE_ERROR(10),
|
||||
;
|
||||
|
||||
private final int value;
|
||||
|
||||
ErrorType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.sf.vertx.enums;
|
||||
|
||||
|
||||
/**
|
||||
* 网关路由类型
|
||||
*
|
||||
* @author zoukun
|
||||
*/
|
||||
public enum GatewayRouteType {
|
||||
WEIGHT_ROUTE("WEIGHT_ROUTE", "权重路由策略"),
|
||||
HEADER_ROUTE("HEADER_ROUTE", "请求头路由策略"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
GatewayRouteType(String code, String info) {
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public static GatewayRouteType getByCode(String code) {
|
||||
for (GatewayRouteType value : GatewayRouteType.values()) {
|
||||
if (value.code.equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.sf.vertx.enums;
|
||||
|
||||
|
||||
/**
|
||||
* 网关服务模式
|
||||
*
|
||||
* @author zoukun
|
||||
*/
|
||||
public enum GatewayServiceModel {
|
||||
NORMAL("NORMAL", "普通模式"),
|
||||
ROUTE("ROUTE", "路由模式"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
GatewayServiceModel(String code, String info) {
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public static GatewayServiceModel getByCode(String code) {
|
||||
for (GatewayServiceModel value : GatewayServiceModel.values()) {
|
||||
if (value.code.equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.sf.vertx.enums;
|
||||
|
||||
|
||||
/**
|
||||
* 网关服务类型
|
||||
*
|
||||
* @author zoukun
|
||||
*/
|
||||
public enum GatewayServiceType {
|
||||
SAC("SAC", "SAC规范服务"),
|
||||
OPEN("OPEN", "开放服务"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
GatewayServiceType(String code, String info) {
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public static GatewayServiceType getByCode(String code) {
|
||||
for (GatewayServiceType value : GatewayServiceType.values()) {
|
||||
if (value.code.equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -226,6 +226,11 @@
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-consul-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.studio</groupId>
|
||||
<artifactId>org.apache.commons.codec</artifactId>
|
||||
<version>1.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.sf.vertx.constans;
|
||||
|
||||
public class SACConstants {
|
||||
|
||||
public static final String CACHE_KEY_CONNECTOR = ":";
|
||||
|
||||
public static final String APP_CONFIG = "appConfig";
|
||||
|
||||
public static final String API_CONFIG = "apiConfig";
|
||||
|
||||
public static final String API_SERVICE_TYPE = "apiServiceType";
|
||||
|
||||
public static final String CIRCUIT_BREAKER = "CIRCUIT_BREAKER";
|
||||
|
||||
/**
|
||||
* 业务码 key
|
||||
*/
|
||||
public static final String GATEWAY_SERVICE_CODE = "serviceCode";
|
||||
|
||||
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package com.sf.vertx.constans;
|
||||
|
||||
public class SacConstans {
|
||||
public static final String CACHE_KEY_CONNECTOR = ":";
|
||||
public static final String CIRCUIT_BREAKER = "CIRCUIT_BREAKER";
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package com.sf.vertx.constans;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import io.vertx.core.json.JsonObject;
|
||||
|
||||
public class SacErrorCode {
|
||||
public static final Integer DEFAULT_ERROR_CODE = 10000;
|
||||
public final static Map<Integer, String> _ERROR = new HashMap<>();
|
||||
static {
|
||||
_ERROR.put(400, "Bad Request");
|
||||
_ERROR.put(401, "Unauthorized");
|
||||
_ERROR.put(403, "Forbidden");
|
||||
_ERROR.put(404, "Not Found");
|
||||
_ERROR.put(413, "Request Entity Too Large");
|
||||
_ERROR.put(415, "Unsupported Media Type");
|
||||
_ERROR.put(500, "Internal Server Error");
|
||||
_ERROR.put(502, "Bad Gateway");
|
||||
_ERROR.put(503, "Service Unavailable");
|
||||
_ERROR.put(504, "Gateway Timeout");
|
||||
_ERROR.put(504, "Gateway Timeout");
|
||||
_ERROR.put(10000, "服务请求失败,请稍后再试"); // 默认错误提示
|
||||
_ERROR.put(10001, "应用禁止访问,请联系管理员");
|
||||
_ERROR.put(10010, "无法找到路由地址");
|
||||
_ERROR.put(10011, "无法找到匹配的加解密算法");
|
||||
_ERROR.put(10012, "参数传递错误");
|
||||
_ERROR.put(10013, "无法匹配加解密、熔断代理模式");
|
||||
_ERROR.put(10014, "反向代理执行错误");
|
||||
_ERROR.put(10015, "请求url被限流");
|
||||
_ERROR.put(10016, "请求url被熔断");
|
||||
_ERROR.put(10017, "应用请求url被限流");
|
||||
_ERROR.put(10018, "apiCode与uri不匹配");
|
||||
_ERROR.put(10019, "请求不支持conetnt-type类型");
|
||||
_ERROR.put(10020, "uri返回mock数据");
|
||||
_ERROR.put(10021, "无法找到负载均衡路由节点");
|
||||
_ERROR.put(10022, "uri模糊匹配,不能使用加解密、熔断策略.");
|
||||
};
|
||||
|
||||
public static JsonObject returnErrorMsg(Integer errorCode) {
|
||||
JsonObject json = new JsonObject();
|
||||
String msg = _ERROR.get(errorCode);
|
||||
if(StringUtils.isBlank(msg)) {
|
||||
// default
|
||||
json.put("code", DEFAULT_ERROR_CODE);
|
||||
json.put("msg", _ERROR.get(DEFAULT_ERROR_CODE));
|
||||
} else {
|
||||
json.put("code", errorCode);
|
||||
json.put("msg", msg);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.sf.vertx.handle;
|
||||
package com.sf.vertx.exception;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.sf.vertx.handle;
|
||||
package com.sf.vertx.exception;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
|
@ -0,0 +1,39 @@
|
||||
package com.sf.vertx.exception;
|
||||
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*/
|
||||
public class ServiceException extends RuntimeException {
|
||||
private static final long serialVersionUID = 7975954645547803572L;
|
||||
private final int statusCode;
|
||||
private final String payload;
|
||||
|
||||
public ServiceException() {
|
||||
this(GatewayError.DEFAULT_SERVICE_ERROR);
|
||||
}
|
||||
|
||||
public ServiceException(GatewayError gatewayError, String payload) {
|
||||
this(gatewayError.getCode(), payload, null);
|
||||
}
|
||||
|
||||
public ServiceException(GatewayError gatewayError) {
|
||||
this(gatewayError.getCode(), gatewayError.getReasonPhrase(), null);
|
||||
}
|
||||
|
||||
private ServiceException(int statusCode, String payload, Throwable cause) {
|
||||
super("(" + statusCode + ")" + payload, cause, false, false);
|
||||
this.statusCode = statusCode;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return payload;
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import com.sf.vertx.api.pojo.MockResponse;
|
||||
import com.sf.vertx.constans.SacErrorCode;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.exception.MockException;
|
||||
import com.sf.vertx.exception.ServiceException;
|
||||
import com.sf.vertx.utils.AppUtils;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.HttpException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ -12,16 +14,15 @@ public class ApiMockHandlerImpl implements ApiMockHandler {
|
||||
@Override
|
||||
public void handle(RoutingContext rc) {
|
||||
try {
|
||||
String cacheKey = AppConfigHandler.getApiCodeConfigCacheKey(rc);
|
||||
// mock
|
||||
MockResponse mockResponse = AppConfigHandler.mock(cacheKey, rc);
|
||||
MockResponse mockResponse = AppUtils.mock(rc);
|
||||
if (mockResponse != null) {
|
||||
rc.fail(new MockException(mockResponse.getHttpStatus(), mockResponse.getMockResponse()));
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
rc.fail(new HttpException(SacErrorCode.DEFAULT_ERROR_CODE));
|
||||
log.error("ApiMockHandlerImpl:",e);
|
||||
rc.fail(new ServiceException(GatewayError.DEFAULT_SERVICE_ERROR));
|
||||
return;
|
||||
}
|
||||
rc.next();
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import com.sf.vertx.constans.RedisKeyConfig;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.exception.ServiceException;
|
||||
import com.sf.vertx.pojo.SacCurrentLimiting;
|
||||
|
||||
import io.github.resilience4j.core.functions.CheckedRunnable;
|
||||
@ -9,6 +11,8 @@ import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.HttpException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.sf.vertx.constans.SACConstants.CACHE_KEY_CONNECTOR;
|
||||
|
||||
/***
|
||||
* 内存存储
|
||||
*
|
||||
@ -20,31 +24,26 @@ public class ApiRateLimitHandlerImpl implements ApiRateLimitHandler {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext rc) {
|
||||
log.info("Enter ApiRateLimitHandlerImpl.handle()");
|
||||
String appCode = rc.request().headers().get(AppConfigHandler.getAppCodeHeaderKey());
|
||||
String apiCode = rc.request().headers().get(AppConfigHandler.getApiCodeHeaderKey());
|
||||
|
||||
SacCurrentLimiting currentLimiting = AppConfigHandler.getApiCurrentLimiting(appCode, apiCode);
|
||||
|
||||
if(currentLimiting != null) {
|
||||
String key = RedisKeyConfig.APP_CURRENT_LIMITING_CONFIG_KEY + ":" + appCode + ":" + apiCode + ":" + rc.request().uri()
|
||||
+ ":" + rc.request().method();
|
||||
String key = RedisKeyConfig.APP_CURRENT_LIMITING_CONFIG_KEY + CACHE_KEY_CONNECTOR + appCode + CACHE_KEY_CONNECTOR + apiCode + CACHE_KEY_CONNECTOR + rc.request().uri()
|
||||
+ CACHE_KEY_CONNECTOR + rc.request().method();
|
||||
RateLimiter rateLimiter = currentLimiting.getRegistry().rateLimiter(key);
|
||||
CheckedRunnable restrictedCall = RateLimiter.decorateCheckedRunnable(rateLimiter,
|
||||
() -> {
|
||||
rc.next();
|
||||
return;
|
||||
});
|
||||
CheckedRunnable restrictedCall = RateLimiter.decorateCheckedRunnable(rateLimiter, rc::next);
|
||||
try {
|
||||
restrictedCall.run();
|
||||
} catch (Throwable t) {
|
||||
//t.printStackTrace();
|
||||
log.info("api ratelimit:{}", key);
|
||||
rc.fail(new HttpException(10015, currentLimiting.getStrategy().getDefaultResponse()));
|
||||
return;
|
||||
rc.fail(new ServiceException(GatewayError.REQUEST_URL_RESTRICTED_BY_FLOW, currentLimiting.getStrategy().getDefaultResponse()));
|
||||
}
|
||||
} else {
|
||||
rc.next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,8 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import com.sf.vertx.constans.RedisKeyConfig;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.exception.ServiceException;
|
||||
import com.sf.vertx.pojo.SacCurrentLimiting;
|
||||
|
||||
import io.github.resilience4j.core.functions.CheckedRunnable;
|
||||
@ -20,27 +22,23 @@ public class AppRateLimitHandlerImpl implements AppRateLimitHandler {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext rc) {
|
||||
log.info("Enter AppRateLimitHandlerImpl.handle()");
|
||||
String appCode = rc.request().headers().get(AppConfigHandler.getAppCodeHeaderKey());
|
||||
SacCurrentLimiting currentLimiting = AppConfigHandler.getGlobalAppCurrentLimitingConfig(appCode);
|
||||
|
||||
if (currentLimiting != null) {
|
||||
String key = RedisKeyConfig.APP_CURRENT_LIMITING_CONFIG_KEY + ":" + appCode;
|
||||
RateLimiter rateLimiter = currentLimiting.getRegistry().rateLimiter(key);
|
||||
CheckedRunnable restrictedCall = RateLimiter.decorateCheckedRunnable(rateLimiter, () -> {
|
||||
rc.next();
|
||||
return;
|
||||
});
|
||||
CheckedRunnable restrictedCall = RateLimiter.decorateCheckedRunnable(rateLimiter, rc::next);
|
||||
try {
|
||||
restrictedCall.run();
|
||||
} catch (Throwable t) {
|
||||
//t.printStackTrace();
|
||||
log.info("app ratelimit:{}", key);
|
||||
rc.fail(new HttpException(10015, currentLimiting.getStrategy().getDefaultResponse()));
|
||||
return;
|
||||
rc.fail(new ServiceException(GatewayError.REQUEST_URL_RESTRICTED_BY_FLOW, currentLimiting.getStrategy().getDefaultResponse()));
|
||||
}
|
||||
} else {
|
||||
rc.next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,6 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.sf.vertx.constans.SacErrorCode;
|
||||
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
@ -25,6 +21,10 @@ import com.sf.vertx.constans.SacErrorCode;
|
||||
* You may elect to redistribute this code under either of these licenses.
|
||||
*/
|
||||
|
||||
import com.sf.vertx.api.pojo.ApiConfig;
|
||||
import com.sf.vertx.api.pojo.AppConfig;
|
||||
import com.sf.vertx.enums.RequestMethod;
|
||||
import com.sf.vertx.utils.AppUtils;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import io.netty.handler.codec.http.HttpHeaderValues;
|
||||
import io.vertx.core.Future;
|
||||
@ -39,10 +39,11 @@ import io.vertx.core.impl.logging.Logger;
|
||||
import io.vertx.core.impl.logging.LoggerFactory;
|
||||
import io.vertx.ext.web.FileUpload;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.HttpException;
|
||||
import io.vertx.ext.web.impl.FileUploadImpl;
|
||||
import io.vertx.ext.web.impl.RoutingContextInternal;
|
||||
|
||||
import static com.sf.vertx.constans.SACConstants.*;
|
||||
|
||||
/**
|
||||
* @author <a href="http://tfox.org">Tim Fox</a>
|
||||
*/
|
||||
@ -77,94 +78,82 @@ public class BodyHandlerImpl implements BodyHandler {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext context) {
|
||||
// TODO 改造了这个地方
|
||||
final HttpServerRequest request = context.request();
|
||||
final HttpServerResponse response = context.response();
|
||||
String appCode = context.request().headers().get(AppConfigHandler.getAppCodeHeaderKey());
|
||||
String apiCode = context.request().headers().get(AppConfigHandler.getApiCodeHeaderKey());
|
||||
String contentType = context.request().headers().get(HttpHeaders.CONTENT_TYPE);
|
||||
boolean isLoadBody = false;
|
||||
try {
|
||||
isLoadBody = AppConfigHandler.isAnalysisBody(appCode, apiCode, contentType);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
context.fail(new HttpException(SacErrorCode.DEFAULT_ERROR_CODE));
|
||||
return;
|
||||
}
|
||||
if (isLoadBody) {
|
||||
// =======源码流程
|
||||
// final HttpServerRequest request = context.request();
|
||||
// final HttpServerResponse response = context.response();
|
||||
//
|
||||
// we need to keep state since we can be called again on reroute
|
||||
if (!((RoutingContextInternal) context).seenHandler(RoutingContextInternal.BODY_HANDLER)) {
|
||||
((RoutingContextInternal) context).visitHandler(RoutingContextInternal.BODY_HANDLER);
|
||||
// =======源码流程
|
||||
final HttpServerRequest request = context.request();
|
||||
final HttpServerResponse response = context.response();
|
||||
//
|
||||
// we need to keep state since we can be called again on reroute
|
||||
if (!((RoutingContextInternal) context).seenHandler(RoutingContextInternal.BODY_HANDLER)) {
|
||||
((RoutingContextInternal) context).visitHandler(RoutingContextInternal.BODY_HANDLER);
|
||||
|
||||
// Check if a request has a request body.
|
||||
// A request with a body __must__ either have `transfer-encoding`
|
||||
// or `content-length` headers set.
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
|
||||
final long parsedContentLength = parseContentLengthHeader(request);
|
||||
// http2 never transmits a `transfer-encoding` as frames are chunks.
|
||||
final boolean hasTransferEncoding = request.version() == HttpVersion.HTTP_2
|
||||
|| request.headers().contains(HttpHeaders.TRANSFER_ENCODING);
|
||||
// Check if a request has a request body.
|
||||
// A request with a body __must__ either have `transfer-encoding`
|
||||
// or `content-length` headers set.
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
|
||||
final long parsedContentLength = parseContentLengthHeader(request);
|
||||
// http2 never transmits a `transfer-encoding` as frames are chunks.
|
||||
final boolean hasTransferEncoding = request.version() == HttpVersion.HTTP_2
|
||||
|| request.headers().contains(HttpHeaders.TRANSFER_ENCODING);
|
||||
|
||||
if (!hasTransferEncoding && parsedContentLength == -1) {
|
||||
// there is no "body", so we can skip this handler
|
||||
context.next();
|
||||
return;
|
||||
}
|
||||
if (!hasTransferEncoding && parsedContentLength == -1) {
|
||||
// there is no "body", so we can skip this handler
|
||||
context.next();
|
||||
return;
|
||||
}
|
||||
|
||||
// before parsing the body we can already discard a bad request just by
|
||||
// inspecting the content-length against
|
||||
// the body limit, this will reduce load, on the server by totally skipping
|
||||
// parsing the request body
|
||||
if (bodyLimit != -1 && parsedContentLength != -1) {
|
||||
if (parsedContentLength > bodyLimit) {
|
||||
context.fail(413);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// before parsing the body we can already discard a bad request just by
|
||||
// inspecting the content-length against
|
||||
// the body limit, this will reduce load, on the server by totally skipping
|
||||
// parsing the request body
|
||||
if (bodyLimit != -1 && parsedContentLength != -1) {
|
||||
if (parsedContentLength > bodyLimit) {
|
||||
context.fail(413);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// handle expectations
|
||||
// https://httpwg.org/specs/rfc7231.html#header.expect
|
||||
final String expect = request.getHeader(HttpHeaders.EXPECT);
|
||||
if (expect != null) {
|
||||
// requirements validation
|
||||
if (expect.equalsIgnoreCase("100-continue")) {
|
||||
// A server that receives a 100-continue expectation in an HTTP/1.0 request MUST
|
||||
// ignore that expectation.
|
||||
if (request.version() != HttpVersion.HTTP_1_0) {
|
||||
// signal the client to continue
|
||||
response.writeContinue();
|
||||
}
|
||||
} else {
|
||||
// the server cannot meet the expectation, we only know about 100-continue
|
||||
context.fail(417);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final BHandler handler = new BHandler(context, isPreallocateBodyBuffer ? parsedContentLength : -1);
|
||||
boolean ended = request.isEnded();
|
||||
if (!ended) {
|
||||
request
|
||||
// resume the request (if paused)
|
||||
.handler(handler).endHandler(handler::end).resume();
|
||||
}
|
||||
} else {
|
||||
// on reroute we need to re-merge the form params if that was desired
|
||||
if (mergeFormAttributes && request.isExpectMultipart()) {
|
||||
request.params().addAll(request.formAttributes());
|
||||
}
|
||||
// handle expectations
|
||||
// https://httpwg.org/specs/rfc7231.html#header.expect
|
||||
final String expect = request.getHeader(HttpHeaders.EXPECT);
|
||||
if (expect != null) {
|
||||
// requirements validation
|
||||
if (expect.equalsIgnoreCase("100-continue")) {
|
||||
// A server that receives a 100-continue expectation in an HTTP/1.0 request MUST
|
||||
// ignore that expectation.
|
||||
if (request.version() != HttpVersion.HTTP_1_0) {
|
||||
// signal the client to continue
|
||||
response.writeContinue();
|
||||
}
|
||||
} else {
|
||||
// the server cannot meet the expectation, we only know about 100-continue
|
||||
context.fail(417);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 改造了这个地方 在真正解析body之前验证是否需要继续解析
|
||||
AppConfig appConfig = AppUtils.getAppConfigFromRoutingContext(context);
|
||||
ApiConfig apiConfig = AppUtils.getApiConfigFromRoutingContext(context);
|
||||
String apiServiceType = context.get(API_SERVICE_TYPE);
|
||||
if (!AppUtils.isAnalysisBody(appConfig,apiConfig,apiServiceType)){
|
||||
context.next();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 非加解密不处理
|
||||
context.next();
|
||||
return;
|
||||
}
|
||||
|
||||
final BHandler handler = new BHandler(context, isPreallocateBodyBuffer ? parsedContentLength : -1);
|
||||
boolean ended = request.isEnded();
|
||||
if (!ended) {
|
||||
request
|
||||
// resume the request (if paused)
|
||||
.handler(handler).endHandler(handler::end).resume();
|
||||
}
|
||||
} else {
|
||||
// on reroute we need to re-merge the form params if that was desired
|
||||
if (mergeFormAttributes && request.isExpectMultipart()) {
|
||||
request.params().addAll(request.formAttributes());
|
||||
}
|
||||
context.next();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,50 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import com.sf.vertx.api.pojo.ApiConfig;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.exception.ServiceException;
|
||||
|
||||
import com.sf.vertx.api.pojo.AppConfig;
|
||||
|
||||
import com.sf.vertx.utils.AppUtils;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.sf.vertx.constans.SACConstants.*;
|
||||
|
||||
@Slf4j
|
||||
public class OpenParameterCheckHandlerImpl implements ParameterCheckHandler {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext rc) {
|
||||
try {
|
||||
log.info("Enter OPEN Route");
|
||||
// 判断OPEN模式, header不传递参数, 走域名映射
|
||||
String domain = rc.request().authority().host();
|
||||
log.info("request domain:{}", domain);
|
||||
AppConfig appConfig = AppConfigHandler.getAppConfigByDomain(domain);
|
||||
if (appConfig == null) {
|
||||
rc.fail(new ServiceException(GatewayError.APP_SERVICE_NOT_FOUND));
|
||||
return;
|
||||
}
|
||||
String apiCacheKey = appConfig.getAppCode() + CACHE_KEY_CONNECTOR + domain;
|
||||
ApiConfig apiConfig = AppConfigHandler.getApicodeConfig(apiCacheKey);
|
||||
if (apiConfig == null) {
|
||||
rc.fail(new ServiceException(GatewayError.API_SERVICE_NOT_FOUND));
|
||||
return;
|
||||
}
|
||||
// 设置应用配置、接口配置到上下文
|
||||
AppUtils.setAppConfigToRoutingContext(appConfig,rc);
|
||||
AppUtils.setApiConfigIntoRoutingContext(apiConfig,rc);
|
||||
rc.put(API_SERVICE_TYPE,AppConfigHandler.getServiceTypeOpen(apiCacheKey));
|
||||
// 将appcode和apicode设置到请求头,兼容原有逻辑
|
||||
rc.request().headers().add(AppConfigHandler.getAppCodeHeaderKey(), appConfig.getAppCode());
|
||||
rc.request().headers().add(AppConfigHandler.getApiCodeHeaderKey(), apiConfig.getApiCode());
|
||||
} catch (Exception e) {
|
||||
log.error("OpenParameterCheckHandlerImpl Error:",e);
|
||||
rc.fail(new ServiceException(GatewayError.DEFAULT_SERVICE_ERROR));
|
||||
return;
|
||||
}
|
||||
rc.next();
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import com.sf.vertx.enums.GatewayServiceType;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.exception.ServiceException;
|
||||
import io.vertx.codegen.annotations.VertxGen;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
@ -13,7 +16,14 @@ import io.vertx.ext.web.RoutingContext;
|
||||
@VertxGen
|
||||
public interface ParameterCheckHandler extends Handler<RoutingContext> {
|
||||
|
||||
static ParameterCheckHandler create() {
|
||||
return new ParameterCheckHandlerImpl();
|
||||
}
|
||||
static ParameterCheckHandler create(GatewayServiceType serviceType) {
|
||||
switch (serviceType) {
|
||||
case SAC:
|
||||
return new SACParameterCheckHandlerImpl();
|
||||
case OPEN:
|
||||
return new OpenParameterCheckHandlerImpl();
|
||||
default:
|
||||
throw new ServiceException(GatewayError.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import com.sf.vertx.api.pojo.MockResponse;
|
||||
import io.vertx.ext.web.RequestBody;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.sf.vertx.api.pojo.AppConfig;
|
||||
import com.sf.vertx.constans.SacErrorCode;
|
||||
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.HttpException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ParameterCheckHandlerImpl implements ParameterCheckHandler {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext rc) {
|
||||
try {
|
||||
String domain = rc.request().authority().host();
|
||||
log.info("domain:{}", domain);
|
||||
String appCode = rc.request().headers().get(AppConfigHandler.getAppCodeHeaderKey());
|
||||
String apiCode = rc.request().headers().get(AppConfigHandler.getApiCodeHeaderKey());
|
||||
String key = appCode + ":" + apiCode;
|
||||
if (StringUtils.isBlank(appCode) || StringUtils.isBlank(apiCode)
|
||||
|| AppConfigHandler.getAppConfig(appCode) == null
|
||||
|| AppConfigHandler.getApicodeConfig(key) == null) {
|
||||
// 判断OPEN模式, header不传递参数, 走域名映射
|
||||
AppConfig appConfig = AppConfigHandler.getAppConfigByDomain(domain);
|
||||
if(appConfig != null) {
|
||||
appCode = appConfig.getAppCode();
|
||||
apiCode = domain;
|
||||
rc.request().headers().add(AppConfigHandler.getAppCodeHeaderKey(), appCode);
|
||||
rc.request().headers().add(AppConfigHandler.getApiCodeHeaderKey(), apiCode);
|
||||
key = appCode + ":" + apiCode;
|
||||
} else {
|
||||
rc.fail(new HttpException(10012));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(AppConfigHandler.isDisabledAppcode(apiCode)) {
|
||||
rc.fail(new HttpException(10001));
|
||||
return;
|
||||
}
|
||||
|
||||
// 通过请求模式来区分
|
||||
String uri = rc.request().uri();
|
||||
String httpMethod = rc.request().method().name();
|
||||
if(AppConfigHandler.isServiceTypeOpen(key) && AppConfigHandler.isApicodeUri(key, uri, httpMethod) == false) {
|
||||
rc.fail(new HttpException(10018));
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
rc.fail(new HttpException(SacErrorCode.DEFAULT_ERROR_CODE));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
rc.next();
|
||||
return;
|
||||
}
|
||||
}
|
@ -1,57 +1,66 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import io.vertx.core.buffer.Buffer;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.exception.MockException;
|
||||
import com.sf.vertx.exception.ServiceException;
|
||||
import com.sf.vertx.utils.AppUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.sf.vertx.constans.SacErrorCode;
|
||||
|
||||
import io.vertx.core.http.HttpHeaders;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.HttpException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public class RestfulFailureHandlerImpl implements RestfulFailureHandler {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext frc) {
|
||||
int statusCode = 500;
|
||||
JsonObject errorJson = null;
|
||||
Integer sc = SacErrorCode.DEFAULT_ERROR_CODE;
|
||||
JsonObject errorJson;
|
||||
// 网关的业务码
|
||||
int gatewayServiceCode = GatewayError.DEFAULT_SERVICE_ERROR.getCode();
|
||||
try {
|
||||
Throwable failure = frc.failure();
|
||||
log.info("failure:", failure);
|
||||
if (failure instanceof HttpException) {
|
||||
HttpException httpException = (HttpException) failure;
|
||||
sc = httpException.getStatusCode();
|
||||
if (StringUtils.isNoneBlank(httpException.getPayload())) {
|
||||
errorJson = new JsonObject(httpException.getPayload());
|
||||
} else {
|
||||
errorJson = SacErrorCode.returnErrorMsg(httpException.getStatusCode());
|
||||
gatewayServiceCode = httpException.getStatusCode();
|
||||
errorJson = AppUtils.getResponseJsonByGatewayError(GatewayError.getByCode(statusCode));
|
||||
if (StringUtils.isNotBlank(httpException.getPayload())){
|
||||
errorJson.put("msg",httpException.getPayload());
|
||||
}
|
||||
} else if (failure instanceof MockException) {
|
||||
MockException httpException = (MockException) failure;
|
||||
sc = httpException.getStatusCode();
|
||||
statusCode = httpException.getStatusCode();
|
||||
if (StringUtils.isNoneBlank(httpException.getPayload())) {
|
||||
errorJson = new JsonObject(httpException.getPayload());
|
||||
} else {
|
||||
errorJson = SacErrorCode.returnErrorMsg(httpException.getStatusCode());
|
||||
MockException mockException = (MockException) failure;
|
||||
gatewayServiceCode = mockException.getStatusCode();
|
||||
statusCode = mockException.getStatusCode();
|
||||
errorJson = new JsonObject(mockException.getPayload());
|
||||
}else if (failure instanceof ServiceException) {
|
||||
ServiceException serviceException = (ServiceException) failure;
|
||||
gatewayServiceCode = serviceException.getStatusCode();
|
||||
// 业务异常,为网关业务错误,响应码设置为500,
|
||||
GatewayError gatewayError = GatewayError.getByCode(serviceException.getStatusCode());
|
||||
// 如果是被限流或熔断,直接返回限流或熔断响应
|
||||
if (GatewayError.REQUEST_URL_RESTRICTED_BY_FLOW.equals(gatewayError)
|
||||
|| GatewayError.REQUEST_URL_IS_BROKEN.equals(gatewayError)){
|
||||
errorJson = new JsonObject(serviceException.getPayload());
|
||||
}else {
|
||||
errorJson = AppUtils.getResponseJsonByGatewayError(gatewayError);
|
||||
}
|
||||
} else {
|
||||
errorJson = SacErrorCode.returnErrorMsg(SacErrorCode.DEFAULT_ERROR_CODE);
|
||||
errorJson = AppUtils.getResponseJsonByGatewayError(GatewayError.getByCode(statusCode));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
errorJson = SacErrorCode.returnErrorMsg(SacErrorCode.DEFAULT_ERROR_CODE);
|
||||
log.error("RestfulFailureHandlerImpl.handle Error:",e);
|
||||
errorJson = AppUtils.getResponseJsonByGatewayError(GatewayError.DEFAULT_SERVICE_ERROR);
|
||||
}
|
||||
|
||||
frc.response().setChunked(true).setStatusCode(statusCode).putHeader("Content-Type", "application/json")
|
||||
.putHeader(AppConfigHandler.sacResponseHeaderKey(), String.valueOf(sc))
|
||||
.putHeader(AppConfigHandler.sacResponseHeaderKey(), String.valueOf(gatewayServiceCode))
|
||||
.end(errorJson.toBuffer());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package com.sf.vertx.handle;
|
||||
|
||||
import com.sf.vertx.api.pojo.ApiConfig;
|
||||
import com.sf.vertx.api.pojo.AppConfig;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.exception.ServiceException;
|
||||
import com.sf.vertx.utils.AppUtils;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static com.sf.vertx.constans.SACConstants.*;
|
||||
|
||||
@Slf4j
|
||||
public class SACParameterCheckHandlerImpl implements ParameterCheckHandler {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext rc) {
|
||||
try {
|
||||
log.info("Enter SAC Route");
|
||||
// SAC规范要求Header必须要同时包含appCode和apiCode
|
||||
String appCode = rc.request().headers().get(AppConfigHandler.getAppCodeHeaderKey());
|
||||
String apiCode = rc.request().headers().get(AppConfigHandler.getApiCodeHeaderKey());
|
||||
if (StringUtils.isBlank(appCode) || StringUtils.isBlank(apiCode)) {
|
||||
rc.fail(new ServiceException(GatewayError.PARAMETER_TRANSFER_ERROR));
|
||||
return;
|
||||
}
|
||||
AppConfig appConfig = AppConfigHandler.getAppConfig(appCode);
|
||||
if (appConfig == null) {
|
||||
rc.fail(new ServiceException(GatewayError.APP_SERVICE_NOT_FOUND));
|
||||
return;
|
||||
}
|
||||
String apiCacheKey = appConfig.getAppCode() + CACHE_KEY_CONNECTOR + apiCode;
|
||||
ApiConfig apiConfig = AppConfigHandler.getApicodeConfig(apiCacheKey);
|
||||
if (apiConfig == null) {
|
||||
rc.fail(new ServiceException(GatewayError.API_SERVICE_NOT_FOUND));
|
||||
return;
|
||||
}
|
||||
// 设置应用配置、接口配置到上下文
|
||||
AppUtils.setAppConfigToRoutingContext(appConfig,rc);
|
||||
AppUtils.setApiConfigIntoRoutingContext(apiConfig,rc);
|
||||
rc.put(API_SERVICE_TYPE,AppConfigHandler.getServiceTypeOpen(apiCacheKey));
|
||||
} catch (Exception e) {
|
||||
log.error("SACParameterCheckHandlerImpl Error:",e);
|
||||
rc.fail(new ServiceException(GatewayError.DEFAULT_SERVICE_ERROR));
|
||||
return;
|
||||
}
|
||||
rc.next();
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ public class MainSecurity {
|
||||
*/
|
||||
public static String rsaEncrypt(String content, String pubKey) {
|
||||
try {
|
||||
return RSAUtil.encrypt1(content, pubKey);
|
||||
return RSAUtil.encrypt(content, pubKey);
|
||||
} catch (Exception e) {
|
||||
LOGGER.info("RSA加密失败");
|
||||
e.printStackTrace();
|
||||
@ -27,7 +27,7 @@ public class MainSecurity {
|
||||
|
||||
public static String rsaDecrypt(String content, String priKey) {
|
||||
try {
|
||||
return RSAUtil.decrypt1(content, priKey);
|
||||
return RSAUtil.decrypt(content, priKey);
|
||||
} catch (Exception e) {
|
||||
LOGGER.info("RSA解密失败");
|
||||
e.printStackTrace();
|
||||
|
File diff suppressed because one or more lines are too long
255
sf-vertx/src/main/java/com/sf/vertx/utils/AppUtils.java
Normal file
255
sf-vertx/src/main/java/com/sf/vertx/utils/AppUtils.java
Normal file
@ -0,0 +1,255 @@
|
||||
package com.sf.vertx.utils;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import com.sf.vertx.api.pojo.*;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.enums.GatewayServiceType;
|
||||
import com.sf.vertx.enums.MatchType;
|
||||
import com.sf.vertx.enums.RequestMethod;
|
||||
import com.sf.vertx.handle.AppConfigHandler;
|
||||
import io.vertx.circuitbreaker.CircuitBreaker;
|
||||
import io.vertx.core.http.HttpServerRequest;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import static com.sf.vertx.constans.SACConstants.*;
|
||||
|
||||
/**
|
||||
* 功能描述:
|
||||
*
|
||||
* @author a_kun
|
||||
* @date 2024/5/24 12:30
|
||||
*/
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
public class AppUtils {
|
||||
|
||||
/**
|
||||
* 将AppConfig设置到上下文中
|
||||
* 配合getAppConfigFromRoutingContext(RoutingContext rc)使用
|
||||
* @param appConfig
|
||||
* @param rc
|
||||
*/
|
||||
public static void setAppConfigToRoutingContext(AppConfig appConfig, RoutingContext rc) {
|
||||
rc.put(APP_CONFIG,appConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从路由上下文获取AppConfig
|
||||
* @param rc
|
||||
* @return AppConfig
|
||||
*/
|
||||
public static AppConfig getAppConfigFromRoutingContext(RoutingContext rc) {
|
||||
return rc.get(APP_CONFIG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将AppConfig设置到上下文中
|
||||
* 配合getApiConfigFromRoutingContext(RoutingContext rc)使用
|
||||
* @param apiConfig
|
||||
* @param rc
|
||||
*/
|
||||
public static void setApiConfigIntoRoutingContext(ApiConfig apiConfig, RoutingContext rc) {
|
||||
rc.put(API_CONFIG,apiConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从路由上下文获取ApiConfig
|
||||
* @param rc
|
||||
* @return ApiConfig
|
||||
*/
|
||||
public static ApiConfig getApiConfigFromRoutingContext(RoutingContext rc) {
|
||||
return rc.get(API_CONFIG);
|
||||
}
|
||||
|
||||
public static boolean isEnableMockApi(ApiConfig apiConfig) {
|
||||
if (apiConfig != null) {
|
||||
return apiConfig.getMockDefaultHttpStatus() != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断API服务类型是否是SAC规范服务类型
|
||||
*
|
||||
* @param apiServiceType
|
||||
* @return
|
||||
*/
|
||||
public static boolean isSACServiceType(String apiServiceType) {
|
||||
return GatewayServiceType.SAC.getCode().equals(apiServiceType);
|
||||
}
|
||||
|
||||
public static boolean isEnableDataSecurity(AppConfig appConfig) {
|
||||
return appConfig != null && appConfig.getDataSecurity() != null;
|
||||
}
|
||||
|
||||
public static MockResponse mock(RoutingContext rc) {
|
||||
AppConfig appConfig = getAppConfigFromRoutingContext(rc);
|
||||
ApiConfig apiConfig = getApiConfigFromRoutingContext(rc);
|
||||
String apiServiceType = rc.get(API_SERVICE_TYPE);
|
||||
if (AppUtils.isEnableMockApi(apiConfig)) {
|
||||
// 如果是sac服务,query和body参数都从body中取
|
||||
Integer httpStatus = apiConfig.getMockDefaultHttpStatus();
|
||||
String mockResponse = apiConfig.getMockDefaultResponse();
|
||||
List<MockExpectation> mockExpectations = apiConfig.getMockExpectations();
|
||||
if (mockExpectations != null && !mockExpectations.isEmpty()) {
|
||||
String bodyStr = rc.body().asString();
|
||||
if (AppUtils.isEnableDataSecurity(appConfig)) {
|
||||
bodyStr = AppConfigHandler.bodyDecrypt(bodyStr, appConfig.getAppCode());
|
||||
}
|
||||
JsonObject jsonBody = new JsonObject(bodyStr);
|
||||
for (MockExpectation mockExpectation : mockExpectations) {
|
||||
// 匹配条件需要全部匹配成功
|
||||
boolean matchSuccess = true;
|
||||
for (MockMatchCondition matchCondition : mockExpectation.getMatchConditions()) {
|
||||
if (!matchSuccess) {
|
||||
break;
|
||||
}
|
||||
MatchType matchType = MatchType.getByCode(matchCondition.getMatchType());
|
||||
if (matchType == null) {
|
||||
matchSuccess = false;
|
||||
break;
|
||||
}
|
||||
String parameterPosition = matchCondition.getParameterPosition();
|
||||
String parameterKey = matchCondition.getParameterKey();
|
||||
List<String> parameterValue = matchCondition.getParameterValue();
|
||||
String requestParameterValue = getRequestParameterValue(AppUtils.isSACServiceType(apiServiceType), parameterPosition, parameterKey, rc.request(), jsonBody);
|
||||
if (!MatchType.IS_NULL.equals(matchType) && !MatchType.NOT_NULL.equals(matchType)) {
|
||||
// 需要值而没有设置值,直接匹配失败
|
||||
if (CollectionUtil.isEmpty(parameterValue) || requestParameterValue == null) {
|
||||
matchSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (matchType) {
|
||||
case EQ:
|
||||
matchSuccess = parameterValue.get(0).equals(requestParameterValue);
|
||||
break;
|
||||
case NOT_EQ:
|
||||
matchSuccess = !parameterValue.get(0).equals(requestParameterValue);
|
||||
break;
|
||||
case GT:
|
||||
if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) {
|
||||
matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) > 0;
|
||||
} else {
|
||||
matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) > 0;
|
||||
}
|
||||
break;
|
||||
case GE:
|
||||
if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) {
|
||||
matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) >= 0;
|
||||
} else {
|
||||
matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) >= 0;
|
||||
}
|
||||
break;
|
||||
case LT:
|
||||
if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) {
|
||||
matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) < 0;
|
||||
} else {
|
||||
matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) < 0;
|
||||
}
|
||||
break;
|
||||
case LE:
|
||||
if (NumberUtil.isNumber(requestParameterValue) && NumberUtil.isNumber(parameterValue.get(0))) {
|
||||
matchSuccess = new BigDecimal(requestParameterValue).compareTo(new BigDecimal(parameterValue.get(0))) <= 0;
|
||||
} else {
|
||||
matchSuccess = requestParameterValue.compareTo(parameterValue.get(0)) <= 0;
|
||||
}
|
||||
break;
|
||||
case IN:
|
||||
matchSuccess = parameterValue.contains(requestParameterValue);
|
||||
break;
|
||||
case NOT_IN:
|
||||
matchSuccess = !parameterValue.contains(requestParameterValue);
|
||||
break;
|
||||
case IS_NULL:
|
||||
matchSuccess = requestParameterValue == null;
|
||||
break;
|
||||
case NOT_NULL:
|
||||
matchSuccess = requestParameterValue != null;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (matchSuccess) {
|
||||
httpStatus = mockExpectation.getHttpStatus();
|
||||
mockResponse = mockExpectation.getMockResponse();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new MockResponse(httpStatus, mockResponse);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getRequestParameterValue(Boolean isServiceTypeSac, String parameterPosition, String parameterKey, HttpServerRequest request, JsonObject jsonBody) {
|
||||
switch (parameterPosition) {
|
||||
case "query":
|
||||
if (isServiceTypeSac) {
|
||||
return jsonBody.getString(parameterKey);
|
||||
}
|
||||
return request.getParam(parameterKey);
|
||||
case "header":
|
||||
return request.getHeader(parameterKey);
|
||||
case "body":
|
||||
return jsonBody.getString(parameterKey);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getResponseMsgByGatewayError(GatewayError gatewayError) {
|
||||
if (gatewayError != null) {
|
||||
return gatewayError.getReasonPhrase();
|
||||
}
|
||||
return getResponseMsgByGatewayError(GatewayError.DEFAULT_SERVICE_ERROR);
|
||||
}
|
||||
|
||||
public static JsonObject getResponseJsonByGatewayError(GatewayError gatewayError) {
|
||||
if (gatewayError != null) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.put("code",gatewayError.getCode());
|
||||
jsonObject.put("msg",gatewayError.getReasonPhrase());
|
||||
return jsonObject;
|
||||
}
|
||||
return getResponseJsonByGatewayError(GatewayError.DEFAULT_SERVICE_ERROR);
|
||||
}
|
||||
|
||||
public static boolean isAnalysisBody(AppConfig appConfig, ApiConfig apiConfig,String apiServiceType) {
|
||||
// 不是Mock(是mock模式的话,存在body就解析。)
|
||||
if (AppUtils.isEnableMockApi(apiConfig)) {
|
||||
return true;
|
||||
}
|
||||
// SAC模式,实际API请求方式GET,DELETE,HEAD请求需要解析body,可能需要二次处理。(SAC模式请求方式参数统一使用body传递)
|
||||
// SAC模式,如果是POST或者PUT,并且没有设置数据加密则跳过
|
||||
if (AppUtils.isSACServiceType(apiServiceType)) {
|
||||
RequestMethod requestMethod = RequestMethod.getByCode(apiConfig.getMethod());
|
||||
if (RequestMethod.GET.equals(requestMethod)
|
||||
|| RequestMethod.DELETE.equals(requestMethod)
|
||||
|| RequestMethod.HEAD.equals(requestMethod)) {
|
||||
return true;
|
||||
}
|
||||
String keyCircuitBreaker = appConfig.getAppCode() + ":" + apiConfig.getApiCode() + ":" + "CIRCUIT_BREAKER";
|
||||
CircuitBreaker circuitBreaker = AppConfigHandler.getApiCodeCircuitBreaker(keyCircuitBreaker);
|
||||
boolean isDataSecurity = AppUtils.isEnableDataSecurity(appConfig);
|
||||
// 文件上传不走加解密
|
||||
return (isDataSecurity || circuitBreaker != null);
|
||||
}else {
|
||||
// 未启用Mock,OPEN模式都不会解析body
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -18,10 +18,13 @@ import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.sf.vertx.api.pojo.ApiConfig;
|
||||
import com.sf.vertx.api.pojo.AppConfig;
|
||||
import com.sf.vertx.enums.GatewayError;
|
||||
import com.sf.vertx.enums.RequestMethod;
|
||||
import com.sf.vertx.utils.AppUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.sf.vertx.constans.SacErrorCode;
|
||||
import com.sf.vertx.handle.AppConfigHandler;
|
||||
import com.sf.vertx.utils.ProxyTool;
|
||||
|
||||
@ -57,6 +60,7 @@ import io.vertx.httpproxy.cache.CacheOptions;
|
||||
import io.vertx.httpproxy.spi.cache.Cache;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.sf.vertx.constans.SACConstants.API_SERVICE_TYPE;
|
||||
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||
|
||||
@Slf4j
|
||||
@ -181,7 +185,7 @@ public class ReverseProxy implements HttpProxy {
|
||||
* @param sc
|
||||
*/
|
||||
private void end(ProxyRequest proxyRequest, int sc) {
|
||||
JsonObject json = SacErrorCode.returnErrorMsg(sc);
|
||||
JsonObject json = AppUtils.getResponseJsonByGatewayError(GatewayError.getByCode(sc));
|
||||
proxyRequest.response().release().setStatusCode(500).putHeader("content-type", "application/json")
|
||||
.putHeader(AppConfigHandler.sacResponseHeaderKey(), String.valueOf(sc))
|
||||
.putHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(json.size())).setBody(Body.body(json.toBuffer()))
|
||||
@ -345,10 +349,7 @@ public class ReverseProxy implements HttpProxy {
|
||||
}
|
||||
|
||||
|
||||
private HttpRequest<Buffer> buildCallRequestBuffer(ProxyRequest proxyRequest,String body) {
|
||||
String appCode = proxyRequest.headers().get(AppConfigHandler.getAppCodeHeaderKey());
|
||||
String apiCode = proxyRequest.headers().get(AppConfigHandler.getApiCodeHeaderKey());
|
||||
String key = appCode + ":" + apiCode;
|
||||
private HttpRequest<Buffer> buildCallRequestBuffer(ProxyRequest proxyRequest,String body,ApiConfig apiConfig) {
|
||||
SocketAddress socketAddress = ProxyTool.resolveOriginAddress(proxyRequest.proxiedRequest());
|
||||
HttpRequest<Buffer> requestBuffer;
|
||||
String requestURI = proxyRequest.getURI();
|
||||
@ -369,7 +370,7 @@ public class ReverseProxy implements HttpProxy {
|
||||
requestBuffer = mainWebClient.post(socketAddress.port(), socketAddress.host(), requestURI);
|
||||
break;
|
||||
}
|
||||
requestBuffer.timeout(AppConfigHandler.getApicodeConfigTimeOut(key));
|
||||
requestBuffer.timeout(apiConfig.getTimeout());
|
||||
requestBuffer.putHeaders(proxyRequest.headers());
|
||||
// 处理sac请求方式
|
||||
RequestMethod requestMethod = RequestMethod.getByCode(proxyRequest.getMethod().name());
|
||||
@ -393,14 +394,14 @@ public class ReverseProxy implements HttpProxy {
|
||||
// 判断<br/>
|
||||
// 1、是否配置全局加解密.<br/>
|
||||
// 2、apiCode 配置熔断
|
||||
String appCode = proxyRequest.headers().get(AppConfigHandler.getAppCodeHeaderKey());
|
||||
String apiCode = proxyRequest.headers().get(AppConfigHandler.getApiCodeHeaderKey());
|
||||
String contentType = proxyRequest.headers().get(HttpHeaders.CONTENT_TYPE);
|
||||
String keyCircuitBreaker = appCode + ":" + apiCode + ":" + "CIRCUIT_BREAKER";
|
||||
AppConfig appConfig = AppUtils.getAppConfigFromRoutingContext(ctx);
|
||||
ApiConfig apiConfig = AppUtils.getApiConfigFromRoutingContext(ctx);
|
||||
String apiServiceType = ctx.get(API_SERVICE_TYPE);
|
||||
String keyCircuitBreaker = appConfig.getAppCode() + ":" + apiConfig.getApiCode() + ":" + "CIRCUIT_BREAKER";
|
||||
CircuitBreaker circuitBreaker = AppConfigHandler.getApiCodeCircuitBreaker(keyCircuitBreaker);
|
||||
if (AppConfigHandler.isAnalysisBody(appCode, apiCode, contentType)) {
|
||||
String body = AppConfigHandler.isDataSecurity(appCode) ? AppConfigHandler.bodyDecrypt(ctx.body().asString(), appCode):ctx.body().asString();
|
||||
HttpRequest<Buffer> requestBuffer = buildCallRequestBuffer(proxyRequest,body);
|
||||
if (AppUtils.isAnalysisBody(appConfig,apiConfig,apiServiceType)) {
|
||||
String body = AppUtils.isEnableDataSecurity(appConfig) ? AppConfigHandler.bodyDecrypt(ctx.body().asString(), appConfig.getAppCode()):ctx.body().asString();
|
||||
HttpRequest<Buffer> requestBuffer = buildCallRequestBuffer(proxyRequest,body,apiConfig);
|
||||
try {
|
||||
if (circuitBreaker != null) {
|
||||
return breakerCall(circuitBreaker, proxyRequest,requestBuffer,body);
|
||||
@ -441,7 +442,7 @@ public class ReverseProxy implements HttpProxy {
|
||||
request.setTimeout(AppConfigHandler.getApicodeConfigTimeOut(key));
|
||||
Future<ProxyResponse> fut = proxyRequest.send(request);
|
||||
fut.onFailure(err -> {
|
||||
JsonObject json = SacErrorCode.returnErrorMsg(502);
|
||||
JsonObject json = AppUtils.getResponseJsonByGatewayError(GatewayError.BAD_GATEWAY);
|
||||
proxyRequest.response().release().setStatusCode(500).putHeader("content-type", "application/json")
|
||||
.putHeader(AppConfigHandler.sacResponseHeaderKey(), String.valueOf(502))
|
||||
.putHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(json.size())).setBody(Body.body(json.toBuffer()))
|
||||
|
@ -3,7 +3,7 @@ server:
|
||||
vertx:
|
||||
deploymentMode: 1 # 1:单机 2:集群
|
||||
isSSL: false # vertx https或者http启动, ssl 证书有过期时间
|
||||
rpcUri: /rpc
|
||||
rpcUri: /rpc.sac
|
||||
sacResponseHeaderKey: sacErrorCode
|
||||
environment: dev
|
||||
server:
|
||||
|
Loading…
x
Reference in New Issue
Block a user