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