1use crate::{httpdata::HttpData, media_types::RDAP_MEDIA_TYPE, prelude::ExtensionId};
2
3use super::{Check, Checks, GetChecks};
4
5impl GetChecks for HttpData {
6 fn get_checks(
7 &self,
8 index: Option<usize>,
9 params: crate::check::CheckParams,
10 ) -> crate::check::Checks {
11 let mut items = vec![];
12
13 if let Some(allow_origin) = &self.access_control_allow_origin {
15 if !allow_origin.eq("*") {
16 items.push(Check::CorsAllowOriginStarRecommended.check_item())
17 }
18 } else {
19 items.push(Check::CorsAllowOriginRecommended.check_item())
20 }
21 if self.access_control_allow_credentials.is_some() {
22 items.push(Check::CorsAllowCredentialsNotRecommended.check_item())
23 }
24 if let Some(content_type) = &self.content_type {
25 if !content_type.starts_with(RDAP_MEDIA_TYPE) {
26 items.push(Check::ContentTypeIsNotRdap.check_item());
27 }
28 } else {
29 items.push(Check::ContentTypeIsAbsent.check_item());
30 }
31
32 if params
34 .root
35 .has_extension_id(ExtensionId::IcannRdapTechnicalImplementationGuide0)
36 || params
37 .root
38 .has_extension_id(ExtensionId::IcannRdapTechnicalImplementationGuide1)
39 {
40 if let Some(scheme) = &self.scheme {
41 if !scheme.eq_ignore_ascii_case("HTTPS") {
42 items.push(Check::MustUseHttps.check_item());
43 }
44 } else {
45 items.push(Check::MustUseHttps.check_item());
46 }
47 if let Some(allow_origin) = &self.access_control_allow_origin {
48 if !allow_origin.eq("*") {
49 items.push(Check::AllowOriginNotStar.check_item())
50 }
51 } else {
52 items.push(Check::AllowOriginNotStar.check_item())
53 }
54 }
55
56 Checks {
57 rdap_struct: super::RdapStructure::HttpData,
58 index,
59 items,
60 sub_checks: vec![],
61 }
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use crate::{
68 check::{Check, CheckParams, GetChecks},
69 httpdata::HttpData,
70 media_types::{JSON_MEDIA_TYPE, RDAP_MEDIA_TYPE},
71 prelude::{Common, ExtensionId, ObjectCommon, ToResponse},
72 response::domain::Domain,
73 };
74
75 #[test]
76 fn check_not_rdap_media() {
77 let domain = Domain {
79 common: Common::level0()
80 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
81 .build(),
82 object_common: ObjectCommon::domain().build(),
83 ldh_name: Some("foo.example".to_string()),
84 unicode_name: None,
85 variants: None,
86 secure_dns: None,
87 nameservers: None,
88 public_ids: None,
89 network: None,
90 };
91 let rdap = domain.to_response();
92
93 let http_data = HttpData::example().content_type(JSON_MEDIA_TYPE).build();
95
96 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
98
99 assert!(checks
101 .items
102 .iter()
103 .any(|c| c.check == Check::ContentTypeIsNotRdap));
104 }
105
106 #[test]
107 fn check_exactly_rdap_media() {
108 let domain = Domain {
110 common: Common::level0()
111 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
112 .build(),
113 object_common: ObjectCommon::domain().build(),
114 ldh_name: Some("foo.example".to_string()),
115 unicode_name: None,
116 variants: None,
117 secure_dns: None,
118 nameservers: None,
119 public_ids: None,
120 network: None,
121 };
122 let rdap = domain.to_response();
123
124 let http_data = HttpData::example().content_type(RDAP_MEDIA_TYPE).build();
126
127 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
129
130 assert!(!checks
132 .items
133 .iter()
134 .any(|c| c.check == Check::ContentTypeIsNotRdap));
135 }
136
137 #[test]
138 fn check_rdap_media_with_charset_parameter() {
139 let domain = Domain {
141 common: Common::level0()
142 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
143 .build(),
144 object_common: ObjectCommon::domain().build(),
145 ldh_name: Some("foo.example".to_string()),
146 unicode_name: None,
147 variants: None,
148 secure_dns: None,
149 nameservers: None,
150 public_ids: None,
151 network: None,
152 };
153 let rdap = domain.to_response();
154
155 let mt = format!("{RDAP_MEDIA_TYPE};charset=UTF-8");
157 let http_data = HttpData::example().content_type(mt).build();
158
159 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
161
162 assert!(!checks
164 .items
165 .iter()
166 .any(|c| c.check == Check::ContentTypeIsNotRdap));
167 }
168
169 #[test]
170 fn check_media_type_absent() {
171 let domain = Domain {
173 common: Common::level0()
174 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
175 .build(),
176 object_common: ObjectCommon::domain().build(),
177 ldh_name: Some("foo.example".to_string()),
178 unicode_name: None,
179 variants: None,
180 secure_dns: None,
181 nameservers: None,
182 public_ids: None,
183 network: None,
184 };
185 let rdap = domain.to_response();
186
187 let http_data = HttpData::example().build();
189
190 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
192
193 assert!(checks
195 .items
196 .iter()
197 .any(|c| c.check == Check::ContentTypeIsAbsent));
198 }
199
200 #[test]
201 fn check_cors_header_with_tig() {
202 let domain = Domain {
204 common: Common::level0()
205 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
206 .build(),
207 object_common: ObjectCommon::domain().build(),
208 ldh_name: Some("foo.example".to_string()),
209 unicode_name: None,
210 variants: None,
211 secure_dns: None,
212 nameservers: None,
213 public_ids: None,
214 network: None,
215 };
216 let rdap = domain.to_response();
217
218 let http_data = HttpData::example().access_control_allow_origin("*").build();
220
221 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
223
224 assert!(!checks
226 .items
227 .iter()
228 .any(|c| c.check == Check::AllowOriginNotStar));
229 }
230
231 #[test]
232 fn check_cors_header_with_foo_and_tig() {
233 let domain = Domain {
235 common: Common::level0()
236 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
237 .build(),
238 object_common: ObjectCommon::domain().build(),
239 ldh_name: Some("foo.example".to_string()),
240 unicode_name: None,
241 variants: None,
242 secure_dns: None,
243 nameservers: None,
244 public_ids: None,
245 network: None,
246 };
247 let rdap = domain.to_response();
248
249 let http_data = HttpData::example()
251 .access_control_allow_origin("foo")
252 .build();
253
254 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
256
257 assert!(checks
259 .items
260 .iter()
261 .any(|c| c.check == Check::AllowOriginNotStar));
262 }
263
264 #[test]
265 fn check_no_cors_header_and_tig() {
266 let domain = Domain {
268 common: Common::level0()
269 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
270 .build(),
271 object_common: ObjectCommon::domain().build(),
272 ldh_name: Some("foo.example".to_string()),
273 unicode_name: None,
274 variants: None,
275 secure_dns: None,
276 nameservers: None,
277 public_ids: None,
278 network: None,
279 };
280 let rdap = domain.to_response();
281
282 let http_data = HttpData::example().build();
284
285 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
287
288 dbg!(&checks);
290 assert!(checks
291 .items
292 .iter()
293 .any(|c| c.check == Check::AllowOriginNotStar));
294 }
295
296 #[test]
297 fn given_response_is_over_https_and_tig() {
298 let domain = Domain {
300 common: Common::level0()
301 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
302 .build(),
303 object_common: ObjectCommon::domain().build(),
304 ldh_name: Some("foo.example".to_string()),
305 unicode_name: None,
306 variants: None,
307 secure_dns: None,
308 nameservers: None,
309 public_ids: None,
310 network: None,
311 };
312 let rdap = domain.to_response();
313
314 let http_data = HttpData::now().scheme("https").host("example.com").build();
316
317 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
319
320 assert!(!checks.items.iter().any(|c| c.check == Check::MustUseHttps));
322 }
323
324 #[test]
325 fn response_over_htttp_and_tig() {
326 let domain = Domain {
328 common: Common::level0()
329 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
330 .build(),
331 object_common: ObjectCommon::domain().build(),
332 ldh_name: Some("foo.example".to_string()),
333 unicode_name: None,
334 variants: None,
335 secure_dns: None,
336 nameservers: None,
337 public_ids: None,
338 network: None,
339 };
340 let rdap = domain.to_response();
341
342 let http_data = HttpData::now().scheme("http").host("example.com").build();
344
345 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
347
348 assert!(checks.items.iter().any(|c| c.check == Check::MustUseHttps));
350 }
351}