fix: 修复获取 wbi 签名的 rust 实现 (#1059)

* fix: 修复获取 wbi 签名的 rust 实现

* chore: 在最上面的介绍里补上 Rust 的超链接
This commit is contained in:
ᴀᴍᴛᴏᴀᴇʀ 2024-07-20 17:53:25 +08:00 committed by GitHub
parent 8cdf355f7e
commit 8f419c1c9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -120,7 +120,7 @@
## Demo
含 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang)、[C#](#CSharp)、[Java](#Java)、[Swift](#Swift)、[C++](#CPlusPlus) 语言编写的 Demo 。
含 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang)、[C#](#CSharp)、[Java](#Java)、[Swift](#Swift)、[C++](#CPlusPlus)、[Rust](#Rust) 语言编写的 Demo 。
### Python
@ -867,6 +867,7 @@ struct ResWbi {
fn get_mixin_key(orig: &[u8]) -> String {
MIXIN_KEY_ENC_TAB
.iter()
.take(32)
.map(|&i| orig[i] as char)
.collect::<String>()
}
@ -891,23 +892,34 @@ fn get_url_encoded(s: &str) -> String {
}
// 为请求参数进行 wbi 签名
fn encode_wbi(params: &mut Vec<(&str, String)>, (img_key, sub_key): (String, String)) -> String {
let mixin_key = get_mixin_key((img_key + &sub_key).as_bytes());
fn encode_wbi(params: Vec<(&str, String)>, (img_key, sub_key): (String, String)) -> String {
let cur_time = match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(t) => t.as_secs(),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
};
_encode_wbi(params, (img_key, sub_key), cur_time)
}
fn _encode_wbi(
mut params: Vec<(&str, String)>,
(img_key, sub_key): (String, String),
timestamp: u64,
) -> String {
let mixin_key = get_mixin_key((img_key + &sub_key).as_bytes());
// 添加当前时间戳
params.push(("wts", cur_time.to_string()));
params.push(("wts", timestamp.to_string()));
// 重新排序
params.sort_by(|a, b| a.0.cmp(b.0));
let query = params.iter().fold(String::from(""), |acc, (k, v)| {
acc + format!("{}={}&", get_url_encoded(k), get_url_encoded(v)).as_str()
});
// 拼接参数
let query = params
.iter()
.map(|(k, v)| format!("{}={}", get_url_encoded(k), get_url_encoded(v)))
.collect::<Vec<_>>()
.join("&");
// 计算签名
let web_sign = format!("{:?}", md5::compute(query.clone() + &mixin_key));
query + &format!("w_rid={}", web_sign)
// 返回最终的 query
query + &format!("&w_rid={}", web_sign)
}
async fn get_wbi_keys() -> Result<(String, String), reqwest::Error> {
@ -922,23 +934,76 @@ async fn get_wbi_keys() -> Result<(String, String), reqwest::Error> {
.await?
.json::<ResWbi>()
.await?;
Ok((
take_filename(wbi_img.img_url).unwrap(),
take_filename(wbi_img.sub_url).unwrap(),
))
}
Ok((wbi_img.img_url, wbi_img.sub_url))
fn take_filename(url: String) -> Option<String> {
url.rsplit_once('/')
.and_then(|(_, s)| s.rsplit_once('.'))
.map(|(s, _)| s.to_string())
}
#[tokio::main]
async fn main() {
let urls = get_wbi_keys().await.unwrap();
let mut params = vec![
let keys = get_wbi_keys().await.unwrap();
let params = vec![
("foo", String::from("114")),
("bar", String::from("514")),
("baz", String::from("1919810")),
];
let query = encode_wbi(&mut params, urls);
let query = encode_wbi(params, keys);
println!("{}", query);
}
// 取自文档描述的测试用例
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_filename() {
assert_eq!(
take_filename(
"https://i0.hdslb.com/bfs/wbi/7cd084941338484aae1ad9425b84077c.png".to_string()
),
Some("7cd084941338484aae1ad9425b84077c".to_string())
);
}
#[test]
fn test_get_mixin_key() {
let concat_key =
"7cd084941338484aae1ad9425b84077c".to_string() + "4932caff0ff746eab6f01bf08b70ac45";
assert_eq!(
get_mixin_key(concat_key.as_bytes()),
"ea1db124af3c7062474693fa704f4ff8"
);
}
#[test]
fn test_encode_wbi() {
let params = vec![
("foo", String::from("114")),
("bar", String::from("514")),
("zab", String::from("1919810")),
];
assert_eq!(
_encode_wbi(
params,
(
"7cd084941338484aae1ad9425b84077c".to_string(),
"4932caff0ff746eab6f01bf08b70ac45".to_string()
),
1702204169
),
"bar=514&foo=114&wts=1702204169&zab=1919810&w_rid=8f6f2b5b3d485fe1886cec6a0be8c5d4"
.to_string()
)
}
}
```
### Swift