forked from torrust/torrust-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscrape.rs
More file actions
118 lines (101 loc) · 3 KB
/
scrape.rs
File metadata and controls
118 lines (101 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::fmt;
use std::str::FromStr;
use torrust_tracker::shared::bit_torrent::info_hash::InfoHash;
use crate::servers::http::{percent_encode_byte_array, ByteArray20};
pub struct Query {
pub info_hash: Vec<ByteArray20>,
}
impl fmt::Display for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.build())
}
}
/// HTTP Tracker Scrape Request:
///
/// <https://www.bittorrent.org/beps/bep_0048.html>
impl Query {
/// It builds the URL query component for the scrape request.
///
/// This custom URL query params encoding is needed because `reqwest` does not allow
/// bytes arrays in query parameters. More info on this issue:
///
/// <https://github.com/seanmonstar/reqwest/issues/1613>
pub fn build(&self) -> String {
self.params().to_string()
}
pub fn params(&self) -> QueryParams {
QueryParams::from(self)
}
}
pub struct QueryBuilder {
scrape_query: Query,
}
impl QueryBuilder {
pub fn default() -> QueryBuilder {
let default_scrape_query = Query {
info_hash: [InfoHash::from_str("9c38422213e30bff212b30c360d26f9a02136422").unwrap().0].to_vec(),
};
Self {
scrape_query: default_scrape_query,
}
}
pub fn with_one_info_hash(mut self, info_hash: &InfoHash) -> Self {
self.scrape_query.info_hash = [info_hash.0].to_vec();
self
}
pub fn add_info_hash(mut self, info_hash: &InfoHash) -> Self {
self.scrape_query.info_hash.push(info_hash.0);
self
}
pub fn query(self) -> Query {
self.scrape_query
}
}
/// It contains all the GET parameters that can be used in a HTTP Scrape request.
///
/// The `info_hash` param is the percent encoded of the the 20-byte array info hash.
///
/// Sample Scrape URL with all the GET parameters:
///
/// For `IpV4`:
///
/// ```text
/// http://127.0.0.1:7070/scrape?info_hash=%9C8B%22%13%E3%0B%FF%21%2B0%C3%60%D2o%9A%02%13d%22
/// ```
///
/// For `IpV6`:
///
/// ```text
/// http://[::1]:7070/scrape?info_hash=%9C8B%22%13%E3%0B%FF%21%2B0%C3%60%D2o%9A%02%13d%22
/// ```
///
/// You can add as many info hashes as you want, just adding the same param again.
pub struct QueryParams {
pub info_hash: Vec<String>,
}
impl QueryParams {
pub fn set_one_info_hash_param(&mut self, info_hash: &str) {
self.info_hash = vec![info_hash.to_string()];
}
}
impl std::fmt::Display for QueryParams {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let query = self
.info_hash
.iter()
.map(|info_hash| format!("info_hash={}", &info_hash))
.collect::<Vec<String>>()
.join("&");
write!(f, "{query}")
}
}
impl QueryParams {
pub fn from(scrape_query: &Query) -> Self {
let info_hashes = scrape_query
.info_hash
.iter()
.map(percent_encode_byte_array)
.collect::<Vec<String>>();
Self { info_hash: info_hashes }
}
}