torrust_tracker/servers/http/v1/responses/
error.rs

1//! `Error` response for the [`HTTP tracker`](crate::servers::http).
2//!
3//! Data structures and logic to build the error responses.
4//!
5//! From the [BEP 03. The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html):
6//!
7//! _"Tracker responses are bencoded dictionaries. If a tracker response has a
8//! key failure reason, then that maps to a human readable string which explains
9//! why the query failed, and no other keys are required."_
10//!
11//! > **NOTICE**: error responses are bencoded and always have a `200 OK` status
12//! > code. The official `BitTorrent` specification does not specify the status
13//! > code.
14use axum::http::StatusCode;
15use axum::response::{IntoResponse, Response};
16use serde::Serialize;
17
18/// `Error` response for the [`HTTP tracker`](crate::servers::http).
19#[derive(Serialize, Debug, PartialEq)]
20pub struct Error {
21    /// Human readable string which explains why the request failed.
22    #[serde(rename = "failure reason")]
23    pub failure_reason: String,
24}
25
26impl Error {
27    /// Returns the bencoded representation of the `Error` struct.
28    ///
29    /// ```rust
30    /// use torrust_tracker::servers::http::v1::responses::error::Error;
31    ///
32    /// let err = Error {
33    ///    failure_reason: "error message".to_owned(),
34    /// };
35    ///
36    /// // cspell:disable-next-line
37    /// assert_eq!(err.write(), "d14:failure reason13:error messagee");
38    /// ```
39    ///
40    /// # Panics
41    ///
42    /// It would panic if the `Error` struct contained an inappropriate field
43    /// type.
44    #[must_use]
45    pub fn write(&self) -> String {
46        serde_bencode::to_string(&self).unwrap()
47    }
48}
49
50impl IntoResponse for Error {
51    fn into_response(self) -> Response {
52        (StatusCode::OK, self.write()).into_response()
53    }
54}
55
56#[cfg(test)]
57mod tests {
58
59    use super::Error;
60
61    #[test]
62    fn http_tracker_errors_can_be_bencoded() {
63        let err = Error {
64            failure_reason: "error message".to_owned(),
65        };
66
67        assert_eq!(err.write(), "d14:failure reason13:error messagee"); // cspell:disable-line
68    }
69}