JSON-RPC: return mimetype and encoding for HTTP blobs

This commit is contained in:
link2xt
2023-04-19 23:33:19 +00:00
parent 37503dd3e8
commit f68a2fc387
8 changed files with 75 additions and 12 deletions

View File

@@ -3,7 +3,7 @@
## Unreleased
### Changes
- Add `get_http_blob` JSON-RPC API.
- Add `get_http_response` JSON-RPC API.
## [1.112.7] - 2023-04-17

5
Cargo.lock generated
View File

@@ -1080,6 +1080,7 @@ dependencies = [
"libc",
"log",
"mailparse",
"mime",
"num-derive",
"num-traits",
"num_cpus",
@@ -2591,9 +2592,9 @@ dependencies = [
[[package]]
name = "mime"
version = "0.3.16"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"

View File

@@ -57,6 +57,7 @@ kamadak-exif = "0.5"
lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" }
libc = "0.2"
mailparse = "0.14"
mime = "0.3.17"
num_cpus = "1.15"
num-derive = "0.3"
num-traits = "0.2"

View File

@@ -43,6 +43,7 @@ use types::account::Account;
use types::chat::FullChat;
use types::chat_list::ChatListEntry;
use types::contact::ContactObject;
use types::http::HttpResponse;
use types::message::MessageData;
use types::message::MessageObject;
use types::provider_info::ProviderInfo;
@@ -1610,15 +1611,13 @@ impl CommandApi {
Ok(general_purpose::STANDARD_NO_PAD.encode(blob))
}
/// Makes an HTTP GET request and returns base64-encoded contents.
/// Makes an HTTP GET request and returns a response.
///
/// `url` is the HTTP or HTTPS URL.
async fn get_http_blob(&self, account_id: u32, url: String) -> Result<String> {
async fn get_http_response(&self, account_id: u32, url: String) -> Result<HttpResponse> {
let ctx = self.get_context(account_id).await?;
let blob = deltachat::net::read_url_blob(&ctx, &url).await?;
use base64::{engine::general_purpose, Engine as _};
Ok(general_purpose::STANDARD_NO_PAD.encode(blob))
let response = deltachat::net::read_url_blob(&ctx, &url).await?.into();
Ok(response)
}
/// Forward messages to another chat.

View File

@@ -0,0 +1,29 @@
use deltachat::net::HttpResponse as CoreHttpResponse;
use serde::Serialize;
use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef)]
pub struct HttpResponse {
/// base64-encoded response body.
blob: String,
/// MIME type, e.g. "text/plain" or "text/html".
mimetype: Option<String>,
/// Encoding, e.g. "utf-8".
encoding: Option<String>,
}
impl From<CoreHttpResponse> for HttpResponse {
fn from(response: CoreHttpResponse) -> Self {
use base64::{engine::general_purpose, Engine as _};
let blob = general_purpose::STANDARD_NO_PAD.encode(response.blob);
let mimetype = response.mimetype;
let encoding = response.encoding;
HttpResponse {
blob,
mimetype,
encoding,
}
}
}

View File

@@ -2,6 +2,7 @@ pub mod account;
pub mod chat;
pub mod chat_list;
pub mod contact;
pub mod http;
pub mod location;
pub mod message;
pub mod provider_info;

View File

@@ -16,7 +16,7 @@ pub(crate) mod http;
pub(crate) mod session;
pub(crate) mod tls;
pub use http::{read_url, read_url_blob};
pub use http::{read_url, read_url_blob, Response as HttpResponse};
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))

View File

@@ -3,20 +3,52 @@
use std::time::Duration;
use anyhow::{anyhow, Result};
use mime::Mime;
use crate::context::Context;
use crate::socks::Socks5Config;
const HTTP_TIMEOUT: Duration = Duration::from_secs(30);
/// HTTP(S) GET response.
#[derive(Debug)]
pub struct Response {
/// Response body.
pub blob: Vec<u8>,
/// MIME type exntracted from the `Content-Type` header, if any.
pub mimetype: Option<String>,
/// Encoding extracted from the `Content-Type` header, if any.
pub encoding: Option<String>,
}
/// Retrieves the text contents of URL using HTTP GET request.
pub async fn read_url(context: &Context, url: &str) -> Result<String> {
Ok(read_url_inner(context, url).await?.text().await?)
}
/// Retrieves the binary contents of URL using HTTP GET request.
pub async fn read_url_blob(context: &Context, url: &str) -> Result<Vec<u8>> {
Ok(read_url_inner(context, url).await?.bytes().await?.into())
pub async fn read_url_blob(context: &Context, url: &str) -> Result<Response> {
let response = read_url_inner(context, url).await?;
let content_type = response
.headers()
.get(reqwest::header::CONTENT_TYPE)
.and_then(|value| value.to_str().ok())
.and_then(|value| value.parse::<Mime>().ok());
let mimetype = content_type
.as_ref()
.map(|mime| mime.essence_str().to_string());
let encoding = content_type.as_ref().and_then(|mime| {
mime.get_param(mime::CHARSET)
.map(|charset| charset.as_str().to_string())
});
let blob: Vec<u8> = response.bytes().await?.into();
Ok(Response {
blob,
mimetype,
encoding,
})
}
async fn read_url_inner(context: &Context, url: &str) -> Result<reqwest::Response> {