gpt4 book ai didi

java - 为什么 Tomcat websockets 不遵守 JVM 范围的 HTTP 代理设置?

转载 作者:行者123 更新时间:2023-11-28 22:27:28 25 4
gpt4 key购买 nike

(这是 Java 8 和 Tomcat 8)

我有一个简单的 websocket 客户端测试应用程序,我正在尝试针对 squid 代理进行测试。我正在使用 http[s].proxy[Host|Port] 系统属性在 JVM 范围内设置代理信息。

当我使用 Tyrus 实现 (tyrus-standalone-client-1.12.jar) 时,代理系统属性得到尊重(当然,然后我遇到了 wss URL 将不起作用,但这是一个不同的问题)。

但是,当我使用 Tomcat 实现 (tomcat-websocket.jar) 时,系统代理设置根据经验被忽略(我正在使用网络嗅探器,我发现数据包不会发送到代理,而使用 Tyrus 我确实看到数据包进入代理)。

我查看了 org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer() 的源代码,它确实看起来像是在获取代理信息并使用它:

    // Check to see if a proxy is configured. Javadoc indicates return value
// will never be null
List<Proxy> proxies = ProxySelector.getDefault().select(proxyPath);
Proxy selectedProxy = null;
for (Proxy proxy : proxies) {
if (proxy.type().equals(Proxy.Type.HTTP)) {
sa = proxy.address();
if (sa instanceof InetSocketAddress) {
InetSocketAddress inet = (InetSocketAddress) sa;
if (inet.isUnresolved()) {
sa = new InetSocketAddress(inet.getHostName(), inet.getPort());
}
}
selectedProxy = proxy;
break;
}
}

我将查找代理的那段代码放入我的测试程序中,以查看它发现了什么,正如您将看到的,它会获取代理信息。所以我不知道为什么 Tomcat websockets 不遵守这些属性。

我的测试应用:

import javax.websocket.*;

import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

/**
* This class is adapted from http://stackoverflow.com/a/26454417/411393 which
* is an answer to http://stackoverflow.com/questions/26452903/javax-websocket-client-simple-example/
*/
public class WebsocketTestApp
{
public static void main(String[] args) {
try {
// Determine where to connect
final URI servicePath;
if ((args.length != 0) && "secure".equals(args[0])) {
// servicePath = new URI("wss://real.okcoin.cn:10440/websocket/okcoinapi");
servicePath = new URI("wss://echo.websocket.org/");
}
else {
servicePath = new URI("ws://echo.websocket.org/");
}

// See what Java thinks the proxy for the service is.
URI proxyPath = buildProxyPath(servicePath);
System.out.println("service path: " + servicePath);
System.out.println("proxy path: " + proxyPath);

// This line is copied from the source to org.apache.tomcat.websocket.WsWebSocketContainer (approx line 254)
List<Proxy> proxies = ProxySelector.getDefault().select(proxyPath);
for (Proxy proxy : proxies) {
System.out.println(proxy.toString());
}

// open websocket
final WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint(servicePath);

// add listener
clientEndPoint.addMessageHandler(System.out::println);

// send message to websocket
clientEndPoint.sendMessage("{'event':'addChannel','channel':'ok_btccny_ticker'}");

// wait 2 seconds for messages from websocket
Thread.sleep(2000);
}
catch (InterruptedException ex) {
System.err.println("InterruptedException exception: " + ex.getMessage());
}
catch (URISyntaxException ex) {
System.err.println("URISyntaxException exception: " + ex.getMessage());
}
}

// This is essentially copied from the source to org.apache.tomcat.websocket.WsWebSocketContainer (approx lines 230-241)
private static URI buildProxyPath(URI path) {
URI proxyPath;

// Validate scheme (and build proxyPath)
String scheme = path.getScheme();
if ("ws".equalsIgnoreCase(scheme)) {
proxyPath = URI.create("http" + path.toString().substring(2));
}
else if ("wss".equalsIgnoreCase(scheme)) {
proxyPath = URI.create("https" + path.toString().substring(3));
}
else {
throw new IllegalArgumentException("wsWebSocketContainer.pathWrongScheme: " + scheme);
}

return proxyPath;
}

@ClientEndpoint
public static class WebsocketClientEndpoint
{

Session userSession = null;
private MessageHandler messageHandler;

public WebsocketClientEndpoint(URI endpointURI) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
//((ClientManager)container).getProperties().put(ClientProperties.PROXY_URI, "http://172.16.99.15:3128");
container.connectToServer(this, endpointURI);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* Callback hook for Connection open events.
*
* @param userSession the userSession which is opened.
*/
@OnOpen
public void onOpen(Session userSession) {
System.out.println("opening websocket");
this.userSession = userSession;
}

/**
* Callback hook for Connection close events.
*
* @param userSession the userSession which is getting closed.
* @param reason the reason for connection close
*/
@OnClose
public void onClose(Session userSession, CloseReason reason) {
System.out.println("closing websocket");
this.userSession = null;
}

/**
* Callback hook for Message Events. This method will be invoked when a client send a message.
*
* @param message The text message
*/
@OnMessage
public void onMessage(String message) {
if (this.messageHandler != null) {
this.messageHandler.handleMessage(message);
}
}

/**
* register message handler
*
* @param msgHandler
*/
public void addMessageHandler(MessageHandler msgHandler) {
this.messageHandler = msgHandler;
}

/**
* Send a message.
*
* @param message
*/
public void sendMessage(String message) {
this.userSession.getAsyncRemote().sendText(message);
}

/**
* Message handler.
*/
@FunctionalInterface
public static interface MessageHandler
{
public void handleMessage(String message);
}
}
}

当我运行它时,输出是:

service path: ws://echo.websocket.org/
proxy path: http://echo.websocket.org/
HTTP @ 172.16.99.15:3128
opening websocket
{'event':'addChannel','channel':'ok_btccny_ticker'}

因此它打印出正确的代理信息,使用与 WsWebSocketContainer.connectToServer() 相同的查找代码,但代理信息未被接受,而是建立了直接连接。

这是 Tomcat 实现中的一些奇怪错误吗? Tomcat 实现是否已知会忽略代理属性设置?


更新:

我还将代码放入正在运行的 Tomcat 中的一个快速但肮脏的 servlet 中,同样的事情发生了。虽然 Tomcat 总体上似乎遵守这些设置(在 Tomcat 中调用 java.net.URL.openStream() 遵守这些设置),但 websocket 的东西再次拒绝遵守这些设置。因此,不管是什么原因造成的,不是代码是独立运行的,而不是在 Tomcat 容器中运行的。

最佳答案

原因是我是个白痴。

我正在运行 Tomcat 8.0.23(这是我的外部需求)。

不过,我忘记了,把源码下载到了8.0.33

我已经返回并将源代码下载到 8.0.23,但我在问题中提到的代理查找代码似乎不存在。

关于java - 为什么 Tomcat websockets 不遵守 JVM 范围的 HTTP 代理设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36941483/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com