mirror of
https://github.com/chatmail/core.git
synced 2026-05-19 23:06:32 +03:00
JSON-RPC: return mimetype and encoding for HTTP blobs
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- Add `get_http_blob` JSON-RPC API.
|
- Add `get_http_response` JSON-RPC API.
|
||||||
|
|
||||||
## [1.112.7] - 2023-04-17
|
## [1.112.7] - 2023-04-17
|
||||||
|
|
||||||
|
|||||||
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -1080,6 +1080,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"mailparse",
|
"mailparse",
|
||||||
|
"mime",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
@@ -2591,9 +2592,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.16"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ kamadak-exif = "0.5"
|
|||||||
lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" }
|
lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
mailparse = "0.14"
|
mailparse = "0.14"
|
||||||
|
mime = "0.3.17"
|
||||||
num_cpus = "1.15"
|
num_cpus = "1.15"
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ use types::account::Account;
|
|||||||
use types::chat::FullChat;
|
use types::chat::FullChat;
|
||||||
use types::chat_list::ChatListEntry;
|
use types::chat_list::ChatListEntry;
|
||||||
use types::contact::ContactObject;
|
use types::contact::ContactObject;
|
||||||
|
use types::http::HttpResponse;
|
||||||
use types::message::MessageData;
|
use types::message::MessageData;
|
||||||
use types::message::MessageObject;
|
use types::message::MessageObject;
|
||||||
use types::provider_info::ProviderInfo;
|
use types::provider_info::ProviderInfo;
|
||||||
@@ -1610,15 +1611,13 @@ impl CommandApi {
|
|||||||
Ok(general_purpose::STANDARD_NO_PAD.encode(blob))
|
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.
|
/// `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 ctx = self.get_context(account_id).await?;
|
||||||
let blob = deltachat::net::read_url_blob(&ctx, &url).await?;
|
let response = deltachat::net::read_url_blob(&ctx, &url).await?.into();
|
||||||
|
Ok(response)
|
||||||
use base64::{engine::general_purpose, Engine as _};
|
|
||||||
Ok(general_purpose::STANDARD_NO_PAD.encode(blob))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forward messages to another chat.
|
/// Forward messages to another chat.
|
||||||
|
|||||||
29
deltachat-jsonrpc/src/api/types/http.rs
Normal file
29
deltachat-jsonrpc/src/api/types/http.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ pub mod account;
|
|||||||
pub mod chat;
|
pub mod chat;
|
||||||
pub mod chat_list;
|
pub mod chat_list;
|
||||||
pub mod contact;
|
pub mod contact;
|
||||||
|
pub mod http;
|
||||||
pub mod location;
|
pub mod location;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod provider_info;
|
pub mod provider_info;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub(crate) mod http;
|
|||||||
pub(crate) mod session;
|
pub(crate) mod session;
|
||||||
pub(crate) mod tls;
|
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> {
|
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
|
||||||
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))
|
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))
|
||||||
|
|||||||
@@ -3,20 +3,52 @@
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use mime::Mime;
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::socks::Socks5Config;
|
use crate::socks::Socks5Config;
|
||||||
|
|
||||||
const HTTP_TIMEOUT: Duration = Duration::from_secs(30);
|
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.
|
/// Retrieves the text contents of URL using HTTP GET request.
|
||||||
pub async fn read_url(context: &Context, url: &str) -> Result<String> {
|
pub async fn read_url(context: &Context, url: &str) -> Result<String> {
|
||||||
Ok(read_url_inner(context, url).await?.text().await?)
|
Ok(read_url_inner(context, url).await?.text().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the binary contents of URL using HTTP GET request.
|
/// Retrieves the binary contents of URL using HTTP GET request.
|
||||||
pub async fn read_url_blob(context: &Context, url: &str) -> Result<Vec<u8>> {
|
pub async fn read_url_blob(context: &Context, url: &str) -> Result<Response> {
|
||||||
Ok(read_url_inner(context, url).await?.bytes().await?.into())
|
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> {
|
async fn read_url_inner(context: &Context, url: &str) -> Result<reqwest::Response> {
|
||||||
|
|||||||
Reference in New Issue
Block a user