added proxy feature

So now, it's support http, socks4 and socks5 proxys
This commit is contained in:
AzZu 2018-05-06 20:34:17 +03:00
parent 95dd4e3a3f
commit 346a9dc045
8 changed files with 252 additions and 7 deletions

View File

@ -33,6 +33,7 @@ import org.telegram.telegrambots.updateshandlers.SentCallback;
import java.io.IOException;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
@ -56,7 +57,7 @@ public abstract class DefaultAbsSender extends AbsSender {
protected final ExecutorService exe;
private final ObjectMapper objectMapper = new ObjectMapper();
private final DefaultBotOptions options;
private volatile CloseableHttpClient httpclient;
private volatile CloseableHttpClient httpClient;
private volatile RequestConfig requestConfig;
protected DefaultAbsSender(DefaultBotOptions options) {
@ -64,10 +65,10 @@ public abstract class DefaultAbsSender extends AbsSender {
this.exe = Executors.newFixedThreadPool(options.getMaxThreads());
this.options = options;
httpclient = TelegramHttpClientBuilder.build(options);
httpClient = TelegramHttpClientBuilder.build(options);
configureHttpContext();
requestConfig = options.getRequestConfig();
if (requestConfig == null) {
requestConfig = RequestConfig.copy(RequestConfig.custom().build())
.setSocketTimeout(SOCKET_TIMEOUT)
@ -76,6 +77,22 @@ public abstract class DefaultAbsSender extends AbsSender {
}
}
private void configureHttpContext() {
if (options.getProxyType() != DefaultBotOptions.ProxyType.NO_PROXY) {
InetSocketAddress socksaddr = new InetSocketAddress(options.getProxyHost(), options.getProxyPort());
options.getHttpContext().setAttribute("socketAddress", socksaddr);
}
if (options.getProxyType() == DefaultBotOptions.ProxyType.SOCKS4) {
options.getHttpContext().setAttribute("socksVersion", 4);
}
if (options.getProxyType() == DefaultBotOptions.ProxyType.SOCKS5) {
options.getHttpContext().setAttribute("socksVersion", 5);
}
}
/**
* Returns the token of the bot to be able to perform Telegram Api Requests
* @return Token of the bot
@ -734,7 +751,7 @@ public abstract class DefaultAbsSender extends AbsSender {
}
private String sendHttpPostRequest(HttpPost httppost) throws IOException {
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
try (CloseableHttpResponse response = httpClient.execute(httppost, options.getHttpContext())) {
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
return EntityUtils.toString(buf, StandardCharsets.UTF_8);

View File

@ -1,8 +1,8 @@
package org.telegram.telegrambots.bots;
import org.apache.http.HttpHost;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.protocol.HttpContext;
import org.telegram.telegrambots.ApiConstants;
import org.telegram.telegrambots.generics.BotOptions;
import org.telegram.telegrambots.updatesreceivers.ExponentialBackOff;
@ -18,14 +18,27 @@ import java.util.List;
public class DefaultBotOptions implements BotOptions {
private int maxThreads; ///< Max number of threads used for async methods executions (default 1)
private RequestConfig requestConfig;
private volatile HttpContext httpContext;
private ExponentialBackOff exponentialBackOff;
private Integer maxWebhookConnections;
private String baseUrl;
private List<String> allowedUpdates;
private ProxyType proxyType;
private String proxyHost;
private int proxyPort;
public enum ProxyType {
NO_PROXY,
HTTP,
SOCKS4,
SOCKS5
}
public DefaultBotOptions() {
maxThreads = 1;
baseUrl = ApiConstants.BASE_URL;
httpContext = HttpClientContext.create();
proxyType = ProxyType.NO_PROXY;
}
@Override
@ -53,6 +66,14 @@ public class DefaultBotOptions implements BotOptions {
return maxWebhookConnections;
}
public HttpContext getHttpContext() {
return httpContext;
}
public void setHttpContext(HttpContext httpContext) {
this.httpContext = httpContext;
}
public void setMaxWebhookConnections(Integer maxWebhookConnections) {
this.maxWebhookConnections = maxWebhookConnections;
}
@ -85,4 +106,27 @@ public class DefaultBotOptions implements BotOptions {
this.exponentialBackOff = exponentialBackOff;
}
public ProxyType getProxyType() {
return proxyType;
}
public void setProxyType(ProxyType proxyType) {
this.proxyType = proxyType;
}
public String getProxyHost() {
return proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public int getProxyPort() {
return proxyPort;
}
public void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
}
}

View File

@ -1,10 +1,20 @@
package org.telegram.telegrambots.facilities;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.facilities.proxysocketfactorys.HttpConnectionSocketFactory;
import org.telegram.telegrambots.facilities.proxysocketfactorys.HttpSSLConnectionSocketFactory;
import org.telegram.telegrambots.facilities.proxysocketfactorys.SocksSSLConnectionSocketFactory;
import org.telegram.telegrambots.facilities.proxysocketfactorys.SocksConnectionSocketFactory;
import java.util.concurrent.TimeUnit;
@ -16,9 +26,30 @@ public class TelegramHttpClientBuilder {
public static CloseableHttpClient build(DefaultBotOptions options) {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create()
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.setConnectionManager(createConnectionManager(options))
.setConnectionTimeToLive(70, TimeUnit.SECONDS)
.setMaxConnTotal(100);
return httpClientBuilder.build();
}
private static HttpClientConnectionManager createConnectionManager(DefaultBotOptions options) {
Registry<ConnectionSocketFactory> registry;
switch (options.getProxyType()) {
case NO_PROXY:
return null;
case HTTP:
registry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", new HttpConnectionSocketFactory())
.register("https", new HttpSSLConnectionSocketFactory(SSLContexts.createSystemDefault())).build();
return new PoolingHttpClientConnectionManager(registry);
case SOCKS4:
case SOCKS5:
registry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", new SocksConnectionSocketFactory())
.register("https", new SocksSSLConnectionSocketFactory(SSLContexts.createSystemDefault())).build();
return new PoolingHttpClientConnectionManager(registry);
}
return null;
}
}

View File

@ -0,0 +1,33 @@
package org.telegram.telegrambots.facilities.proxysocketfactorys;
import org.apache.http.HttpHost;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.protocol.HttpContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
public class HttpConnectionSocketFactory extends PlainConnectionSocketFactory {
@Override
public Socket createSocket(final HttpContext context) throws IOException {
InetSocketAddress socketAddress = (InetSocketAddress) context.getAttribute("socketAddress");
Proxy proxy = new Proxy(Proxy.Type.HTTP, socketAddress);
return new Socket(proxy);
}
@Override
public Socket connectSocket(
int connectTimeout,
Socket socket,
HttpHost host,
InetSocketAddress remoteAddress,
InetSocketAddress localAddress,
HttpContext context) throws IOException {
String hostName = host.getHostName();
int port = remoteAddress.getPort();
InetSocketAddress unresolvedRemote = InetSocketAddress.createUnresolved(hostName, port);
return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
}
}

View File

@ -0,0 +1,40 @@
package org.telegram.telegrambots.facilities.proxysocketfactorys;
import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.protocol.HttpContext;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
public class HttpSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
public HttpSSLConnectionSocketFactory(final SSLContext sslContext) {
super(sslContext, new NoopHostnameVerifier());
}
@Override
public Socket createSocket(final HttpContext context) throws IOException {
InetSocketAddress socketAddress = (InetSocketAddress) context.getAttribute("socketAddress");
Proxy proxy = new Proxy(Proxy.Type.HTTP, socketAddress);
return new Socket(proxy);
}
@Override
public Socket connectSocket(
int connectTimeout,
Socket socket,
HttpHost host,
InetSocketAddress remoteAddress,
InetSocketAddress localAddress,
HttpContext context) throws IOException {
String hostName = host.getHostName();
int port = remoteAddress.getPort();
InetSocketAddress unresolvedRemote = InetSocketAddress.createUnresolved(hostName, port);
return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
}
}

View File

@ -0,0 +1,37 @@
package org.telegram.telegrambots.facilities.proxysocketfactorys;
import org.apache.http.HttpHost;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.protocol.HttpContext;
import sun.net.SocksProxy;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
public class SocksConnectionSocketFactory extends PlainConnectionSocketFactory {
@Override
public Socket createSocket(final HttpContext context) throws IOException {
InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socketAddress");
int socksVersion = (Integer) context.getAttribute("socksVersion");
Proxy proxy = SocksProxy.create(socksaddr, socksVersion);
return new Socket(proxy);
}
@Override
public Socket connectSocket(
int connectTimeout,
Socket socket,
HttpHost host,
InetSocketAddress remoteAddress,
InetSocketAddress localAddress,
HttpContext context) throws IOException {
String hostName = host.getHostName();
int port = remoteAddress.getPort();
InetSocketAddress unresolvedRemote = InetSocketAddress.createUnresolved(hostName, port);
return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
}
}

View File

@ -0,0 +1,43 @@
package org.telegram.telegrambots.facilities.proxysocketfactorys;
import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.protocol.HttpContext;
import sun.net.SocksProxy;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
public class SocksSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
public SocksSSLConnectionSocketFactory(final SSLContext sslContext) {
super(sslContext, new NoopHostnameVerifier());
}
@Override
public Socket createSocket(final HttpContext context) throws IOException {
InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socketAddress");
int socksVersion = (Integer) context.getAttribute("socksVersion");
Proxy proxy = SocksProxy.create(socksaddr, socksVersion);
return new Socket(proxy);
}
@Override
public Socket connectSocket(
int connectTimeout,
Socket socket,
HttpHost host,
InetSocketAddress remoteAddress,
InetSocketAddress localAddress,
HttpContext context) throws IOException {
String hostName = host.getHostName();
int port = remoteAddress.getPort();
InetSocketAddress unresolvedRemote = InetSocketAddress.createUnresolved(hostName, port);
return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
}
}

View File

@ -245,7 +245,7 @@ public class DefaultBotSession implements BotSession {
httpPost.setConfig(requestConfig);
httpPost.setEntity(new StringEntity(objectMapper.writeValueAsString(request), ContentType.APPLICATION_JSON));
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
try (CloseableHttpResponse response = httpclient.execute(httpPost, options.getHttpContext())) {
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);