Open bk2204 opened 2 years ago
I'm implementing a client for a BitTorrent HTTP tracker, and it uses two byte arrays parameters in the URL query.
info_hash: urlencoded 20-byte SHA1 hash of the value of the info key from the Metainfo file. Note that the value will be a bencoded dictionary, given the definition of the info key above.
peer_id: urlencoded 20-byte string used as a unique ID for the client, generated by the client at startup. This is allowed to be any value, and may be binary data. There are currently no guidelines for generating this peer ID. However, one may rightly presume that it must at least be unique for your local machine, thus should probably incorporate things like process ID and perhaps a timestamp recorded at startup. See peer_id below for common client encodings of this field.
Is there a way to pass raw GET parameters which have already been percent-encoded? I do not see it.
This is my current workaround for this:
pub struct TrackerRequest<'caller> {
pub info_hash: &'caller [u8],
pub peer_id: &'caller [u8],
pub port: u16,
pub uploaded: u64,
pub downloaded: u64,
pub left: u64,
pub compact: bool,
}
impl<'a> TrackerRequest<'a> {
pub fn url(&'a self, metainfo: &'a Metainfo) -> String {
let url_encoded_info_hash = urlencoding::encode_binary(metainfo.info().hash());
let url_encoded_peer_id = urlencoding::encode_binary(self.peer_id);
let mut url = String::new();
url.push_str(metainfo.announce());
url.push('?');
url.push_str("info_hash=");
url.push_str(&url_encoded_info_hash);
url.push('&');
url.push_str("peer_id=");
url.push_str(&url_encoded_peer_id);
url.push('&');
url.push_str("port=");
url.push_str(&self.port.to_string());
url.push('&');
url.push_str("uploaded=");
url.push_str(&self.uploaded.to_string());
url.push('&');
url.push_str("downloaded=");
url.push_str(&self.downloaded.to_string());
url.push('&');
url.push_str("left=");
url.push_str(&self.left.to_string());
url.push('&');
url.push_str("compact=");
url.push_str(&(self.compact as u8).to_string());
url
}
}
Not ideal but it works for now.
Reqwest uses
serde_urlencoded
for query parameters. However, that is designed to handle only UTF-8 strings, and query parameters may contain arbitrary octets encoded according to the RFC 3986.I filed nox/serde_urlencoded#104 on the underlying library, which was refused because that is designed for
application/x-www-form-urlencoded
, which allegedly only deals with UTF-8. However, the query parameters are not so restricted by RFC 3986, so a different library probably needs to be used here.