forked from fanruan/design
Browse Source
Merge in DESIGN/design from ~HADES/design:feature/x to feature/x * commit '596486c056cf80434832ea98532658dcdd6158b8': REPORT-62882 websocket攻坚落地(远程设计适配)feature/x
Hades
3 years ago
6 changed files with 269 additions and 80 deletions
@ -0,0 +1,98 @@ |
|||||||
|
package com.fr.design.mainframe.socketio; |
||||||
|
|
||||||
|
import com.fr.decision.webservice.utils.DecisionServiceConstants; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.report.RemoteDesignConstants; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.third.org.apache.http.conn.ssl.NoopHostnameVerifier; |
||||||
|
import com.fr.third.org.apache.http.conn.ssl.TrustSelfSignedStrategy; |
||||||
|
import com.fr.third.org.apache.http.ssl.SSLContexts; |
||||||
|
import com.fr.web.WebSocketConfig; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.Workspace; |
||||||
|
import com.fr.workspace.base.WorkspaceConstants; |
||||||
|
import com.fr.workspace.connect.WorkspaceConnection; |
||||||
|
import com.fr.workspace.connect.WorkspaceConnectionInfo; |
||||||
|
import io.socket.client.IO; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.net.URL; |
||||||
|
import java.security.KeyStore; |
||||||
|
import java.util.Arrays; |
||||||
|
import javax.net.ssl.SSLContext; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 11.0 |
||||||
|
* Created by hades on 2021/11/29 |
||||||
|
*/ |
||||||
|
public abstract class AbstractSocketConfig { |
||||||
|
|
||||||
|
public static final String HTTPS = "https"; |
||||||
|
public static final String HTTP = "http"; |
||||||
|
|
||||||
|
/** |
||||||
|
* 当前webSocket选择的协议 |
||||||
|
*/ |
||||||
|
private String currentProtocol; |
||||||
|
|
||||||
|
protected abstract String getCurrentProtocolFromUrl(URL url); |
||||||
|
|
||||||
|
protected abstract Integer[] getPorts(); |
||||||
|
|
||||||
|
public IO.Options createOptions() { |
||||||
|
IO.Options options = new IO.Options(); |
||||||
|
options.path = WebSocketConfig.getInstance().getSocketContext(); |
||||||
|
try { |
||||||
|
if (ComparatorUtils.equals(currentProtocol, HTTPS)) { |
||||||
|
options.sslContext = getSSLContext(); |
||||||
|
options.hostnameVerifier = NoopHostnameVerifier.INSTANCE; |
||||||
|
options.secure = true; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
return options; |
||||||
|
} |
||||||
|
|
||||||
|
private SSLContext getSSLContext() throws Exception { |
||||||
|
WorkspaceConnectionInfo connection = DesignerSocketIO.getConnectionInfo(); |
||||||
|
String certPath = connection.getCertPath(); |
||||||
|
String certSecretKey = connection.getCertSecretKey(); |
||||||
|
if (StringUtils.isBlank(certPath) || StringUtils.isBlank(certSecretKey)) { |
||||||
|
return SSLContexts.createDefault(); |
||||||
|
} |
||||||
|
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
||||||
|
try (FileInputStream keystore = new FileInputStream(new File(certPath))) { |
||||||
|
trustStore.load(keystore, certSecretKey.toCharArray()); |
||||||
|
} |
||||||
|
return SSLContexts.custom() |
||||||
|
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getUri() throws IOException { |
||||||
|
Workspace current = WorkContext.getCurrent(); |
||||||
|
URL url = new URL(current.getPath()); |
||||||
|
Integer[] ports = getPorts(); |
||||||
|
WorkspaceConnection connection = current.getConnection(); |
||||||
|
currentProtocol = getCurrentProtocolFromUrl(url); |
||||||
|
String[] result = new String[ports.length]; |
||||||
|
for (int i = 0; i < ports.length; i++) { |
||||||
|
result[i] = String.format("%s://%s:%s%s?%s=%s&%s=%s", |
||||||
|
currentProtocol, |
||||||
|
url.getHost(), |
||||||
|
ports[i], |
||||||
|
WorkspaceConstants.WS_NAMESPACE, |
||||||
|
DecisionServiceConstants.WEB_SOCKET_TOKEN_NAME, |
||||||
|
connection.getToken(), |
||||||
|
RemoteDesignConstants.USER_LOCK_ID, |
||||||
|
connection.getId()); |
||||||
|
} |
||||||
|
FineLoggerFactory.getLogger().info("Available ports: {}, current Protocol: {}", Arrays.toString(ports), currentProtocol); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.fr.design.mainframe.socketio; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 11.0 |
||||||
|
* Created by hades on 2021/11/29 |
||||||
|
*/ |
||||||
|
public class ConnectionInfo { |
||||||
|
|
||||||
|
private final String uri; |
||||||
|
|
||||||
|
private final AbstractSocketConfig socketConfig; |
||||||
|
|
||||||
|
public ConnectionInfo(String uri, AbstractSocketConfig socketConfig) { |
||||||
|
this.uri = uri; |
||||||
|
this.socketConfig = socketConfig; |
||||||
|
} |
||||||
|
|
||||||
|
public String getUri() { |
||||||
|
return uri; |
||||||
|
} |
||||||
|
|
||||||
|
public AbstractSocketConfig getSocketConfig() { |
||||||
|
return socketConfig; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
package com.fr.design.mainframe.socketio; |
||||||
|
|
||||||
|
import com.fr.rpc.ExceptionHandler; |
||||||
|
import com.fr.rpc.RPCInvokerExceptionInfo; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.socket.SocketInfoOperator; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 11.0 |
||||||
|
* Created by hades on 2021/11/29 |
||||||
|
*/ |
||||||
|
public class ConnectionInfoFactory { |
||||||
|
|
||||||
|
public static ConnectionInfo[] createConnectionInfo() throws IOException { |
||||||
|
|
||||||
|
List<ConnectionInfo> connectionInfos = new ArrayList<>(); |
||||||
|
boolean useJavaxWebsocket = WorkContext.getCurrent().get(SocketInfoOperator.class, new ExceptionHandler() { |
||||||
|
@Override |
||||||
|
public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
}).isUseJavaxWebsocket(); |
||||||
|
if (useJavaxWebsocket) { |
||||||
|
// 新方案配置
|
||||||
|
addConfig(new ContainerSocketConfig(), connectionInfos); |
||||||
|
} |
||||||
|
// 老方案配置
|
||||||
|
addConfig(new IOSocketConfig(), connectionInfos); |
||||||
|
return connectionInfos.toArray(new ConnectionInfo[0]); |
||||||
|
} |
||||||
|
|
||||||
|
private static void addConfig(AbstractSocketConfig config, List<ConnectionInfo> connectionInfos) throws IOException { |
||||||
|
String[] configUri = config.getUri(); |
||||||
|
for (String uri : configUri) { |
||||||
|
connectionInfos.add(new ConnectionInfo(uri, config)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
package com.fr.design.mainframe.socketio; |
||||||
|
|
||||||
|
import com.fr.base.FRContext; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.rpc.ExceptionHandler; |
||||||
|
import com.fr.rpc.RPCInvokerExceptionInfo; |
||||||
|
import com.fr.stable.ArrayUtils; |
||||||
|
import com.fr.web.WebSocketConfig; |
||||||
|
import com.fr.web.socketio.WebSocketConstants; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.socket.SocketInfoOperator; |
||||||
|
import io.socket.client.IO; |
||||||
|
import io.socket.engineio.client.transports.Polling; |
||||||
|
import io.socket.engineio.client.transports.WebSocket; |
||||||
|
import java.net.MalformedURLException; |
||||||
|
import java.net.URL; |
||||||
|
|
||||||
|
/** |
||||||
|
* 连接基于容器端口的WebSocket |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 11.0 |
||||||
|
* Created by hades on 2021/11/29 |
||||||
|
*/ |
||||||
|
public class ContainerSocketConfig extends AbstractSocketConfig { |
||||||
|
|
||||||
|
private static final int DEFAULT_SERVER_PORT = 80; |
||||||
|
|
||||||
|
@Override |
||||||
|
public IO.Options createOptions() { |
||||||
|
IO.Options options = super.createOptions(); |
||||||
|
options.transports = new String[]{WebSocket.NAME, Polling.NAME}; |
||||||
|
options.path = String.format("/%s%s", FRContext.getCommonOperator().getAppName(), WebSocketConstants.WEBSOCKET_PATH); |
||||||
|
return options; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String getCurrentProtocolFromUrl(URL url) { |
||||||
|
return url.getProtocol(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Integer[] getPorts() { |
||||||
|
Integer[] ports = WebSocketConfig.getInstance().getPort(); |
||||||
|
int serverPort = DEFAULT_SERVER_PORT; |
||||||
|
URL url = null; |
||||||
|
try { |
||||||
|
url = new URL(WorkContext.getCurrent().getPath()); |
||||||
|
} catch (MalformedURLException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
if (url != null && url.getPort() > 0) { |
||||||
|
serverPort = url.getPort(); |
||||||
|
} |
||||||
|
return ArrayUtils.insert(0, ports, serverPort); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package com.fr.design.mainframe.socketio; |
||||||
|
|
||||||
|
import com.fr.web.WebSocketConfig; |
||||||
|
import com.fr.web.socketio.WebSocketProtocol; |
||||||
|
import io.socket.client.IO; |
||||||
|
import java.net.URL; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 11.0 |
||||||
|
* Created by hades on 2021/11/29 |
||||||
|
*/ |
||||||
|
public class IOSocketConfig extends AbstractSocketConfig { |
||||||
|
|
||||||
|
@Override |
||||||
|
public IO.Options createOptions() { |
||||||
|
IO.Options options = super.createOptions(); |
||||||
|
options.path = WebSocketConfig.getInstance().getSocketContext(); |
||||||
|
return options; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String getCurrentProtocolFromUrl(URL url) { |
||||||
|
// 服务器配置https webSocket可能是wss也可能是ws webSocket的协议可以单独配置
|
||||||
|
WebSocketProtocol webSocketProtocol = WebSocketConfig.getInstance().getProtocol(); |
||||||
|
String currentProtocol = webSocketProtocol == WebSocketProtocol.PLAIN ? HTTP : HTTPS; |
||||||
|
if (WebSocketConfig.getInstance().isUsingProxy()) { |
||||||
|
// 如果配置了代理服务器跟随服务器协议
|
||||||
|
currentProtocol = url.getProtocol(); |
||||||
|
} |
||||||
|
return currentProtocol; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Integer[] getPorts() { |
||||||
|
return WebSocketConfig.getInstance().getAvailablePorts(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue