nntp_proxy/protocol/
responses.rs1pub const MULTILINE_TERMINATOR: &[u8] = b"\r\n.\r\n";
8
9pub const CRLF: &[u8] = b"\r\n";
11
12pub const TERMINATOR_TAIL_SIZE: usize = 4;
14
15pub const MIN_RESPONSE_LENGTH: usize = 5;
17
18pub const AUTH_REQUIRED: &[u8] = b"381 Password required\r\n";
22
23pub const AUTH_ACCEPTED: &[u8] = b"281 Authentication accepted\r\n";
25
26pub const AUTH_FAILED: &[u8] = b"481 Authentication failed\r\n";
28
29pub const AUTH_REQUIRED_FOR_COMMAND: &[u8] = b"480 Authentication required\r\n";
31
32pub const PROXY_GREETING_PCR: &[u8] = b"200 NNTP Proxy Ready (Per-Command Routing)\r\n";
36
37pub const CONNECTION_CLOSING: &[u8] = b"205 Connection closing\r\n";
39
40pub const GOODBYE: &[u8] = b"205 Goodbye\r\n";
42
43pub const COMMAND_NOT_SUPPORTED: &[u8] = b"500 Command not supported by this proxy\r\n";
47
48pub const BACKEND_ERROR: &[u8] = b"503 Backend error\r\n";
50
51pub const BACKEND_UNAVAILABLE: &[u8] = b"400 Backend server unavailable\r\n";
53
54pub const NO_SUCH_ARTICLE: &[u8] = b"430 No such article\r\n";
56
57pub const COMMAND_NOT_SUPPORTED_STATELESS: &[u8] =
59 b"500 Command not supported by this proxy (stateless proxy mode)\r\n";
60
61#[inline]
73pub fn greeting(message: &str) -> String {
74 format!("200 {}\r\n", message)
75}
76
77#[inline]
79pub fn greeting_readonly(message: &str) -> String {
80 format!("201 {}\r\n", message)
81}
82
83#[inline]
85pub fn ok_response(message: &str) -> String {
86 format!("200 {}\r\n", message)
87}
88
89#[inline]
99pub fn error_response(code: u16, message: &str) -> String {
100 format!("{} {}\r\n", code, message)
101}
102
103#[inline]
105pub fn response(code: u16, message: &str) -> String {
106 format!("{} {}\r\n", code, message)
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_constants() {
115 assert_eq!(CRLF, b"\r\n");
116 assert_eq!(MULTILINE_TERMINATOR, b"\r\n.\r\n");
117 assert_eq!(MULTILINE_TERMINATOR.len(), 5);
118 assert_eq!(TERMINATOR_TAIL_SIZE, 4);
119 }
120
121 #[test]
122 fn test_greeting() {
123 assert_eq!(greeting("Ready"), "200 Ready\r\n");
124 assert_eq!(
125 greeting("news.example.com ready"),
126 "200 news.example.com ready\r\n"
127 );
128 assert_eq!(greeting_readonly("Read only"), "201 Read only\r\n");
129 }
130
131 #[test]
132 fn test_ok_response() {
133 assert_eq!(ok_response("OK"), "200 OK\r\n");
134 assert_eq!(ok_response("Command accepted"), "200 Command accepted\r\n");
135 }
136
137 #[test]
138 fn test_error_response() {
139 assert_eq!(
140 error_response(430, "No such article"),
141 "430 No such article\r\n"
142 );
143 assert_eq!(
144 error_response(500, "Command not recognized"),
145 "500 Command not recognized\r\n"
146 );
147 }
148
149 #[test]
150 fn test_response() {
151 assert_eq!(
152 response(215, "Newsgroups follow"),
153 "215 Newsgroups follow\r\n"
154 );
155 assert_eq!(
156 response(381, "Password required"),
157 "381 Password required\r\n"
158 );
159 }
160
161 #[test]
162 fn test_auth_constants() {
163 assert_eq!(AUTH_REQUIRED, b"381 Password required\r\n");
164 assert_eq!(AUTH_ACCEPTED, b"281 Authentication accepted\r\n");
165 assert_eq!(AUTH_FAILED, b"481 Authentication failed\r\n");
166 assert_eq!(
167 AUTH_REQUIRED_FOR_COMMAND,
168 b"480 Authentication required\r\n"
169 );
170 }
171
172 #[test]
173 fn test_standard_responses() {
174 assert!(PROXY_GREETING_PCR.starts_with(b"200"));
175 assert!(CONNECTION_CLOSING.starts_with(b"205"));
176 assert!(GOODBYE.starts_with(b"205"));
177 }
178
179 #[test]
180 fn test_error_constants() {
181 assert!(COMMAND_NOT_SUPPORTED.starts_with(b"500"));
182 assert!(BACKEND_ERROR.starts_with(b"503"));
183 assert!(BACKEND_UNAVAILABLE.starts_with(b"400"));
184 assert!(COMMAND_NOT_SUPPORTED_STATELESS.starts_with(b"500"));
185 }
186
187 #[test]
188 fn test_all_responses_end_with_crlf() {
189 assert!(AUTH_REQUIRED.ends_with(CRLF));
190 assert!(AUTH_ACCEPTED.ends_with(CRLF));
191 assert!(AUTH_FAILED.ends_with(CRLF));
192 assert!(AUTH_REQUIRED_FOR_COMMAND.ends_with(CRLF));
193 assert!(PROXY_GREETING_PCR.ends_with(CRLF));
194 assert!(CONNECTION_CLOSING.ends_with(CRLF));
195 assert!(GOODBYE.ends_with(CRLF));
196 assert!(COMMAND_NOT_SUPPORTED.ends_with(CRLF));
197 assert!(BACKEND_ERROR.ends_with(CRLF));
198 assert!(BACKEND_UNAVAILABLE.ends_with(CRLF));
199 assert!(COMMAND_NOT_SUPPORTED_STATELESS.ends_with(CRLF));
200 }
201}