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