capmonstercloud_client/requests/
imperva.rs1use serde::Serialize;
2
3use super::{require_non_empty, CaptchaRequest};
4use crate::error::Result;
5use crate::proxy::ProxyInfo;
6use crate::timeouts::GetResultTimeouts;
7
8#[derive(Debug, Clone, Serialize)]
11pub struct ImpervaMetadata {
12 #[serde(rename = "incapsulaScriptUrl")]
14 pub incapsula_script_url: String,
15 #[serde(rename = "incapsulaCookies")]
17 pub incapsula_cookies: String,
18 #[serde(rename = "reese84UrlEndpoint", skip_serializing_if = "Option::is_none")]
20 pub reese84_url_endpoint: Option<String>,
21}
22
23impl ImpervaMetadata {
24 pub fn new(
25 incapsula_script_url: impl Into<String>,
26 incapsula_cookies: impl Into<String>,
27 ) -> Self {
28 Self {
29 incapsula_script_url: incapsula_script_url.into(),
30 incapsula_cookies: incapsula_cookies.into(),
31 reese84_url_endpoint: None,
32 }
33 }
34
35 pub fn with_reese84_url_endpoint(mut self, value: impl Into<String>) -> Self {
36 self.reese84_url_endpoint = Some(value.into());
37 self
38 }
39}
40
41#[derive(Debug, Clone, Serialize)]
43pub struct ImpervaCustomTaskRequest {
44 #[serde(rename = "websiteURL")]
46 pub website_url: String,
47 pub metadata: ImpervaMetadata,
48 #[serde(flatten)]
50 pub proxy: ProxyInfo,
51 #[serde(rename = "userAgent", skip_serializing_if = "Option::is_none")]
53 pub user_agent: Option<String>,
54}
55
56impl ImpervaCustomTaskRequest {
57 pub fn new(
58 website_url: impl Into<String>,
59 metadata: ImpervaMetadata,
60 proxy: ProxyInfo,
61 ) -> Self {
62 Self {
63 website_url: website_url.into(),
64 metadata,
65 proxy,
66 user_agent: None,
67 }
68 }
69
70 pub fn with_user_agent(mut self, value: impl Into<String>) -> Self {
71 self.user_agent = Some(value.into());
72 self
73 }
74}
75
76impl CaptchaRequest for ImpervaCustomTaskRequest {
77 const TASK_TYPE: &'static str = "CustomTask";
78 const CLASS: Option<&'static str> = Some("Imperva");
79
80 fn timeouts(&self) -> GetResultTimeouts {
81 GetResultTimeouts::secs(1.0, 0.0, 1.0, 15.0)
82 }
83
84 fn validate(&self) -> Result<()> {
85 require_non_empty("websiteURL", &self.website_url)?;
86 require_non_empty(
87 "metadata.incapsulaScriptUrl",
88 &self.metadata.incapsula_script_url,
89 )?;
90 require_non_empty(
91 "metadata.incapsulaCookies",
92 &self.metadata.incapsula_cookies,
93 )?;
94 Ok(())
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use crate::proxy::ProxyType;
102 use serde_json::json;
103
104 fn proxy() -> ProxyInfo {
105 ProxyInfo::new(ProxyType::Socks5, "1.2.3.4", 1080).with_auth("u", "p")
106 }
107
108 #[test]
109 fn minimal_task() {
110 let task = ImpervaCustomTaskRequest::new(
111 "https://example.com",
112 ImpervaMetadata::new("_Incapsula_Resource?x=1", "incap_sess_1=a"),
113 proxy(),
114 )
115 .to_task()
116 .unwrap();
117 assert_eq!(
118 task,
119 json!({
120 "type": "CustomTask", "class": "Imperva", "websiteURL": "https://example.com",
121 "metadata": {"incapsulaScriptUrl": "_Incapsula_Resource?x=1", "incapsulaCookies": "incap_sess_1=a"},
122 "proxyType": "socks5", "proxyAddress": "1.2.3.4", "proxyPort": 1080,
123 "proxyLogin": "u", "proxyPassword": "p"
124 })
125 );
126 }
127
128 #[test]
129 fn full_task() {
130 let task = ImpervaCustomTaskRequest::new(
131 "https://example.com",
132 ImpervaMetadata::new("S", "C").with_reese84_url_endpoint("E?d=example.com"),
133 proxy(),
134 )
135 .with_user_agent("UA")
136 .to_task()
137 .unwrap();
138 assert_eq!(
139 task,
140 json!({
141 "type": "CustomTask", "class": "Imperva", "websiteURL": "https://example.com",
142 "metadata": {"incapsulaScriptUrl": "S", "incapsulaCookies": "C", "reese84UrlEndpoint": "E?d=example.com"},
143 "proxyType": "socks5", "proxyAddress": "1.2.3.4", "proxyPort": 1080,
144 "proxyLogin": "u", "proxyPassword": "p", "userAgent": "UA"
145 })
146 );
147 }
148
149 #[test]
150 fn empty_required_strings_are_rejected() {
151 let err = ImpervaCustomTaskRequest::new("", ImpervaMetadata::new("S", "C"), proxy())
152 .to_task()
153 .unwrap_err();
154 assert!(matches!(err, crate::error::Error::Validation(ref m) if m.contains("websiteURL")));
155 let err = ImpervaCustomTaskRequest::new(
156 "https://example.com",
157 ImpervaMetadata::new("", "C"),
158 proxy(),
159 )
160 .to_task()
161 .unwrap_err();
162 assert!(
163 matches!(err, crate::error::Error::Validation(ref m) if m.contains("metadata.incapsulaScriptUrl"))
164 );
165 let err = ImpervaCustomTaskRequest::new(
166 "https://example.com",
167 ImpervaMetadata::new("S", ""),
168 proxy(),
169 )
170 .to_task()
171 .unwrap_err();
172 assert!(
173 matches!(err, crate::error::Error::Validation(ref m) if m.contains("metadata.incapsulaCookies"))
174 );
175 }
176}