Rust (Bittorrent):发布失败,响应 "Requested download is not authorized for use with this tracker"
Rust (Bittorrent): Failing at announcing, with response "Requested download is not authorized for use with this tracker"
我正在尝试在 Bittorrent 网络中寻找对等点,但收到响应“请求的下载未被授权用于此跟踪器”。我要下载的 torrent 文件是“Ubuntu 20.04.2.0 Desktop (64-bit)”,可以在 here 中找到。我检查了其他 Bittorrent 客户端,并确认 info_hash
是正确的。我倾向于认为我的错误可能是因为一些不正确的 url-编码,但我不确定。
代码的网络部分正在使用 reqwest crate. To url-encode the info_hash
, I'm using the urlencode crate。这是 url 编码和发送 GET 请求的代码:
let client = reqwest::blocking::Client::new();
let info_hash_encoded = urlencoding::encode_binary(&torrent.info_hash).into_owned().to_uppercase();
let resp = client
.get(&torrent.announce)
.query(&[
("info_hash", info_hash_encoded.as_str()),
("peer_id", PEER_ID),
("port", PORT),
("uploaded", "0"),
("downloaded", "0"),
("compact", "1"),
("left", torrent.length.to_string().as_str()),
])
.send()?
.text()?;
println!("{:?}", resp);
其中 torrent.info_hash
是作为字节向量 (Vec) 的信息散列。
下面是 reqwest 响应的实际样子:
Response { url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("torrent.ubuntu.com")), port: None, path: "/announce", query: Some("info_hash=K%25A4%25FB%25F7%2523%251A%253AF%250E%2586%2589%2527%2507%25D2%255C%2513U3%25A1J&peer_id=-rqbt01-jsbckj94ksj3&port=5035&uploaded=0&downloaded=0&compact=1&left=2877227008"), fragment: None }, status: 200, headers: {"date": "Sat, 17 Jul 2021 17:05:25 GMT", "server": "Apache/2.4.18 (Ubuntu)", "content-length": "85", "content-type": "text/plain", "pragma": "no-cache", "vary": "Accept-Encoding"} }
我最初认为问题可能是因为 info_hash_encoded
是小写的十六进制,但在大写后,我仍然收到同样的错误。顺便说一下,十六进制形式的信息散列是:4ba4fbf7231a3a660e86892707d25c135533a16a
.
谢谢!
编辑:事实证明哈希以某种方式被编码了两次,但即使在修复之后我仍然遇到同样的问题。有谁知道什么是正确的 url 编码信息散列,以便我可以将它与我目前拥有的进行比较?我也尝试在 this spec 之后实现我自己的 url 编码,但我仍然收到同样的错误。
我有两个错误阻止了它的工作:
info_hash
被编码两次,导致“%”个字符被编码为“%25”。
- 每个非数字字节都应编码为 %
,表示“%7”应为“%07”。我缺少前导零。
以下是对我有用的方法:
use std::error::Error;
use std::fmt::Write;
pub fn url_encode_bytes(content: &[u8]) -> Result<String, Box<dyn Error>> {
let mut out: String = String::new();
for byte in content.iter() {
match *byte as char {
'0'..='9' | 'a'..='z' | 'A'..='Z' | '.' | '-' | '_' | '~' => out.push(*byte as char),
_ => write!(&mut out, "%{:02X}", byte)?,
};
}
Ok(out)
}
我还没有找到解决双重编码问题的好方法,但目前我只是像这样手动创建 info_hash
查询:
let url_builder = ureq::get(&torrent.announce)
.query("peer_id", PEER_ID)
.query("port", PORT)
.query("uploaded", "0")
.query("downloaded", "0")
.query("compact", "1")
.query("left", LENGTH);
let url = format!(
"{}{}",
url_builder.url(),
format!("&info_hash={}", url_encode_bytes(&torrent.info_hash)?)
);
我也从 reqwest crate to the ureq crate 切换了。
正确的 url 编码哈希(据我所知)是:K%A4%FB%F7%23%1A%3Af%0E%86%89%27%07%D2%5C%13U3%A1j
.
我正在尝试在 Bittorrent 网络中寻找对等点,但收到响应“请求的下载未被授权用于此跟踪器”。我要下载的 torrent 文件是“Ubuntu 20.04.2.0 Desktop (64-bit)”,可以在 here 中找到。我检查了其他 Bittorrent 客户端,并确认 info_hash
是正确的。我倾向于认为我的错误可能是因为一些不正确的 url-编码,但我不确定。
代码的网络部分正在使用 reqwest crate. To url-encode the info_hash
, I'm using the urlencode crate。这是 url 编码和发送 GET 请求的代码:
let client = reqwest::blocking::Client::new();
let info_hash_encoded = urlencoding::encode_binary(&torrent.info_hash).into_owned().to_uppercase();
let resp = client
.get(&torrent.announce)
.query(&[
("info_hash", info_hash_encoded.as_str()),
("peer_id", PEER_ID),
("port", PORT),
("uploaded", "0"),
("downloaded", "0"),
("compact", "1"),
("left", torrent.length.to_string().as_str()),
])
.send()?
.text()?;
println!("{:?}", resp);
其中 torrent.info_hash
是作为字节向量 (Vec
下面是 reqwest 响应的实际样子:
Response { url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("torrent.ubuntu.com")), port: None, path: "/announce", query: Some("info_hash=K%25A4%25FB%25F7%2523%251A%253AF%250E%2586%2589%2527%2507%25D2%255C%2513U3%25A1J&peer_id=-rqbt01-jsbckj94ksj3&port=5035&uploaded=0&downloaded=0&compact=1&left=2877227008"), fragment: None }, status: 200, headers: {"date": "Sat, 17 Jul 2021 17:05:25 GMT", "server": "Apache/2.4.18 (Ubuntu)", "content-length": "85", "content-type": "text/plain", "pragma": "no-cache", "vary": "Accept-Encoding"} }
我最初认为问题可能是因为 info_hash_encoded
是小写的十六进制,但在大写后,我仍然收到同样的错误。顺便说一下,十六进制形式的信息散列是:4ba4fbf7231a3a660e86892707d25c135533a16a
.
谢谢!
编辑:事实证明哈希以某种方式被编码了两次,但即使在修复之后我仍然遇到同样的问题。有谁知道什么是正确的 url 编码信息散列,以便我可以将它与我目前拥有的进行比较?我也尝试在 this spec 之后实现我自己的 url 编码,但我仍然收到同样的错误。
我有两个错误阻止了它的工作:
info_hash
被编码两次,导致“%”个字符被编码为“%25”。- 每个非数字字节都应编码为 %
,表示“%7”应为“%07”。我缺少前导零。
以下是对我有用的方法:
use std::error::Error;
use std::fmt::Write;
pub fn url_encode_bytes(content: &[u8]) -> Result<String, Box<dyn Error>> {
let mut out: String = String::new();
for byte in content.iter() {
match *byte as char {
'0'..='9' | 'a'..='z' | 'A'..='Z' | '.' | '-' | '_' | '~' => out.push(*byte as char),
_ => write!(&mut out, "%{:02X}", byte)?,
};
}
Ok(out)
}
我还没有找到解决双重编码问题的好方法,但目前我只是像这样手动创建 info_hash
查询:
let url_builder = ureq::get(&torrent.announce)
.query("peer_id", PEER_ID)
.query("port", PORT)
.query("uploaded", "0")
.query("downloaded", "0")
.query("compact", "1")
.query("left", LENGTH);
let url = format!(
"{}{}",
url_builder.url(),
format!("&info_hash={}", url_encode_bytes(&torrent.info_hash)?)
);
我也从 reqwest crate to the ureq crate 切换了。
正确的 url 编码哈希(据我所知)是:K%A4%FB%F7%23%1A%3Af%0E%86%89%27%07%D2%5C%13U3%A1j
.