责任链模式

本文介绍了一个基于责任链模式的游戏网关代理系统的设计与实现。该系统通过一系列事件处理类串联起复杂的请求处理流程,包括参数预处理、签名验证、IP白名单检查等,并详细展示了如何通过回调机制协调各个处理环节。
摘要由CSDN通过智能技术生成

**

责任链模式

**

@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()+"]"));
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值