package com.datasophon.api.configuration;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* Zuul 支持 websocket 的代理
*
*
*
* Created by zhenqin.
* User: zhenqin
* Date: 2023/3/17
* Time: 上午11:32
* Vendor: yiidata.com
*
*
*
* @author zhenqin
*/
@Component
@Slf4j
public class WebSocketProxyFilter extends ZuulFilter {
/**
* 所有 websocket 的特殊处理
*/
final static Map WEBSOCKET_ACTION_MAPPING = new ConcurrentHashMap<>();
/**
* 添加 WebSocket 地址
* @param path
* @param route
*/
public static void addWebSocketRouter(String path, ApiRoute route) {
WEBSOCKET_ACTION_MAPPING.put(path, route);
}
/**
* 过滤器类型
* pre 前置
* routing
* post 后置
* error
*
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 执行顺序
* 数值越小,优先级越高
*
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 执行条件
* true 开启, 执行 run 的特殊处理
* false 关闭,否则不需要特殊处理,直接代理
*
* @return
*/
@Override
public boolean shouldFilter() {
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
if(request == null) {
return false;
}
final String path = request.getServletPath();
final String connectionHeader = request.getHeader("Connection");
final String upgradeHeader = request.getHeader("Upgrade");
// 检验是不是 websocket 的链接, websocket 连接 Connection: Upgrade, Upgrade: websocket, Websocket, WebSocket
return StringUtils.equals("Upgrade", connectionHeader) && StringUtils.equalsIgnoreCase("websocket", upgradeHeader) && WEBSOCKET_ACTION_MAPPING.get(path) != null;
}
/**
* 动作(具体操作)
* 具体逻辑
*
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
final String path = request.getServletPath();
rc.addZuulRequestHeader("Connection", request.getHeader("Connection"));
rc.addZuulRequestHeader("Upgrade", request.getHeader("Upgrade"));
//过滤该请求,不进行路由
rc.setSendZuulResponse(false);
//返回对应http status状态码
rc.setResponseStatusCode(401);
//设置返回的内容
rc.setResponseBody("{'error':'token is empty'}");
final ApiRoute apiRoute = WEBSOCKET_ACTION_MAPPING.get(path);
log.info(path);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return apiRoute;
}
}