Add internal ability to change API url

Recently, telegram has published [Telegram Bot API Server] - HTTP API <->
MTPROTO proxy which is used internally by telegram. Now it's possible to run
the server locally.

However currently it's not possible to use teloxide with such local server,
because API url is hardcoded into teloxide.

This commit makes _internall_ changes to allow setting the API url. It doesn't
yet allow to set the url from user code (i.e.: no changes in public API), in my
opinion such additions are blocked on some bot refactorings.

`Bot::api_url` is made `Option<Arc<str>>` to minimize costs in case of 'default
url' (probably the most common case).

Progress of this issue is tracked in https://github.com/teloxide/teloxide/issues/317

[Telegram Bot API Server]: https://github.com/tdlib/telegram-bot-api
This commit is contained in:
Waffle 2020-11-16 14:14:00 +03:00
parent 207e9b19b8
commit fa0e86c547
2 changed files with 17 additions and 7 deletions

View file

@ -27,6 +27,7 @@ pub(crate) const TELOXIDE_PROXY: &str = "TELOXIDE_PROXY";
#[derive(Debug, Clone)]
pub struct Bot {
token: Arc<str>,
api_url: Option<Arc<str>>,
client: Client,
parse_mode: Option<ParseMode>,
}
@ -102,6 +103,7 @@ impl Bot {
{
Self {
token: Into::<Arc<str>>::into(Into::<String>::into(token)),
api_url: None,
client,
parse_mode: None,
}
@ -119,13 +121,16 @@ impl Bot {
{
let client = self.client.clone();
let token = Arc::clone(&self.token);
let api_url = self.api_url.clone();
let params = serde_json::to_vec(payload)
// this `expect` should be ok since we don't write request those may trigger error here
.expect("serialization of request to be infallible");
// async move to capture client&token
async move { net::request_json2(&client, token.as_ref(), P::NAME, params).await }
// async move to capture client&token&api_url&params
async move {
net::request_json2(&client, token.as_ref(), api_url.as_deref(), P::NAME, params).await
}
}
pub(crate) fn execute_multipart<P>(
@ -138,13 +143,15 @@ impl Bot {
{
let client = self.client.clone();
let token = Arc::clone(&self.token);
let api_url = self.api_url.clone();
let params = serde_multipart::to_form(payload);
// async move to capture client&token&params
// async move to capture client&token&api_url&params
async move {
let params = params.await?;
net::request_multipart2(&client, token.as_ref(), P::NAME, params).await
net::request_multipart2(&client, token.as_ref(), api_url.as_deref(), P::NAME, params)
.await
}
}
}
@ -281,8 +288,9 @@ impl BotBuilder {
#[must_use]
pub fn build(self) -> Bot {
Bot {
client: self.client.unwrap_or_else(crate::client_from_env),
token: self.token.unwrap_or_else(|| get_env(TELOXIDE_TOKEN)).into(),
api_url: None,
client: self.client.unwrap_or_else(crate::client_from_env),
parse_mode: self.parse_mode,
}
}

View file

@ -72,6 +72,7 @@ where
pub async fn request_multipart2<T>(
client: &Client,
token: &str,
api_url: Option<&str>,
method_name: &str,
params: reqwest::multipart::Form,
) -> ResponseResult<T>
@ -79,7 +80,7 @@ where
T: DeserializeOwned,
{
let response = client
.post(&super::method_url(TELEGRAM_API_URL, token, method_name))
.post(&super::method_url(api_url.unwrap_or(TELEGRAM_API_URL), token, method_name))
.multipart(params)
.send()
.await
@ -91,6 +92,7 @@ where
pub async fn request_json2<T>(
client: &Client,
token: &str,
api_url: Option<&str>,
method_name: &str,
params: Vec<u8>,
) -> ResponseResult<T>
@ -98,7 +100,7 @@ where
T: DeserializeOwned,
{
let response = client
.post(&super::method_url(TELEGRAM_API_URL, token, method_name))
.post(&super::method_url(api_url.unwrap_or(TELEGRAM_API_URL), token, method_name))
.header(CONTENT_TYPE, HeaderValue::from_static("application/json"))
.body(params)
.send()