**
责任链模式
**
@Service
@DefaultCmd
public class ProxyCmd implements BaseCmd{
private static Logger logger=LogManager.getLogger(ProxyCmd.class);
@Autowired
private Event preDeal;
@Autowired
private Event checkSign;
@Autowired
private Event checkIp;
@Autowired
private Event paramTranServer;
@Autowired
private Event paramTranAccount;
@Autowired
private Event paramTranAppId;
@Autowired
private Event signAgain;
@Autowired
private Event warpProxyUrl;
@Autowired
private Event warpResp;
@Autowired
private Event tranRespServer;
@Autowired
private Event tranRespAccount;
@Autowired
private Event copyParam;
@Autowired
private Event stardardOldResp;
@Autowired
private Event setFromApp;
@Autowired
private Event getReqUdbidInfo;
@Autowired
private Event guestDeal;
//网关校验参数
@Override
public void deal(ChannelHandlerContextWarp ctx,FullHttpRequestWarp request){
ProxyInfo proxyInfo = new ProxyInfo(request);
logger.debug(“requestid[{}]postcontent[{}]”,proxyInfo.getProxyInfoId(),StringUtil.cut(request.getPostContent(), 255));
pre(ctx,proxyInfo);
}
/**
* 前期准备工作处理,处理完成后,进入请求参数转换
* @return
*/
private void pre(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
preDeal.deal(ctx, proxyInfo, new Callback() {
@Override
public void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo,Object ext) {
setFromApp(ctx, proxyInfo);
}
},null);
}
/**
* 设置fromApp
* @param ctx
* @param proxyInfo
*/
private void setFromApp(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
setFromApp.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
checkIp(ctx, proxyInfo);
}
}, null);
}
/**
* 验证ip
* @param ctx
* @param proxyInfo
*/
private void checkIp(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
checkIp.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo,Object ext) {
checkSign(ctx,proxyInfo);
}
},null);
}
/**
* 验证签名
* @param ctx
* @param proxyInfo
*/
private void checkSign(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
checkSign.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo,Object ext) {
copyParamBeforeTranParam(ctx, proxyInfo);
}
},null);
}
/**
* 拷贝转换前的参数
* @param ctx
* @param proxyInfo
*/
private void copyParamBeforeTranParam(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
copyParam.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
getReqUdbidInfo(ctx,proxyInfo);
}
}, true);
}
private void getReqUdbidInfo(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
logger.debug("requestid[{}] start getReqUdbidInfo[{}]",proxyInfo.getProxyInfoId(),StringUtil.cut(proxyInfo.getUri(), 255));
getReqUdbidInfo.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
logger.debug("requestid[{}] end getReqUdbidInfo[{}]",proxyInfo.getProxyInfoId(),StringUtil.cut(proxyInfo.getUri(), 255));
guestDeal(ctx, proxyInfo);
}
}, null);
}
private void guestDeal(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
guestDeal.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
tranParamAppId(ctx, proxyInfo);
}
}, null);
}
/**
* 请求参数处理
* 转换参数内的区服和账号
*/
private void tranParamAppId(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
paramTranAppId.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo,Object ext) {
tranServerParam(ctx,proxyInfo);
}
},null);
}
/**
* 请求参数处理
* 转换参数内的区服和账号
*/
private void tranServerParam(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
paramTranServer.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo,Object ext) {
tranParamAccount(ctx, proxyInfo);
}
},null);
}
/**
* 请求参数处理
* 转换参数内的区服和账号
*/
private void tranParamAccount(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
paramTranAccount.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo,Object ext) {
copyParamAfterTranParam(ctx, proxyInfo);
}
},null);
}
/**
* 拷贝转换后的参数
* @param ctx
* @param proxyInfo
*/
private void copyParamAfterTranParam(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
copyParam.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
signAgain(ctx, proxyInfo);
}
}, false);
}
/**
* 二次签名
* @param proxyInfo
*/
private void signAgain(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
signAgain.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo,Object ext) {
warpProxyUrl(ctx,proxyInfo);
}
},null);
}
/**
* 封装url
* @param proxyInfo
*/
private void warpProxyUrl(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo){
warpProxyUrl.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo,Object ext){
URL url=(URL) ext;
ProxyInterface proxyInterface=proxyInfo.getProxyInterface();
if(proxyInterface.getIs302()){
Callback.forward302(ctx, proxyInfo, url);
}else{
sendProxy(ctx,proxyInfo,url);
}
}
},null);
}
/** 发送请求
* @param url
* @param proxyInfo
*/
private void sendProxy(final ChannelHandlerContextWarp ctx,final ProxyInfo proxyInfo,final URL url){
ClientRespCallBack clientRespCallBack = new ClientRespCallBack(url) {
@Override
public void doSuccess(String content) {
//日志
logger.debug("requestid[{}]time[{}]proxyresp[{}]",proxyInfo.getProxyInfoId(),getTime(),StringUtil.cut(content, 255));
if(content==null){
content="";
}
content = content.endsWith("\n") ? content.substring(0, content.length() - 1) : content;
boolean isDealResp=isNeedDealResp(proxyInfo);
if(isDealResp){
stardardOldResp(ctx,proxyInfo,content);
}else{
Callback.write(ctx, proxyInfo, content);
}
}
@Override
public void doFail(Throwable throwable) {
//日志
if(throwable instanceof ReaderTimeoutException){
Callback.writeFail(ctx, proxyInfo, new CodeException(RCODE.RESP_ERROR.getCode(), "网关代理响应超时,请求地址:"+throwable.getMessage()));
return;
}
if(throwable instanceof RespStatusException){
Callback.writeFail(ctx, proxyInfo, new CodeException(RCODE.RESP_ERROR.getCode(), "网关代理响应码非200,响应摘要:"+StringUtil.cut(throwable.getMessage(), 255)));
return;
}
if(throwable instanceof ConnectTimeoutException){
Callback.writeFail(ctx, proxyInfo, new CodeException(RCODE.CONNECT_TIMEOUT.getCode(), "网关代理请求连接超时:"+throwable.getMessage()));
return;
}
if(throwable instanceof ResolverDomainNoAnswerException){
Callback.writeFail(ctx, proxyInfo, new CodeException(RCODE.ERROR.getCode(), "网关代理请求域名无法解析:"+throwable.getMessage()));
return;
}
logger.error("requestid[{}] proxy fail time[{}],cause[{}]",proxyInfo.getProxyInfoId(),getTime(),throwable.getMessage(),throwable);
Callback.writeFail(ctx, proxyInfo, new CodeException(RCODE.ERROR.getCode(), "网关代理请求出现异常"));
return;
}
};
if(logger.isDebugEnabled()){
String logStr=url.toString();
logStr=logStr.length()>255?logStr.substring(0, 255):logStr;
logger.debug("requestid[{}]proxyurl[{}]",proxyInfo.getProxyInfoId(),logStr);
}
boolean isPost = proxyInfo.getProxyInterface().getIsPost();
AsynClient.lazyAsynRequest(url, isPost, clientRespCallBack,GpDomainResolverCallback.getInstance());
}
/**
* 旧接口响应兼容
* @param ctx
* @param proxyInfo
* @param content
*/
private void stardardOldResp(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo,String content){
stardardOldResp.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
warpResp(ctx,proxyInfo,ext);
}
}, content);
}
/**
* 封装响应
* @param ctx
* @param proxyInfo
* @param ext
*/
private void warpResp(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo,Object ext){
warpResp.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
tranRespServer(ctx, proxyInfo, (RespData)ext);
}
}, ext);
}
/**
* 转换响应中的server
* @param ctx
* @param proxyInfo
* @param respData
*/
private void tranRespServer(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo,RespData respData){
tranRespServer.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
tranRespAccount(ctx,proxyInfo,(RespData) ext);
}
}, respData);
}
/**
* 转换响应中的account
* @param ctx
* @param proxyInfo
* @param respData
*/
private void tranRespAccount(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo,RespData respData){
tranRespAccount.deal(ctx, proxyInfo, new Callback() {
@Override
protected void doSuccess(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Object ext) {
Callback.write(ctx, proxyInfo, (RespData) ext);
}
}, respData);
}
/**
* 判断是否需要对resp内容处理
* @param proxyInfo
* @return
*/
private static boolean isNeedDealResp(ProxyInfo proxyInfo){
AppInterface appInterface=proxyInfo.getAppInterface();
if(appInterface.getIsOld()){
return true;
}
ProxyInterface proxyInterface=proxyInfo.getProxyInterface();
if(proxyInterface.getIsTransRespAccount()){
return true;
}
if(proxyInterface.getIsTransRespServer()){
return true;
}
return false;
}
}
//实现接口公告hander类
public interface Event {
public void deal(ChannelHandlerContextWarp ctx,ProxyInfo proxyInfo,Callback callback,Object ext);
}
//具体处理逻辑
@Service
public class CheckIp implements Event{
private static Logger logger = LogManager.getLogger(CheckIp.class);
@Autowired
private WhiteIpService whiteIpService;
@Override
public void deal(ChannelHandlerContextWarp ctx, ProxyInfo proxyInfo, Callback callback,Object ext) {
ProxyInterface proxyInterface=proxyInfo.getProxyInterface();
if(!proxyInterface.getIsLimitIp()){
callback.success(ctx, proxyInfo,null);
return;
}
String clientIp = proxyInfo.getClientIp();
if("127.0.0.1".equals(clientIp)){
callback.success(ctx, proxyInfo,null);
return;
}
WhiteIp whiteIp=null;
try{
whiteIp=whiteIpService.get(proxyInfo.getAppId(), proxyInterface.getId());
}catch(Throwable e){
//ip查询出现异常,属于非主要业务,认为ip通过
logger.error("网关查询appId[{}]接口[{}]对应白名单出现异常",proxyInfo.getAppId(),proxyInfo.getPath(),e);
callback.fail(ctx, proxyInfo, new CodeException(RCODE.PROXY_CONFIG.getCode(), "网关查询appId["+proxyInfo.getAppId()+"]接口["+proxyInfo.getPath()+"]对应白名单出现异常"));
return;
}
if(whiteIp==null||StringUtil.isEmpty(whiteIp.getIps())){
callback.fail(ctx, proxyInfo,new CodeException(RCODE.IP_FAIL.getCode(), "网关禁止IP["+clientIp+"]访问接口["+proxyInfo.getPath()+"]"));
return;
}
String ips = "|" + whiteIp.getIps() + "|";
boolean flag=ips.contains("|" + clientIp + "|");
if(flag){
callback.success(ctx, proxyInfo,null);
return;
}
callback.fail(ctx,proxyInfo,new CodeException(RCODE.IP_FAIL.getCode(), "网关禁止IP["+clientIp+"]访问接口["+proxyInfo.getPath()+"]"));
}
}