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 ttl0_data: None,
91 };
92 let rdap = domain.to_response();
93
94 let http_data = HttpData::example().content_type(JSON_MEDIA_TYPE).build();
96
97 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
99
100 assert!(checks
102 .items
103 .iter()
104 .any(|c| c.check == Check::ContentTypeIsNotRdap));
105 }
106
107 #[test]
108 fn check_exactly_rdap_media() {
109 let domain = Domain {
111 common: Common::level0()
112 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
113 .build(),
114 object_common: ObjectCommon::domain().build(),
115 ldh_name: Some("foo.example".to_string()),
116 unicode_name: None,
117 variants: None,
118 secure_dns: None,
119 nameservers: None,
120 public_ids: None,
121 network: None,
122 ttl0_data: None,
123 };
124 let rdap = domain.to_response();
125
126 let http_data = HttpData::example().content_type(RDAP_MEDIA_TYPE).build();
128
129 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
131
132 assert!(!checks
134 .items
135 .iter()
136 .any(|c| c.check == Check::ContentTypeIsNotRdap));
137 }
138
139 #[test]
140 fn check_rdap_media_with_charset_parameter() {
141 let domain = Domain {
143 common: Common::level0()
144 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
145 .build(),
146 object_common: ObjectCommon::domain().build(),
147 ldh_name: Some("foo.example".to_string()),
148 unicode_name: None,
149 variants: None,
150 secure_dns: None,
151 nameservers: None,
152 public_ids: None,
153 network: None,
154 ttl0_data: None,
155 };
156 let rdap = domain.to_response();
157
158 let mt = format!("{RDAP_MEDIA_TYPE};charset=UTF-8");
160 let http_data = HttpData::example().content_type(mt).build();
161
162 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
164
165 assert!(!checks
167 .items
168 .iter()
169 .any(|c| c.check == Check::ContentTypeIsNotRdap));
170 }
171
172 #[test]
173 fn check_media_type_absent() {
174 let domain = Domain {
176 common: Common::level0()
177 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
178 .build(),
179 object_common: ObjectCommon::domain().build(),
180 ldh_name: Some("foo.example".to_string()),
181 unicode_name: None,
182 variants: None,
183 secure_dns: None,
184 nameservers: None,
185 public_ids: None,
186 network: None,
187 ttl0_data: None,
188 };
189 let rdap = domain.to_response();
190
191 let http_data = HttpData::example().build();
193
194 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
196
197 assert!(checks
199 .items
200 .iter()
201 .any(|c| c.check == Check::ContentTypeIsAbsent));
202 }
203
204 #[test]
205 fn check_cors_header_with_tig() {
206 let domain = Domain {
208 common: Common::level0()
209 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
210 .build(),
211 object_common: ObjectCommon::domain().build(),
212 ldh_name: Some("foo.example".to_string()),
213 unicode_name: None,
214 variants: None,
215 secure_dns: None,
216 nameservers: None,
217 public_ids: None,
218 network: None,
219 ttl0_data: None,
220 };
221 let rdap = domain.to_response();
222
223 let http_data = HttpData::example().access_control_allow_origin("*").build();
225
226 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
228
229 assert!(!checks
231 .items
232 .iter()
233 .any(|c| c.check == Check::AllowOriginNotStar));
234 }
235
236 #[test]
237 fn check_cors_header_with_foo_and_tig() {
238 let domain = Domain {
240 common: Common::level0()
241 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
242 .build(),
243 object_common: ObjectCommon::domain().build(),
244 ldh_name: Some("foo.example".to_string()),
245 unicode_name: None,
246 variants: None,
247 secure_dns: None,
248 nameservers: None,
249 public_ids: None,
250 network: None,
251 ttl0_data: None,
252 };
253 let rdap = domain.to_response();
254
255 let http_data = HttpData::example()
257 .access_control_allow_origin("foo")
258 .build();
259
260 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
262
263 assert!(checks
265 .items
266 .iter()
267 .any(|c| c.check == Check::AllowOriginNotStar));
268 }
269
270 #[test]
271 fn check_no_cors_header_and_tig() {
272 let domain = Domain {
274 common: Common::level0()
275 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
276 .build(),
277 object_common: ObjectCommon::domain().build(),
278 ldh_name: Some("foo.example".to_string()),
279 unicode_name: None,
280 variants: None,
281 secure_dns: None,
282 nameservers: None,
283 public_ids: None,
284 network: None,
285 ttl0_data: None,
286 };
287 let rdap = domain.to_response();
288
289 let http_data = HttpData::example().build();
291
292 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
294
295 dbg!(&checks);
297 assert!(checks
298 .items
299 .iter()
300 .any(|c| c.check == Check::AllowOriginNotStar));
301 }
302
303 #[test]
304 fn given_response_is_over_https_and_tig() {
305 let domain = Domain {
307 common: Common::level0()
308 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
309 .build(),
310 object_common: ObjectCommon::domain().build(),
311 ldh_name: Some("foo.example".to_string()),
312 unicode_name: None,
313 variants: None,
314 secure_dns: None,
315 nameservers: None,
316 public_ids: None,
317 network: None,
318 ttl0_data: None,
319 };
320 let rdap = domain.to_response();
321
322 let http_data = HttpData::now().scheme("https").host("example.com").build();
324
325 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
327
328 assert!(!checks.items.iter().any(|c| c.check == Check::MustUseHttps));
330 }
331
332 #[test]
333 fn response_over_http_and_tig() {
334 let domain = Domain {
336 common: Common::level0()
337 .extension(ExtensionId::IcannRdapTechnicalImplementationGuide0.to_extension())
338 .build(),
339 object_common: ObjectCommon::domain().build(),
340 ldh_name: Some("foo.example".to_string()),
341 unicode_name: None,
342 variants: None,
343 secure_dns: None,
344 nameservers: None,
345 public_ids: None,
346 network: None,
347 ttl0_data: None,
348 };
349 let rdap = domain.to_response();
350
351 let http_data = HttpData::now().scheme("http").host("example.com").build();
353
354 let checks = http_data.get_checks(None, CheckParams::for_rdap(&rdap));
356
357 assert!(checks.items.iter().any(|c| c.check == Check::MustUseHttps));
359 }
360}