JDK 25 HttpClient 不使用 ProxySelector 的 SOCKS 路由
选择一个真正支持 SOCKS 的 Java HTTP 传输,而不是只依赖 ProxySelector 返回的类型。
Java 的代理对象只描述一条路由。究竟能使用哪类路由,仍由网络客户端自己决定。当可用端点使用 SOCKS、而应用使用 java.net.http.HttpClient 时,这一点很重要。
在本文考察的 JDK 25 实现中,HTTP 客户端的请求代码会接受选择器给出的 HTTP 候选,但 SOCKS 候选并不会让它执行 SOCKS 协商;实现可能在没有代理的情况下继续。因此,仅凭一次成功的响应,不足以证明自定义选择器的 SOCKS 条目被使用了。
先选择传输方式
对于已有的基于 URLConnection 的应用,可以在打开连接时把受支持的显式代理交给协议处理器:
Proxy route = new Proxy(Proxy.Type.SOCKS,
new InetSocketAddress("proxy.example", 1080));
URLConnection connection = URI.create("https://service.example/")
.toURL().openConnection(route);
connection.setConnectTimeout(5000);
connection.setReadTimeout(15000);
对于获准的公开目标测试,请使用你所选服务或 SOCKS 代理列表 中匹配的 SOCKS 端点。这是另一种客户端 API,而不是 HttpClient.Builder.proxy 的另一种写法。请保留目标 URL,以便 HTTPS 继续识别预期的网站。
必须保留 java.net.http 的应用,可以改用兼容的 HTTP 代理端点,包括负责后续 SOCKS 连接的已批准适配器。这会增加一个真实组件和又一道访问边界;把 8080 端口改成 1080 并不能提供这种转换。
让选择与采用都可见
既记录选择器的结果,也记录客户端实际打开的连接。前者描述策略输出,后者确定实现是否采用了它。
把结论绑定到实际使用的运行时和传输上。某个套接字实现所使用的 JVM SOCKS 属性,并不保证每个 HTTP 库都会查阅它们。当路由是强制要求时,应在接受看似成功的直连请求之前识别出不受支持的代理类型。