Skip to content

Commit f68a2fc

Browse files
committed
JSON-RPC: return mimetype and encoding for HTTP blobs
1 parent 37503dd commit f68a2fc

File tree

8 files changed

+75
-12
lines changed

8 files changed

+75
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Unreleased
44

55
### Changes
6-
- Add `get_http_blob` JSON-RPC API.
6+
- Add `get_http_response` JSON-RPC API.
77

88
## [1.112.7] - 2023-04-17
99

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ kamadak-exif = "0.5"
5757
lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" }
5858
libc = "0.2"
5959
mailparse = "0.14"
60+
mime = "0.3.17"
6061
num_cpus = "1.15"
6162
num-derive = "0.3"
6263
num-traits = "0.2"

deltachat-jsonrpc/src/api/mod.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use types::account::Account;
4343
use types::chat::FullChat;
4444
use types::chat_list::ChatListEntry;
4545
use types::contact::ContactObject;
46+
use types::http::HttpResponse;
4647
use types::message::MessageData;
4748
use types::message::MessageObject;
4849
use types::provider_info::ProviderInfo;
@@ -1610,15 +1611,13 @@ impl CommandApi {
16101611
Ok(general_purpose::STANDARD_NO_PAD.encode(blob))
16111612
}
16121613

1613-
/// Makes an HTTP GET request and returns base64-encoded contents.
1614+
/// Makes an HTTP GET request and returns a response.
16141615
///
16151616
/// `url` is the HTTP or HTTPS URL.
1616-
async fn get_http_blob(&self, account_id: u32, url: String) -> Result<String> {
1617+
async fn get_http_response(&self, account_id: u32, url: String) -> Result<HttpResponse> {
16171618
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))
1619+
let response = deltachat::net::read_url_blob(&ctx, &url).await?.into();
1620+
Ok(response)
16221621
}
16231622

16241623
/// Forward messages to another chat.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use deltachat::net::HttpResponse as CoreHttpResponse;
2+
use serde::Serialize;
3+
use typescript_type_def::TypeDef;
4+
5+
#[derive(Serialize, TypeDef)]
6+
pub struct HttpResponse {
7+
/// base64-encoded response body.
8+
blob: String,
9+
10+
/// MIME type, e.g. "text/plain" or "text/html".
11+
mimetype: Option<String>,
12+
13+
/// Encoding, e.g. "utf-8".
14+
encoding: Option<String>,
15+
}
16+
17+
impl From<CoreHttpResponse> for HttpResponse {
18+
fn from(response: CoreHttpResponse) -> Self {
19+
use base64::{engine::general_purpose, Engine as _};
20+
let blob = general_purpose::STANDARD_NO_PAD.encode(response.blob);
21+
let mimetype = response.mimetype;
22+
let encoding = response.encoding;
23+
HttpResponse {
24+
blob,
25+
mimetype,
26+
encoding,
27+
}
28+
}
29+
}

deltachat-jsonrpc/src/api/types/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub mod account;
22
pub mod chat;
33
pub mod chat_list;
44
pub mod contact;
5+
pub mod http;
56
pub mod location;
67
pub mod message;
78
pub mod provider_info;

src/net.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub(crate) mod http;
1616
pub(crate) mod session;
1717
pub(crate) mod tls;
1818

19-
pub use http::{read_url, read_url_blob};
19+
pub use http::{read_url, read_url_blob, Response as HttpResponse};
2020

2121
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
2222
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))

src/net/http.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,52 @@
33
use std::time::Duration;
44

55
use anyhow::{anyhow, Result};
6+
use mime::Mime;
67

78
use crate::context::Context;
89
use crate::socks::Socks5Config;
910

1011
const HTTP_TIMEOUT: Duration = Duration::from_secs(30);
1112

13+
/// HTTP(S) GET response.
14+
#[derive(Debug)]
15+
pub struct Response {
16+
/// Response body.
17+
pub blob: Vec<u8>,
18+
19+
/// MIME type exntracted from the `Content-Type` header, if any.
20+
pub mimetype: Option<String>,
21+
22+
/// Encoding extracted from the `Content-Type` header, if any.
23+
pub encoding: Option<String>,
24+
}
25+
1226
/// Retrieves the text contents of URL using HTTP GET request.
1327
pub async fn read_url(context: &Context, url: &str) -> Result<String> {
1428
Ok(read_url_inner(context, url).await?.text().await?)
1529
}
1630

1731
/// 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())
32+
pub async fn read_url_blob(context: &Context, url: &str) -> Result<Response> {
33+
let response = read_url_inner(context, url).await?;
34+
let content_type = response
35+
.headers()
36+
.get(reqwest::header::CONTENT_TYPE)
37+
.and_then(|value| value.to_str().ok())
38+
.and_then(|value| value.parse::<Mime>().ok());
39+
let mimetype = content_type
40+
.as_ref()
41+
.map(|mime| mime.essence_str().to_string());
42+
let encoding = content_type.as_ref().and_then(|mime| {
43+
mime.get_param(mime::CHARSET)
44+
.map(|charset| charset.as_str().to_string())
45+
});
46+
let blob: Vec<u8> = response.bytes().await?.into();
47+
Ok(Response {
48+
blob,
49+
mimetype,
50+
encoding,
51+
})
2052
}
2153

2254
async fn read_url_inner(context: &Context, url: &str) -> Result<reqwest::Response> {

0 commit comments

Comments
 (0)