Skip to content

Commit 37503dd

Browse files
committed
JSON-RPC: add get_http_blob API
1 parent 0b832fb commit 37503dd

File tree

12 files changed

+88
-77
lines changed

12 files changed

+88
-77
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Changes
6+
- Add `get_http_blob` JSON-RPC API.
7+
38
## [1.112.7] - 2023-04-17
49

510
### Fixes

deltachat-jsonrpc/src/api/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,17 @@ impl CommandApi {
16101610
Ok(general_purpose::STANDARD_NO_PAD.encode(blob))
16111611
}
16121612

1613+
/// Makes an HTTP GET request and returns base64-encoded contents.
1614+
///
1615+
/// `url` is the HTTP or HTTPS URL.
1616+
async fn get_http_blob(&self, account_id: u32, url: String) -> Result<String> {
1617+
let ctx = self.get_context(account_id).await?;
1618+
let blob = deltachat::net::read_url_blob(&ctx, &url).await?;
1619+
1620+
use base64::{engine::general_purpose, Engine as _};
1621+
Ok(general_purpose::STANDARD_NO_PAD.encode(blob))
1622+
}
1623+
16131624
/// Forward messages to another chat.
16141625
///
16151626
/// All types of messages can be forwarded,

src/configure.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
mod auto_mozilla;
44
mod auto_outlook;
5-
mod read_url;
65
mod server_params;
76

87
use anyhow::{bail, ensure, Context as _, Result};

src/configure/auto_mozilla.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use std::str::FromStr;
66

77
use quick_xml::events::{BytesStart, Event};
88

9-
use super::read_url::read_url;
109
use super::{Error, ServerParams};
1110
use crate::context::Context;
1211
use crate::login_param::LoginParam;
12+
use crate::net::read_url;
1313
use crate::provider::{Protocol, Socket};
1414

1515
#[derive(Debug)]

src/configure/auto_outlook.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use std::io::BufRead;
77

88
use quick_xml::events::Event;
99

10-
use super::read_url::read_url;
1110
use super::{Error, ServerParams};
1211
use crate::context::Context;
12+
use crate::net::read_url;
1313
use crate::provider::{Protocol, Socket};
1414

1515
/// Result of parsing a single `Protocol` tag.

src/configure/read_url.rs

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/http.rs

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ mod decrypt;
6868
pub mod download;
6969
mod e2ee;
7070
pub mod ephemeral;
71-
mod http;
7271
mod imap;
7372
pub mod imex;
7473
mod scheduler;
@@ -104,7 +103,7 @@ mod dehtml;
104103
mod authres;
105104
mod color;
106105
pub mod html;
107-
mod net;
106+
pub mod net;
108107
pub mod plaintext;
109108
pub mod summary;
110109

src/net.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
///! # Common network utilities.
1+
//! # Common network utilities.
22
use std::net::{IpAddr, SocketAddr};
33
use std::pin::Pin;
44
use std::str::FromStr;
@@ -12,9 +12,12 @@ use tokio_io_timeout::TimeoutStream;
1212
use crate::context::Context;
1313
use crate::tools::time;
1414

15+
pub(crate) mod http;
1516
pub(crate) mod session;
1617
pub(crate) mod tls;
1718

19+
pub use http::{read_url, read_url_blob};
20+
1821
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
1922
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))
2023
.await

src/net/http.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//! # HTTP module.
2+
3+
use std::time::Duration;
4+
5+
use anyhow::{anyhow, Result};
6+
7+
use crate::context::Context;
8+
use crate::socks::Socks5Config;
9+
10+
const HTTP_TIMEOUT: Duration = Duration::from_secs(30);
11+
12+
/// Retrieves the text contents of URL using HTTP GET request.
13+
pub async fn read_url(context: &Context, url: &str) -> Result<String> {
14+
Ok(read_url_inner(context, url).await?.text().await?)
15+
}
16+
17+
/// Retrieves the binary contents of URL using HTTP GET request.
18+
pub async fn read_url_blob(context: &Context, url: &str) -> Result<Vec<u8>> {
19+
Ok(read_url_inner(context, url).await?.bytes().await?.into())
20+
}
21+
22+
async fn read_url_inner(context: &Context, url: &str) -> Result<reqwest::Response> {
23+
let socks5_config = Socks5Config::from_database(&context.sql).await?;
24+
let client = get_client(socks5_config)?;
25+
let mut url = url.to_string();
26+
27+
// Follow up to 10 http-redirects
28+
for _i in 0..10 {
29+
let response = client.get(&url).send().await?;
30+
if response.status().is_redirection() {
31+
let headers = response.headers();
32+
let header = headers
33+
.get_all("location")
34+
.iter()
35+
.last()
36+
.ok_or_else(|| anyhow!("Redirection doesn't have a target location"))?
37+
.to_str()?;
38+
info!(context, "Following redirect to {}", header);
39+
url = header.to_string();
40+
continue;
41+
}
42+
43+
return Ok(response);
44+
}
45+
46+
Err(anyhow!("Followed 10 redirections"))
47+
}
48+
49+
pub(crate) fn get_client(socks5_config: Option<Socks5Config>) -> Result<reqwest::Client> {
50+
let builder = reqwest::ClientBuilder::new().timeout(HTTP_TIMEOUT);
51+
let builder = if let Some(socks5_config) = socks5_config {
52+
let proxy = reqwest::Proxy::all(socks5_config.to_url())?;
53+
builder.proxy(proxy)
54+
} else {
55+
// Disable usage of "system" proxy configured via environment variables.
56+
// It is enabled by default in `reqwest`, see
57+
// <https://docs.rs/reqwest/0.11.14/reqwest/struct.ClientBuilder.html#method.no_proxy>
58+
// for documentation.
59+
builder.no_proxy()
60+
};
61+
Ok(builder.build()?)
62+
}

0 commit comments

Comments
 (0)