wx-bot-sdk 0.1.3

Standalone Weixin Bot SDK in Rust
Documentation
use reqwest::header::HeaderMap;

use super::{aes_ecb::encrypt_aes_ecb, cdn_url::build_cdn_upload_url};

#[derive(Clone, Debug)]
pub struct UploadBufferToCdnResult {
    pub download_param: String,
}

pub async fn upload_buffer_to_cdn(
    buf: &[u8],
    upload_full_url: Option<&str>,
    upload_param: Option<&str>,
    filekey: &str,
    cdn_base_url: &str,
    aeskey: &[u8],
    label: &str,
) -> crate::Result<UploadBufferToCdnResult> {
    let url = match upload_full_url.filter(|s| !s.trim().is_empty()) {
        Some(u) => u.to_string(),
        None => build_cdn_upload_url(
            cdn_base_url,
            upload_param.ok_or("missing upload_param")?,
            filekey,
        ),
    };
    let encrypted = encrypt_aes_ecb(buf, aeskey)?;
    let res = reqwest::Client::new()
        .post(url)
        .header("Content-Type", "application/octet-stream")
        .body(encrypted)
        .send()
        .await?;
    let status = res.status();
    let headers = res.headers().clone();
    let body = res.text().await.unwrap_or_default();
    if !status.is_success() {
        return Err(format!("{label} CDN upload HTTP {status}: {body}").into());
    }
    let download_param = encrypted_param_from_headers(&headers)
        .ok_or_else(|| format!("{label}: CDN response missing x-encrypted-param"))?;
    Ok(UploadBufferToCdnResult { download_param })
}

fn encrypted_param_from_headers(headers: &HeaderMap) -> Option<String> {
    headers
        .get("x-encrypted-param")
        .or_else(|| headers.get("X-Encrypted-Param"))
        .and_then(|v| v.to_str().ok())
        .map(ToOwned::to_owned)
}