如何在Rust中实现这个Python post请求



我有下面的python脚本,可以将图像上传到imgurl:

headers = {"Authorization": "Client-ID "+client_id}
data = {
"key": client_secret,
"image": base64.b64encode(file),
"type": "base64",
}
r = requests.post("https://api.imgur.com/3/upload.json",headers=headers,data=data)
if json.loads(r.content)["status"] == 200:
link = json.loads(r.content)["data"]["link"]
print(link)

我正试图在铁锈上重新制作,这就是我走的路:

use curl::easy::{Easy,List};
fn main() {
let mut list = List::new();
list.append("Authorization  Client-ID MYCLIENTID").unwrap();
let mut easy = Easy::new();
easy.url("https://api.imgur.com/3/upload.json").unwrap();
easy.http_headers(list).unwrap();
easy.post(true).unwrap();
easy.write_function(|data| {
stdout().write_all(data).unwrap();
Ok(data.len())
}).unwrap();
easy.perform().unwrap();
}

我不知道如何在rust上使数据成为python脚本的一部分
我尝试过使用reqwest,但在使用多部分/表单数据的post请求中没有找到任何可用的示例。

Easy Curl

您可以使用read_function

use data_encoding::BASE64;
use std::collections::HashMap;
fn main() {
let mut data = HashMap::new();
data.insert("key", client_secret);
data.insert("image", BASE64.encode(file));
data.insert("type", "base64");
let post_data = format!("{:?}", data);
let mut list = List::new();
list.append("Authorization  Client-ID MYCLIENTID").unwrap();
let mut easy = Easy::new();
easy.url("https://api.imgur.com/3/upload.json").unwrap();
easy.http_headers(list).unwrap();
easy.post(true).unwrap();
easy.read_function(|into| {
Ok(post_data.as_bytes().read(into).unwrap())
});
easy.write_function(|data| {
stdout().write_all(data).unwrap();
Ok(data.len())
}).unwrap();
easy.perform().unwrap();
}

post_fields_copy

use data_encoding::BASE64;
use std::collections::HashMap;
fn main() {
let mut data = HashMap::new();
data.insert("key", client_secret);
data.insert("image", BASE64.encode(file));
data.insert("type", "base64");
let post_data = format!("{:?}", data);
let mut list = List::new();
list.append("Authorization  Client-ID MYCLIENTID").unwrap();
let mut easy = Easy::new();
easy.url("https://api.imgur.com/3/upload.json").unwrap();
easy.http_headers(list).unwrap();
easy.post(true).unwrap();
easy.post_fields_copy(post_data.as_bytes());
easy.write_function(|data| {
stdout().write_all(data).unwrap();
Ok(data.len())
}).unwrap();
easy.perform().unwrap();
}

Reqwest

use reqwest::header::HeaderName;
fn main() {
let mut data = HashMap::new();
data.insert("key", client_secret);
data.insert("image", BASE64.encode(file));
data.insert("type", "base64");
let mut headers = reqwest::header::HeaderMap::new();
let name: HeaderName = "Authorization".parse().unwrap();
headers.insert(name, "Client-ID MYCLIENTID".parse().unwrap());
let client = reqwest::blocking::Client::new();
let res = client.post("https://api.imgur.com/3/upload.json")
.headers(headers)
.json(&data)
.send();
}

我尝试使用curl和reqwest来完成,您可以参考curl的测试用例

use std::io::{stdout, Write};
use curl::easy::{Easy, Form, List};
fn main() {
let mut list = List::new();
list.append("Authorization:  Client-ID MYCLIENTID").unwrap();
let mut easy = Easy::new();
easy.url("http://127.0.0.1:8000/").unwrap();
easy.http_headers(list).unwrap();
let mut form = Form::new();
form.part("key").contents("key".as_bytes()).add();
form.part("image").contents("image".as_bytes()).add();
form.part("type").contents("type".as_bytes()).add();
easy.write_function(|data| {
stdout().write_all(data).unwrap();
Ok(data.len())
}).unwrap();
easy.httppost(form);
easy.perform().unwrap();
}
Path: /
Headers:
Host: 127.0.0.1:8000
Accept: */*
Authorization: Client-ID MYCLIENTID
Content-Length: 337
Content-Type: multipart/form-data; boundary=------------------------7f3cd45715114afd

Body:
--------------------------7f3cd45715114afd
Content-Disposition: form-data; name="key"
key
--------------------------7f3cd45715114afd
Content-Disposition: form-data; name="image"
image
--------------------------7f3cd45715114afd
Content-Disposition: form-data; name="type"
type
--------------------------7f3cd45715114afd--

127.0.0.1 - - [19/Mar/2022 01:48:29] "POST / HTTP/1.1" 200 -

添加请求实现

reqwest = { version = "0.11.10", features = ['multipart', "blocking"] }
use reqwest::blocking::multipart;
use reqwest::header::HeaderName;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let form = multipart::Form::new()
.text("key", "key")
.text("type", "type");
let mut headers = reqwest::header::HeaderMap::new();
let name: HeaderName = "Authorization".parse().unwrap();
headers.insert(name, "Client-ID MYCLIENTID".parse().unwrap());
let client = reqwest::blocking::Client::new();
let res = client.post("http://127.0.0.1:8000/")
.headers(headers)
.multipart(form)
.send()?;
Ok(())
}
Path: /
Headers:
authorization: Client-ID MYCLIENTID
content-type: multipart/form-data; boundary=333d5f9f981ff8c4-52968a2548643dba-06b19c9eb1896219-083c4cc6b1618966
content-length: 319
accept: */*
host: 127.0.0.1:8000

Body:
--333d5f9f981ff8c4-52968a2548643dba-06b19c9eb1896219-083c4cc6b1618966
Content-Disposition: form-data; name="key"
key
--333d5f9f981ff8c4-52968a2548643dba-06b19c9eb1896219-083c4cc6b1618966
Content-Disposition: form-data; name="type"
type
--333d5f9f981ff8c4-52968a2548643dba-06b19c9eb1896219-083c4cc6b1618966--

127.0.0.1 - - [19/Mar/2022 02:27:40] "POST / HTTP/1.1" 200 -