crawlberg 1.7.2 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/crawlberg_rb/native/Cargo.lock +433 -160
- data/ext/crawlberg_rb/native/Cargo.toml +3 -3
- data/ext/crawlberg_rb/src/lib.rs +574 -11
- data/lib/crawlberg/version.rb +2 -2
- data/sig/types.rbs +29 -8
- metadata +2 -2
data/ext/crawlberg_rb/src/lib.rs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// This file is auto-generated by alef. DO NOT EDIT.
|
|
2
|
-
// alef:hash:
|
|
2
|
+
// alef:hash:51d55e2247bdc2514829f3eaafb5c8524624f269469856210cf0950e6c206e7f
|
|
3
3
|
// Re-generate with: alef generate
|
|
4
4
|
#![allow(dead_code, unused_imports, unused_variables)]
|
|
5
5
|
#![allow(
|
|
@@ -821,7 +821,7 @@ impl BatchScrapeResults {
|
|
|
821
821
|
}
|
|
822
822
|
}
|
|
823
823
|
|
|
824
|
-
#[derive(Clone,
|
|
824
|
+
#[derive(Clone, serde::Serialize)]
|
|
825
825
|
#[serde(default)]
|
|
826
826
|
#[magnus::wrap(class = "Crawlberg::BrowserConfig")]
|
|
827
827
|
pub struct BrowserConfig {
|
|
@@ -830,6 +830,8 @@ pub struct BrowserConfig {
|
|
|
830
830
|
endpoint: Option<String>,
|
|
831
831
|
#[serde(default = "default_timeout")]
|
|
832
832
|
timeout: u64,
|
|
833
|
+
overall_timeout: u64,
|
|
834
|
+
shutdown_timeout: u64,
|
|
833
835
|
wait: BrowserWait,
|
|
834
836
|
wait_selector: Option<String>,
|
|
835
837
|
extra_wait: Option<u64>,
|
|
@@ -839,6 +841,8 @@ pub struct BrowserConfig {
|
|
|
839
841
|
robots_user_agent: Option<String>,
|
|
840
842
|
capture_network_events: bool,
|
|
841
843
|
session_affinity: bool,
|
|
844
|
+
chrome_path: Option<String>,
|
|
845
|
+
chrome_args: Vec<String>,
|
|
842
846
|
}
|
|
843
847
|
|
|
844
848
|
unsafe impl IntoValueFromNative for BrowserConfig {}
|
|
@@ -868,6 +872,29 @@ impl magnus::TryConvert for BrowserConfig {
|
|
|
868
872
|
}
|
|
869
873
|
|
|
870
874
|
unsafe impl TryConvertOwned for BrowserConfig {}
|
|
875
|
+
impl std::fmt::Debug for BrowserConfig {
|
|
876
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
877
|
+
let mut debug = f.debug_struct("BrowserConfig");
|
|
878
|
+
debug.field("mode", &self.mode);
|
|
879
|
+
debug.field("backend", &self.backend);
|
|
880
|
+
debug.field("endpoint", &"<redacted>");
|
|
881
|
+
debug.field("timeout", &self.timeout);
|
|
882
|
+
debug.field("overall_timeout", &self.overall_timeout);
|
|
883
|
+
debug.field("shutdown_timeout", &self.shutdown_timeout);
|
|
884
|
+
debug.field("wait", &self.wait);
|
|
885
|
+
debug.field("wait_selector", &self.wait_selector);
|
|
886
|
+
debug.field("extra_wait", &self.extra_wait);
|
|
887
|
+
debug.field("proxy", &self.proxy);
|
|
888
|
+
debug.field("block_url_patterns", &self.block_url_patterns);
|
|
889
|
+
debug.field("eval_script", &"<redacted>");
|
|
890
|
+
debug.field("robots_user_agent", &self.robots_user_agent);
|
|
891
|
+
debug.field("capture_network_events", &self.capture_network_events);
|
|
892
|
+
debug.field("session_affinity", &self.session_affinity);
|
|
893
|
+
debug.field("chrome_path", &self.chrome_path);
|
|
894
|
+
debug.field("chrome_args", &"<redacted>");
|
|
895
|
+
debug.finish()
|
|
896
|
+
}
|
|
897
|
+
}
|
|
871
898
|
impl<'de> serde::Deserialize<'de> for BrowserConfig {
|
|
872
899
|
fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
|
|
873
900
|
where
|
|
@@ -926,6 +953,24 @@ impl BrowserConfig {
|
|
|
926
953
|
})?,
|
|
927
954
|
None => 30000,
|
|
928
955
|
},
|
|
956
|
+
overall_timeout: match kwargs.get(ruby.to_symbol("overall_timeout")) {
|
|
957
|
+
Some(v) => u64::try_convert(v).map_err(|e| {
|
|
958
|
+
magnus::Error::new(
|
|
959
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
960
|
+
format!("invalid value for `overall_timeout`: {}", e),
|
|
961
|
+
)
|
|
962
|
+
})?,
|
|
963
|
+
None => 60000,
|
|
964
|
+
},
|
|
965
|
+
shutdown_timeout: match kwargs.get(ruby.to_symbol("shutdown_timeout")) {
|
|
966
|
+
Some(v) => u64::try_convert(v).map_err(|e| {
|
|
967
|
+
magnus::Error::new(
|
|
968
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
969
|
+
format!("invalid value for `shutdown_timeout`: {}", e),
|
|
970
|
+
)
|
|
971
|
+
})?,
|
|
972
|
+
None => 5000,
|
|
973
|
+
},
|
|
929
974
|
wait: match kwargs.get(ruby.to_symbol("wait")) {
|
|
930
975
|
Some(v) => BrowserWait::try_convert(v).map_err(|e| {
|
|
931
976
|
magnus::Error::new(
|
|
@@ -1007,6 +1052,24 @@ impl BrowserConfig {
|
|
|
1007
1052
|
})?,
|
|
1008
1053
|
None => true,
|
|
1009
1054
|
},
|
|
1055
|
+
chrome_path: match kwargs.get(ruby.to_symbol("chrome_path")).filter(|v| !v.is_nil()) {
|
|
1056
|
+
Some(v) => Some(String::try_convert(v).map_err(|e| {
|
|
1057
|
+
magnus::Error::new(
|
|
1058
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
1059
|
+
format!("invalid value for `chrome_path`: {}", e),
|
|
1060
|
+
)
|
|
1061
|
+
})?),
|
|
1062
|
+
None => None,
|
|
1063
|
+
},
|
|
1064
|
+
chrome_args: match kwargs.get(ruby.to_symbol("chrome_args")) {
|
|
1065
|
+
Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
|
|
1066
|
+
magnus::Error::new(
|
|
1067
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
1068
|
+
format!("invalid value for `chrome_args`: {}", e),
|
|
1069
|
+
)
|
|
1070
|
+
})?,
|
|
1071
|
+
None => Default::default(),
|
|
1072
|
+
},
|
|
1010
1073
|
})
|
|
1011
1074
|
}
|
|
1012
1075
|
|
|
@@ -1026,6 +1089,14 @@ impl BrowserConfig {
|
|
|
1026
1089
|
self.timeout.clone()
|
|
1027
1090
|
}
|
|
1028
1091
|
|
|
1092
|
+
fn overall_timeout(&self) -> u64 {
|
|
1093
|
+
self.overall_timeout.clone()
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
fn shutdown_timeout(&self) -> u64 {
|
|
1097
|
+
self.shutdown_timeout.clone()
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1029
1100
|
fn wait(&self) -> BrowserWait {
|
|
1030
1101
|
self.wait.clone()
|
|
1031
1102
|
}
|
|
@@ -1061,6 +1132,14 @@ impl BrowserConfig {
|
|
|
1061
1132
|
fn session_affinity(&self) -> bool {
|
|
1062
1133
|
self.session_affinity
|
|
1063
1134
|
}
|
|
1135
|
+
|
|
1136
|
+
fn chrome_path(&self) -> Option<String> {
|
|
1137
|
+
self.chrome_path.clone()
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
fn chrome_args(&self) -> Vec<String> {
|
|
1141
|
+
self.chrome_args.clone()
|
|
1142
|
+
}
|
|
1064
1143
|
}
|
|
1065
1144
|
|
|
1066
1145
|
#[derive(Clone, Debug, serde::Serialize)]
|
|
@@ -1357,6 +1436,7 @@ pub struct ContentConfig {
|
|
|
1357
1436
|
wrap: bool,
|
|
1358
1437
|
wrap_width: usize,
|
|
1359
1438
|
include_document_structure: bool,
|
|
1439
|
+
extract_metadata: bool,
|
|
1360
1440
|
}
|
|
1361
1441
|
|
|
1362
1442
|
unsafe impl IntoValueFromNative for ContentConfig {}
|
|
@@ -1516,6 +1596,15 @@ impl ContentConfig {
|
|
|
1516
1596
|
})?,
|
|
1517
1597
|
None => true,
|
|
1518
1598
|
},
|
|
1599
|
+
extract_metadata: match kwargs.get(ruby.to_symbol("extract_metadata")) {
|
|
1600
|
+
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
1601
|
+
magnus::Error::new(
|
|
1602
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
1603
|
+
format!("invalid value for `extract_metadata`: {}", e),
|
|
1604
|
+
)
|
|
1605
|
+
})?,
|
|
1606
|
+
None => true,
|
|
1607
|
+
},
|
|
1519
1608
|
})
|
|
1520
1609
|
}
|
|
1521
1610
|
|
|
@@ -1566,9 +1655,13 @@ impl ContentConfig {
|
|
|
1566
1655
|
fn include_document_structure(&self) -> bool {
|
|
1567
1656
|
self.include_document_structure
|
|
1568
1657
|
}
|
|
1658
|
+
|
|
1659
|
+
fn extract_metadata(&self) -> bool {
|
|
1660
|
+
self.extract_metadata
|
|
1661
|
+
}
|
|
1569
1662
|
}
|
|
1570
1663
|
|
|
1571
|
-
#[derive(Clone,
|
|
1664
|
+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
|
1572
1665
|
#[serde(default)]
|
|
1573
1666
|
#[magnus::wrap(class = "Crawlberg::CookieInfo")]
|
|
1574
1667
|
pub struct CookieInfo {
|
|
@@ -1605,6 +1698,16 @@ impl magnus::TryConvert for CookieInfo {
|
|
|
1605
1698
|
}
|
|
1606
1699
|
|
|
1607
1700
|
unsafe impl TryConvertOwned for CookieInfo {}
|
|
1701
|
+
impl std::fmt::Debug for CookieInfo {
|
|
1702
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
1703
|
+
let mut debug = f.debug_struct("CookieInfo");
|
|
1704
|
+
debug.field("name", &self.name);
|
|
1705
|
+
debug.field("value", &"<redacted>");
|
|
1706
|
+
debug.field("domain", &self.domain);
|
|
1707
|
+
debug.field("path", &self.path);
|
|
1708
|
+
debug.finish()
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1608
1711
|
|
|
1609
1712
|
impl Default for CookieInfo {
|
|
1610
1713
|
fn default() -> Self {
|
|
@@ -1675,7 +1778,7 @@ impl CookieInfo {
|
|
|
1675
1778
|
}
|
|
1676
1779
|
}
|
|
1677
1780
|
|
|
1678
|
-
#[derive(Clone,
|
|
1781
|
+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
|
1679
1782
|
#[serde(default)]
|
|
1680
1783
|
#[magnus::wrap(class = "Crawlberg::CrawlConfig")]
|
|
1681
1784
|
pub struct CrawlConfig {
|
|
@@ -1694,6 +1797,11 @@ pub struct CrawlConfig {
|
|
|
1694
1797
|
allow_subdomains: bool,
|
|
1695
1798
|
include_paths: Vec<String>,
|
|
1696
1799
|
exclude_paths: Vec<String>,
|
|
1800
|
+
path_patterns_match_query: bool,
|
|
1801
|
+
path_patterns_match_url: bool,
|
|
1802
|
+
dedup_include_query: bool,
|
|
1803
|
+
strip_tracking_params: bool,
|
|
1804
|
+
tracking_params: Vec<String>,
|
|
1697
1805
|
custom_headers: HashMap<String, String>,
|
|
1698
1806
|
#[serde(default = "default_timeout")]
|
|
1699
1807
|
request_timeout: u64,
|
|
@@ -1701,6 +1809,9 @@ pub struct CrawlConfig {
|
|
|
1701
1809
|
max_redirects: usize,
|
|
1702
1810
|
retry_count: usize,
|
|
1703
1811
|
retry_codes: Vec<u16>,
|
|
1812
|
+
retry_initial_delay_ms: u64,
|
|
1813
|
+
retry_max_delay_ms: u64,
|
|
1814
|
+
rate_limit_jitter_ratio: f64,
|
|
1704
1815
|
cookies_enabled: bool,
|
|
1705
1816
|
auth: Option<AuthConfig>,
|
|
1706
1817
|
max_body_size: Option<usize>,
|
|
@@ -1756,6 +1867,67 @@ impl magnus::TryConvert for CrawlConfig {
|
|
|
1756
1867
|
}
|
|
1757
1868
|
|
|
1758
1869
|
unsafe impl TryConvertOwned for CrawlConfig {}
|
|
1870
|
+
impl std::fmt::Debug for CrawlConfig {
|
|
1871
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
1872
|
+
let mut debug = f.debug_struct("CrawlConfig");
|
|
1873
|
+
debug.field("max_depth", &self.max_depth);
|
|
1874
|
+
debug.field("max_pages", &self.max_pages);
|
|
1875
|
+
debug.field("max_links_per_page", &self.max_links_per_page);
|
|
1876
|
+
debug.field("max_concurrent", &self.max_concurrent);
|
|
1877
|
+
debug.field("crawl_strategy", &self.crawl_strategy);
|
|
1878
|
+
debug.field("content_filter", &self.content_filter);
|
|
1879
|
+
debug.field("bm25_query", &self.bm25_query);
|
|
1880
|
+
debug.field("bm25_threshold", &self.bm25_threshold);
|
|
1881
|
+
debug.field("respect_robots_txt", &self.respect_robots_txt);
|
|
1882
|
+
debug.field("soft_http_errors", &self.soft_http_errors);
|
|
1883
|
+
debug.field("user_agent", &self.user_agent);
|
|
1884
|
+
debug.field("stay_on_domain", &self.stay_on_domain);
|
|
1885
|
+
debug.field("allow_subdomains", &self.allow_subdomains);
|
|
1886
|
+
debug.field("include_paths", &self.include_paths);
|
|
1887
|
+
debug.field("exclude_paths", &self.exclude_paths);
|
|
1888
|
+
debug.field("path_patterns_match_query", &self.path_patterns_match_query);
|
|
1889
|
+
debug.field("path_patterns_match_url", &self.path_patterns_match_url);
|
|
1890
|
+
debug.field("dedup_include_query", &self.dedup_include_query);
|
|
1891
|
+
debug.field("strip_tracking_params", &self.strip_tracking_params);
|
|
1892
|
+
debug.field("tracking_params", &self.tracking_params);
|
|
1893
|
+
debug.field("custom_headers", &"<redacted>");
|
|
1894
|
+
debug.field("request_timeout", &self.request_timeout);
|
|
1895
|
+
debug.field("rate_limit_ms", &self.rate_limit_ms);
|
|
1896
|
+
debug.field("max_redirects", &self.max_redirects);
|
|
1897
|
+
debug.field("retry_count", &self.retry_count);
|
|
1898
|
+
debug.field("retry_codes", &self.retry_codes);
|
|
1899
|
+
debug.field("retry_initial_delay_ms", &self.retry_initial_delay_ms);
|
|
1900
|
+
debug.field("retry_max_delay_ms", &self.retry_max_delay_ms);
|
|
1901
|
+
debug.field("rate_limit_jitter_ratio", &self.rate_limit_jitter_ratio);
|
|
1902
|
+
debug.field("cookies_enabled", &self.cookies_enabled);
|
|
1903
|
+
debug.field("auth", &self.auth);
|
|
1904
|
+
debug.field("max_body_size", &self.max_body_size);
|
|
1905
|
+
debug.field("remove_tags", &self.remove_tags);
|
|
1906
|
+
debug.field("content", &self.content);
|
|
1907
|
+
debug.field("map_limit", &self.map_limit);
|
|
1908
|
+
debug.field("map_search", &self.map_search);
|
|
1909
|
+
debug.field("download_assets", &self.download_assets);
|
|
1910
|
+
debug.field("asset_types", &self.asset_types);
|
|
1911
|
+
debug.field("max_asset_size", &self.max_asset_size);
|
|
1912
|
+
debug.field("browser", &self.browser);
|
|
1913
|
+
debug.field("proxy", &self.proxy);
|
|
1914
|
+
debug.field("user_agents", &self.user_agents);
|
|
1915
|
+
debug.field("capture_screenshot", &self.capture_screenshot);
|
|
1916
|
+
debug.field("follow_document_urls", &self.follow_document_urls);
|
|
1917
|
+
debug.field("document_url_depth", &self.document_url_depth);
|
|
1918
|
+
debug.field("download_documents", &self.download_documents);
|
|
1919
|
+
debug.field("document_max_size", &self.document_max_size);
|
|
1920
|
+
debug.field("document_mime_types", &self.document_mime_types);
|
|
1921
|
+
debug.field("document_output_dir", &self.document_output_dir);
|
|
1922
|
+
debug.field("document_content_encoding", &self.document_content_encoding);
|
|
1923
|
+
debug.field("warc_output", &self.warc_output);
|
|
1924
|
+
debug.field("browser_profile", &self.browser_profile);
|
|
1925
|
+
debug.field("save_browser_profile", &self.save_browser_profile);
|
|
1926
|
+
debug.field("ssrf", &self.ssrf);
|
|
1927
|
+
debug.field("ssrf_deny_private_explicit", &self.ssrf_deny_private_explicit);
|
|
1928
|
+
debug.finish()
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1759
1931
|
|
|
1760
1932
|
impl Default for CrawlConfig {
|
|
1761
1933
|
fn default() -> Self {
|
|
@@ -1905,6 +2077,56 @@ impl CrawlConfig {
|
|
|
1905
2077
|
})?,
|
|
1906
2078
|
None => Default::default(),
|
|
1907
2079
|
},
|
|
2080
|
+
path_patterns_match_query: match kwargs.get(ruby.to_symbol("path_patterns_match_query")) {
|
|
2081
|
+
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
2082
|
+
magnus::Error::new(
|
|
2083
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2084
|
+
format!("invalid value for `path_patterns_match_query`: {}", e),
|
|
2085
|
+
)
|
|
2086
|
+
})?,
|
|
2087
|
+
None => false,
|
|
2088
|
+
},
|
|
2089
|
+
path_patterns_match_url: match kwargs.get(ruby.to_symbol("path_patterns_match_url")) {
|
|
2090
|
+
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
2091
|
+
magnus::Error::new(
|
|
2092
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2093
|
+
format!("invalid value for `path_patterns_match_url`: {}", e),
|
|
2094
|
+
)
|
|
2095
|
+
})?,
|
|
2096
|
+
None => false,
|
|
2097
|
+
},
|
|
2098
|
+
dedup_include_query: match kwargs.get(ruby.to_symbol("dedup_include_query")) {
|
|
2099
|
+
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
2100
|
+
magnus::Error::new(
|
|
2101
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2102
|
+
format!("invalid value for `dedup_include_query`: {}", e),
|
|
2103
|
+
)
|
|
2104
|
+
})?,
|
|
2105
|
+
None => false,
|
|
2106
|
+
},
|
|
2107
|
+
strip_tracking_params: match kwargs.get(ruby.to_symbol("strip_tracking_params")) {
|
|
2108
|
+
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
2109
|
+
magnus::Error::new(
|
|
2110
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2111
|
+
format!("invalid value for `strip_tracking_params`: {}", e),
|
|
2112
|
+
)
|
|
2113
|
+
})?,
|
|
2114
|
+
None => false,
|
|
2115
|
+
},
|
|
2116
|
+
tracking_params: match kwargs.get(ruby.to_symbol("tracking_params")) {
|
|
2117
|
+
Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
|
|
2118
|
+
magnus::Error::new(
|
|
2119
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2120
|
+
format!("invalid value for `tracking_params`: {}", e),
|
|
2121
|
+
)
|
|
2122
|
+
})?,
|
|
2123
|
+
None => vec![
|
|
2124
|
+
"utm_*".to_string(),
|
|
2125
|
+
"fbclid".to_string(),
|
|
2126
|
+
"gclid".to_string(),
|
|
2127
|
+
"ref".to_string(),
|
|
2128
|
+
],
|
|
2129
|
+
},
|
|
1908
2130
|
custom_headers: match kwargs.get(ruby.to_symbol("custom_headers")) {
|
|
1909
2131
|
Some(v) => <HashMap<String, String>>::try_convert(v).map_err(|e| {
|
|
1910
2132
|
magnus::Error::new(
|
|
@@ -1959,6 +2181,33 @@ impl CrawlConfig {
|
|
|
1959
2181
|
})?,
|
|
1960
2182
|
None => Default::default(),
|
|
1961
2183
|
},
|
|
2184
|
+
retry_initial_delay_ms: match kwargs.get(ruby.to_symbol("retry_initial_delay_ms")) {
|
|
2185
|
+
Some(v) => u64::try_convert(v).map_err(|e| {
|
|
2186
|
+
magnus::Error::new(
|
|
2187
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2188
|
+
format!("invalid value for `retry_initial_delay_ms`: {}", e),
|
|
2189
|
+
)
|
|
2190
|
+
})?,
|
|
2191
|
+
None => 100,
|
|
2192
|
+
},
|
|
2193
|
+
retry_max_delay_ms: match kwargs.get(ruby.to_symbol("retry_max_delay_ms")) {
|
|
2194
|
+
Some(v) => u64::try_convert(v).map_err(|e| {
|
|
2195
|
+
magnus::Error::new(
|
|
2196
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2197
|
+
format!("invalid value for `retry_max_delay_ms`: {}", e),
|
|
2198
|
+
)
|
|
2199
|
+
})?,
|
|
2200
|
+
None => 60000,
|
|
2201
|
+
},
|
|
2202
|
+
rate_limit_jitter_ratio: match kwargs.get(ruby.to_symbol("rate_limit_jitter_ratio")) {
|
|
2203
|
+
Some(v) => f64::try_convert(v).map_err(|e| {
|
|
2204
|
+
magnus::Error::new(
|
|
2205
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
2206
|
+
format!("invalid value for `rate_limit_jitter_ratio`: {}", e),
|
|
2207
|
+
)
|
|
2208
|
+
})?,
|
|
2209
|
+
None => 0.0,
|
|
2210
|
+
},
|
|
1962
2211
|
cookies_enabled: match kwargs.get(ruby.to_symbol("cookies_enabled")) {
|
|
1963
2212
|
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
1964
2213
|
magnus::Error::new(
|
|
@@ -2265,6 +2514,26 @@ impl CrawlConfig {
|
|
|
2265
2514
|
self.exclude_paths.clone()
|
|
2266
2515
|
}
|
|
2267
2516
|
|
|
2517
|
+
fn path_patterns_match_query(&self) -> bool {
|
|
2518
|
+
self.path_patterns_match_query
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
fn path_patterns_match_url(&self) -> bool {
|
|
2522
|
+
self.path_patterns_match_url
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
fn dedup_include_query(&self) -> bool {
|
|
2526
|
+
self.dedup_include_query
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
fn strip_tracking_params(&self) -> bool {
|
|
2530
|
+
self.strip_tracking_params
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2533
|
+
fn tracking_params(&self) -> Vec<String> {
|
|
2534
|
+
self.tracking_params.clone()
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2268
2537
|
fn custom_headers(&self) -> HashMap<String, String> {
|
|
2269
2538
|
self.custom_headers.clone()
|
|
2270
2539
|
}
|
|
@@ -2289,6 +2558,18 @@ impl CrawlConfig {
|
|
|
2289
2558
|
self.retry_codes.clone()
|
|
2290
2559
|
}
|
|
2291
2560
|
|
|
2561
|
+
fn retry_initial_delay_ms(&self) -> u64 {
|
|
2562
|
+
self.retry_initial_delay_ms
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
fn retry_max_delay_ms(&self) -> u64 {
|
|
2566
|
+
self.retry_max_delay_ms
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
fn rate_limit_jitter_ratio(&self) -> f64 {
|
|
2570
|
+
self.rate_limit_jitter_ratio
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2292
2573
|
fn cookies_enabled(&self) -> bool {
|
|
2293
2574
|
self.cookies_enabled
|
|
2294
2575
|
}
|
|
@@ -2426,6 +2707,16 @@ impl CrawlConfig {
|
|
|
2426
2707
|
|
|
2427
2708
|
exclude_paths: self.exclude_paths.clone(),
|
|
2428
2709
|
|
|
2710
|
+
path_patterns_match_query: self.path_patterns_match_query,
|
|
2711
|
+
|
|
2712
|
+
path_patterns_match_url: self.path_patterns_match_url,
|
|
2713
|
+
|
|
2714
|
+
dedup_include_query: self.dedup_include_query,
|
|
2715
|
+
|
|
2716
|
+
strip_tracking_params: self.strip_tracking_params,
|
|
2717
|
+
|
|
2718
|
+
tracking_params: self.tracking_params.clone(),
|
|
2719
|
+
|
|
2429
2720
|
custom_headers: self
|
|
2430
2721
|
.custom_headers
|
|
2431
2722
|
.clone()
|
|
@@ -2443,6 +2734,12 @@ impl CrawlConfig {
|
|
|
2443
2734
|
|
|
2444
2735
|
retry_codes: self.retry_codes.clone(),
|
|
2445
2736
|
|
|
2737
|
+
retry_initial_delay_ms: self.retry_initial_delay_ms,
|
|
2738
|
+
|
|
2739
|
+
retry_max_delay_ms: self.retry_max_delay_ms,
|
|
2740
|
+
|
|
2741
|
+
rate_limit_jitter_ratio: self.rate_limit_jitter_ratio,
|
|
2742
|
+
|
|
2446
2743
|
cookies_enabled: self.cookies_enabled,
|
|
2447
2744
|
|
|
2448
2745
|
auth: self.auth.clone().map(Into::into),
|
|
@@ -2619,7 +2916,7 @@ impl CrawlEngineHandle {
|
|
|
2619
2916
|
}
|
|
2620
2917
|
}
|
|
2621
2918
|
|
|
2622
|
-
#[derive(Clone, Debug, serde::Serialize
|
|
2919
|
+
#[derive(Clone, Debug, serde::Serialize)]
|
|
2623
2920
|
#[serde(default)]
|
|
2624
2921
|
#[magnus::wrap(class = "Crawlberg::CrawlPageResult")]
|
|
2625
2922
|
pub struct CrawlPageResult {
|
|
@@ -2644,6 +2941,11 @@ pub struct CrawlPageResult {
|
|
|
2644
2941
|
extraction_meta: Option<ExtractionMeta>,
|
|
2645
2942
|
downloaded_document: Option<DownloadedDocument>,
|
|
2646
2943
|
browser_used: bool,
|
|
2944
|
+
final_url: String,
|
|
2945
|
+
redirect_count: usize,
|
|
2946
|
+
noindex_detected: bool,
|
|
2947
|
+
nofollow_detected: bool,
|
|
2948
|
+
ssrf_refused_urls: Vec<String>,
|
|
2647
2949
|
}
|
|
2648
2950
|
|
|
2649
2951
|
unsafe impl IntoValueFromNative for CrawlPageResult {}
|
|
@@ -2673,6 +2975,14 @@ impl magnus::TryConvert for CrawlPageResult {
|
|
|
2673
2975
|
}
|
|
2674
2976
|
|
|
2675
2977
|
unsafe impl TryConvertOwned for CrawlPageResult {}
|
|
2978
|
+
impl<'de> serde::Deserialize<'de> for CrawlPageResult {
|
|
2979
|
+
fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
|
|
2980
|
+
where
|
|
2981
|
+
D: serde::Deserializer<'de>,
|
|
2982
|
+
{
|
|
2983
|
+
<crawlberg::CrawlPageResult as serde::Deserialize>::deserialize(deserializer).map(Into::into)
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2676
2986
|
|
|
2677
2987
|
impl Default for CrawlPageResult {
|
|
2678
2988
|
fn default() -> Self {
|
|
@@ -2879,6 +3189,51 @@ impl CrawlPageResult {
|
|
|
2879
3189
|
})?,
|
|
2880
3190
|
None => Default::default(),
|
|
2881
3191
|
},
|
|
3192
|
+
final_url: match kwargs.get(ruby.to_symbol("final_url")) {
|
|
3193
|
+
Some(v) => String::try_convert(v).map_err(|e| {
|
|
3194
|
+
magnus::Error::new(
|
|
3195
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
3196
|
+
format!("invalid value for `final_url`: {}", e),
|
|
3197
|
+
)
|
|
3198
|
+
})?,
|
|
3199
|
+
None => Default::default(),
|
|
3200
|
+
},
|
|
3201
|
+
redirect_count: match kwargs.get(ruby.to_symbol("redirect_count")) {
|
|
3202
|
+
Some(v) => usize::try_convert(v).map_err(|e| {
|
|
3203
|
+
magnus::Error::new(
|
|
3204
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
3205
|
+
format!("invalid value for `redirect_count`: {}", e),
|
|
3206
|
+
)
|
|
3207
|
+
})?,
|
|
3208
|
+
None => Default::default(),
|
|
3209
|
+
},
|
|
3210
|
+
noindex_detected: match kwargs.get(ruby.to_symbol("noindex_detected")) {
|
|
3211
|
+
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
3212
|
+
magnus::Error::new(
|
|
3213
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
3214
|
+
format!("invalid value for `noindex_detected`: {}", e),
|
|
3215
|
+
)
|
|
3216
|
+
})?,
|
|
3217
|
+
None => Default::default(),
|
|
3218
|
+
},
|
|
3219
|
+
nofollow_detected: match kwargs.get(ruby.to_symbol("nofollow_detected")) {
|
|
3220
|
+
Some(v) => bool::try_convert(v).map_err(|e| {
|
|
3221
|
+
magnus::Error::new(
|
|
3222
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
3223
|
+
format!("invalid value for `nofollow_detected`: {}", e),
|
|
3224
|
+
)
|
|
3225
|
+
})?,
|
|
3226
|
+
None => Default::default(),
|
|
3227
|
+
},
|
|
3228
|
+
ssrf_refused_urls: match kwargs.get(ruby.to_symbol("ssrf_refused_urls")) {
|
|
3229
|
+
Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
|
|
3230
|
+
magnus::Error::new(
|
|
3231
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
3232
|
+
format!("invalid value for `ssrf_refused_urls`: {}", e),
|
|
3233
|
+
)
|
|
3234
|
+
})?,
|
|
3235
|
+
None => Default::default(),
|
|
3236
|
+
},
|
|
2882
3237
|
})
|
|
2883
3238
|
}
|
|
2884
3239
|
|
|
@@ -2965,6 +3320,26 @@ impl CrawlPageResult {
|
|
|
2965
3320
|
fn browser_used(&self) -> bool {
|
|
2966
3321
|
self.browser_used
|
|
2967
3322
|
}
|
|
3323
|
+
|
|
3324
|
+
fn final_url(&self) -> String {
|
|
3325
|
+
self.final_url.clone()
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
fn redirect_count(&self) -> usize {
|
|
3329
|
+
self.redirect_count
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
fn noindex_detected(&self) -> bool {
|
|
3333
|
+
self.noindex_detected
|
|
3334
|
+
}
|
|
3335
|
+
|
|
3336
|
+
fn nofollow_detected(&self) -> bool {
|
|
3337
|
+
self.nofollow_detected
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
fn ssrf_refused_urls(&self) -> Vec<String> {
|
|
3341
|
+
self.ssrf_refused_urls.clone()
|
|
3342
|
+
}
|
|
2968
3343
|
}
|
|
2969
3344
|
|
|
2970
3345
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
|
@@ -3360,7 +3735,7 @@ impl DownloadedAsset {
|
|
|
3360
3735
|
}
|
|
3361
3736
|
}
|
|
3362
3737
|
|
|
3363
|
-
#[derive(Clone,
|
|
3738
|
+
#[derive(Clone, serde::Serialize)]
|
|
3364
3739
|
#[serde(default)]
|
|
3365
3740
|
#[magnus::wrap(class = "Crawlberg::DownloadedDocument")]
|
|
3366
3741
|
pub struct DownloadedDocument {
|
|
@@ -3402,6 +3777,21 @@ impl magnus::TryConvert for DownloadedDocument {
|
|
|
3402
3777
|
}
|
|
3403
3778
|
|
|
3404
3779
|
unsafe impl TryConvertOwned for DownloadedDocument {}
|
|
3780
|
+
impl std::fmt::Debug for DownloadedDocument {
|
|
3781
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
3782
|
+
let mut debug = f.debug_struct("DownloadedDocument");
|
|
3783
|
+
debug.field("url", &self.url);
|
|
3784
|
+
debug.field("mime_type", &self.mime_type);
|
|
3785
|
+
debug.field("size", &self.size);
|
|
3786
|
+
debug.field("filename", &self.filename);
|
|
3787
|
+
debug.field("content_hash", &self.content_hash);
|
|
3788
|
+
debug.field("headers", &"<redacted>");
|
|
3789
|
+
debug.field("truncated", &self.truncated);
|
|
3790
|
+
debug.field("content_path", &self.content_path);
|
|
3791
|
+
debug.field("content_base64", &self.content_base64);
|
|
3792
|
+
debug.finish()
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3405
3795
|
impl<'de> serde::Deserialize<'de> for DownloadedDocument {
|
|
3406
3796
|
fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
|
|
3407
3797
|
where
|
|
@@ -4145,7 +4535,7 @@ impl ImageInfo {
|
|
|
4145
4535
|
}
|
|
4146
4536
|
}
|
|
4147
4537
|
|
|
4148
|
-
#[derive(Clone, Debug, serde::Serialize
|
|
4538
|
+
#[derive(Clone, Debug, serde::Serialize)]
|
|
4149
4539
|
#[serde(default)]
|
|
4150
4540
|
#[magnus::wrap(class = "Crawlberg::InteractionResult")]
|
|
4151
4541
|
pub struct InteractionResult {
|
|
@@ -4153,6 +4543,7 @@ pub struct InteractionResult {
|
|
|
4153
4543
|
final_html: String,
|
|
4154
4544
|
final_url: String,
|
|
4155
4545
|
screenshot_base64: Option<String>,
|
|
4546
|
+
ssrf_refused_urls: Vec<String>,
|
|
4156
4547
|
}
|
|
4157
4548
|
|
|
4158
4549
|
unsafe impl IntoValueFromNative for InteractionResult {}
|
|
@@ -4182,6 +4573,14 @@ impl magnus::TryConvert for InteractionResult {
|
|
|
4182
4573
|
}
|
|
4183
4574
|
|
|
4184
4575
|
unsafe impl TryConvertOwned for InteractionResult {}
|
|
4576
|
+
impl<'de> serde::Deserialize<'de> for InteractionResult {
|
|
4577
|
+
fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
|
|
4578
|
+
where
|
|
4579
|
+
D: serde::Deserializer<'de>,
|
|
4580
|
+
{
|
|
4581
|
+
<crawlberg::InteractionResult as serde::Deserialize>::deserialize(deserializer).map(Into::into)
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4185
4584
|
|
|
4186
4585
|
impl Default for InteractionResult {
|
|
4187
4586
|
fn default() -> Self {
|
|
@@ -4232,6 +4631,15 @@ impl InteractionResult {
|
|
|
4232
4631
|
})?),
|
|
4233
4632
|
None => None,
|
|
4234
4633
|
},
|
|
4634
|
+
ssrf_refused_urls: match kwargs.get(ruby.to_symbol("ssrf_refused_urls")) {
|
|
4635
|
+
Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
|
|
4636
|
+
magnus::Error::new(
|
|
4637
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
4638
|
+
format!("invalid value for `ssrf_refused_urls`: {}", e),
|
|
4639
|
+
)
|
|
4640
|
+
})?,
|
|
4641
|
+
None => Default::default(),
|
|
4642
|
+
},
|
|
4235
4643
|
})
|
|
4236
4644
|
}
|
|
4237
4645
|
|
|
@@ -4250,6 +4658,10 @@ impl InteractionResult {
|
|
|
4250
4658
|
fn screenshot_base64(&self) -> Option<String> {
|
|
4251
4659
|
self.screenshot_base64.clone()
|
|
4252
4660
|
}
|
|
4661
|
+
|
|
4662
|
+
fn ssrf_refused_urls(&self) -> Vec<String> {
|
|
4663
|
+
self.ssrf_refused_urls.clone()
|
|
4664
|
+
}
|
|
4253
4665
|
}
|
|
4254
4666
|
|
|
4255
4667
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
|
@@ -5330,7 +5742,7 @@ impl PageMetadata {
|
|
|
5330
5742
|
}
|
|
5331
5743
|
}
|
|
5332
5744
|
|
|
5333
|
-
#[derive(Clone,
|
|
5745
|
+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
|
5334
5746
|
#[serde(default)]
|
|
5335
5747
|
#[magnus::wrap(class = "Crawlberg::ProxyConfig")]
|
|
5336
5748
|
pub struct ProxyConfig {
|
|
@@ -5366,6 +5778,15 @@ impl magnus::TryConvert for ProxyConfig {
|
|
|
5366
5778
|
}
|
|
5367
5779
|
|
|
5368
5780
|
unsafe impl TryConvertOwned for ProxyConfig {}
|
|
5781
|
+
impl std::fmt::Debug for ProxyConfig {
|
|
5782
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
5783
|
+
let mut debug = f.debug_struct("ProxyConfig");
|
|
5784
|
+
debug.field("url", &"<redacted>");
|
|
5785
|
+
debug.field("username", &self.username);
|
|
5786
|
+
debug.field("password", &"<redacted>");
|
|
5787
|
+
debug.finish()
|
|
5788
|
+
}
|
|
5789
|
+
}
|
|
5369
5790
|
|
|
5370
5791
|
impl Default for ProxyConfig {
|
|
5371
5792
|
fn default() -> Self {
|
|
@@ -5572,7 +5993,7 @@ impl ResponseMeta {
|
|
|
5572
5993
|
}
|
|
5573
5994
|
}
|
|
5574
5995
|
|
|
5575
|
-
#[derive(Clone, Debug, serde::Serialize
|
|
5996
|
+
#[derive(Clone, Debug, serde::Serialize)]
|
|
5576
5997
|
#[serde(default)]
|
|
5577
5998
|
#[magnus::wrap(class = "Crawlberg::ScrapeResult")]
|
|
5578
5999
|
pub struct ScrapeResult {
|
|
@@ -5605,6 +6026,7 @@ pub struct ScrapeResult {
|
|
|
5605
6026
|
screenshot_base64: Option<String>,
|
|
5606
6027
|
downloaded_document: Option<DownloadedDocument>,
|
|
5607
6028
|
browser: Option<BrowserExtras>,
|
|
6029
|
+
ssrf_refused_urls: Vec<String>,
|
|
5608
6030
|
}
|
|
5609
6031
|
|
|
5610
6032
|
unsafe impl IntoValueFromNative for ScrapeResult {}
|
|
@@ -5634,6 +6056,14 @@ impl magnus::TryConvert for ScrapeResult {
|
|
|
5634
6056
|
}
|
|
5635
6057
|
|
|
5636
6058
|
unsafe impl TryConvertOwned for ScrapeResult {}
|
|
6059
|
+
impl<'de> serde::Deserialize<'de> for ScrapeResult {
|
|
6060
|
+
fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
|
|
6061
|
+
where
|
|
6062
|
+
D: serde::Deserializer<'de>,
|
|
6063
|
+
{
|
|
6064
|
+
<crawlberg::ScrapeResult as serde::Deserialize>::deserialize(deserializer).map(Into::into)
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
5637
6067
|
|
|
5638
6068
|
impl Default for ScrapeResult {
|
|
5639
6069
|
fn default() -> Self {
|
|
@@ -5912,6 +6342,15 @@ impl ScrapeResult {
|
|
|
5912
6342
|
})?),
|
|
5913
6343
|
None => None,
|
|
5914
6344
|
},
|
|
6345
|
+
ssrf_refused_urls: match kwargs.get(ruby.to_symbol("ssrf_refused_urls")) {
|
|
6346
|
+
Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
|
|
6347
|
+
magnus::Error::new(
|
|
6348
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
6349
|
+
format!("invalid value for `ssrf_refused_urls`: {}", e),
|
|
6350
|
+
)
|
|
6351
|
+
})?,
|
|
6352
|
+
None => Default::default(),
|
|
6353
|
+
},
|
|
5915
6354
|
})
|
|
5916
6355
|
}
|
|
5917
6356
|
|
|
@@ -6030,6 +6469,10 @@ impl ScrapeResult {
|
|
|
6030
6469
|
fn browser(&self) -> Option<BrowserExtras> {
|
|
6031
6470
|
self.browser.clone()
|
|
6032
6471
|
}
|
|
6472
|
+
|
|
6473
|
+
fn ssrf_refused_urls(&self) -> Vec<String> {
|
|
6474
|
+
self.ssrf_refused_urls.clone()
|
|
6475
|
+
}
|
|
6033
6476
|
}
|
|
6034
6477
|
|
|
6035
6478
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
|
@@ -6145,6 +6588,7 @@ impl SitemapUrl {
|
|
|
6145
6588
|
pub struct SsrfPolicy {
|
|
6146
6589
|
deny_private: bool,
|
|
6147
6590
|
allowlist: Vec<HostMatcher>,
|
|
6591
|
+
denylist: Vec<HostMatcher>,
|
|
6148
6592
|
max_redirects: u8,
|
|
6149
6593
|
scheme_allowlist: Vec<String>,
|
|
6150
6594
|
}
|
|
@@ -6216,6 +6660,15 @@ impl SsrfPolicy {
|
|
|
6216
6660
|
})?,
|
|
6217
6661
|
None => Default::default(),
|
|
6218
6662
|
},
|
|
6663
|
+
denylist: match kwargs.get(ruby.to_symbol("denylist")) {
|
|
6664
|
+
Some(v) => <Vec<HostMatcher>>::try_convert(v).map_err(|e| {
|
|
6665
|
+
magnus::Error::new(
|
|
6666
|
+
unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
|
|
6667
|
+
format!("invalid value for `denylist`: {}", e),
|
|
6668
|
+
)
|
|
6669
|
+
})?,
|
|
6670
|
+
None => Default::default(),
|
|
6671
|
+
},
|
|
6219
6672
|
max_redirects: match kwargs.get(ruby.to_symbol("max_redirects")) {
|
|
6220
6673
|
Some(v) => u8::try_convert(v).map_err(|e| {
|
|
6221
6674
|
magnus::Error::new(
|
|
@@ -6245,6 +6698,10 @@ impl SsrfPolicy {
|
|
|
6245
6698
|
self.allowlist.clone()
|
|
6246
6699
|
}
|
|
6247
6700
|
|
|
6701
|
+
fn denylist(&self) -> Vec<HostMatcher> {
|
|
6702
|
+
self.denylist.clone()
|
|
6703
|
+
}
|
|
6704
|
+
|
|
6248
6705
|
fn max_redirects(&self) -> u8 {
|
|
6249
6706
|
self.max_redirects
|
|
6250
6707
|
}
|
|
@@ -6328,7 +6785,7 @@ impl magnus::TryConvert for AssetCategory {
|
|
|
6328
6785
|
unsafe impl IntoValueFromNative for AssetCategory {}
|
|
6329
6786
|
unsafe impl TryConvertOwned for AssetCategory {}
|
|
6330
6787
|
|
|
6331
|
-
#[derive(Clone,
|
|
6788
|
+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
|
6332
6789
|
#[serde(tag = "type")]
|
|
6333
6790
|
pub enum AuthConfig {
|
|
6334
6791
|
#[serde(rename = "basic")]
|
|
@@ -6394,6 +6851,11 @@ unsafe impl IntoValueFromNative for AuthConfig {}
|
|
|
6394
6851
|
unsafe impl TryConvertOwned for AuthConfig {}
|
|
6395
6852
|
|
|
6396
6853
|
impl AuthConfig {}
|
|
6854
|
+
impl std::fmt::Debug for AuthConfig {
|
|
6855
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
6856
|
+
f.write_str("AuthConfig(<redacted>)")
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6397
6859
|
|
|
6398
6860
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
|
|
6399
6861
|
#[serde(rename_all = "snake_case")]
|
|
@@ -6991,7 +7453,7 @@ impl magnus::TryConvert for LinkType {
|
|
|
6991
7453
|
unsafe impl IntoValueFromNative for LinkType {}
|
|
6992
7454
|
unsafe impl TryConvertOwned for LinkType {}
|
|
6993
7455
|
|
|
6994
|
-
#[derive(Clone,
|
|
7456
|
+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
|
6995
7457
|
#[serde(tag = "type")]
|
|
6996
7458
|
#[serde(rename_all = "camelCase")]
|
|
6997
7459
|
pub enum PageAction {
|
|
@@ -7077,6 +7539,11 @@ unsafe impl IntoValueFromNative for PageAction {}
|
|
|
7077
7539
|
unsafe impl TryConvertOwned for PageAction {}
|
|
7078
7540
|
|
|
7079
7541
|
impl PageAction {}
|
|
7542
|
+
impl std::fmt::Debug for PageAction {
|
|
7543
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
7544
|
+
f.write_str("PageAction(<redacted>)")
|
|
7545
|
+
}
|
|
7546
|
+
}
|
|
7080
7547
|
|
|
7081
7548
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
|
|
7082
7549
|
#[serde(rename_all = "camelCase")]
|
|
@@ -7522,6 +7989,8 @@ impl From<BrowserConfig> for crawlberg::BrowserConfig {
|
|
|
7522
7989
|
backend: val.backend.into(),
|
|
7523
7990
|
endpoint: val.endpoint,
|
|
7524
7991
|
timeout: std::time::Duration::from_millis(val.timeout),
|
|
7992
|
+
overall_timeout: std::time::Duration::from_millis(val.overall_timeout),
|
|
7993
|
+
shutdown_timeout: std::time::Duration::from_millis(val.shutdown_timeout),
|
|
7525
7994
|
wait: val.wait.into(),
|
|
7526
7995
|
wait_selector: val.wait_selector,
|
|
7527
7996
|
extra_wait: val.extra_wait.map(std::time::Duration::from_millis),
|
|
@@ -7531,6 +8000,8 @@ impl From<BrowserConfig> for crawlberg::BrowserConfig {
|
|
|
7531
8000
|
robots_user_agent: val.robots_user_agent,
|
|
7532
8001
|
capture_network_events: val.capture_network_events,
|
|
7533
8002
|
session_affinity: val.session_affinity,
|
|
8003
|
+
chrome_path: val.chrome_path.map(Into::into),
|
|
8004
|
+
chrome_args: val.chrome_args.into_iter().collect(),
|
|
7534
8005
|
..Default::default()
|
|
7535
8006
|
}
|
|
7536
8007
|
}
|
|
@@ -7544,6 +8015,8 @@ impl From<crawlberg::BrowserConfig> for BrowserConfig {
|
|
|
7544
8015
|
backend: val.backend.into(),
|
|
7545
8016
|
endpoint: val.endpoint.map(|v| v.to_string()),
|
|
7546
8017
|
timeout: val.timeout.as_millis() as u64,
|
|
8018
|
+
overall_timeout: val.overall_timeout.as_millis() as u64,
|
|
8019
|
+
shutdown_timeout: val.shutdown_timeout.as_millis() as u64,
|
|
7547
8020
|
wait: val.wait.into(),
|
|
7548
8021
|
wait_selector: val.wait_selector.map(|v| v.to_string()),
|
|
7549
8022
|
extra_wait: val.extra_wait.map(|d| d.as_millis() as u64),
|
|
@@ -7553,6 +8026,8 @@ impl From<crawlberg::BrowserConfig> for BrowserConfig {
|
|
|
7553
8026
|
robots_user_agent: val.robots_user_agent.map(|v| v.to_string()),
|
|
7554
8027
|
capture_network_events: val.capture_network_events,
|
|
7555
8028
|
session_affinity: val.session_affinity,
|
|
8029
|
+
chrome_path: val.chrome_path.map(|p| p.to_string_lossy().to_string()),
|
|
8030
|
+
chrome_args: val.chrome_args.into_iter().collect(),
|
|
7556
8031
|
}
|
|
7557
8032
|
}
|
|
7558
8033
|
}
|
|
@@ -7641,6 +8116,7 @@ impl From<ContentConfig> for crawlberg::ContentConfig {
|
|
|
7641
8116
|
wrap: val.wrap,
|
|
7642
8117
|
wrap_width: val.wrap_width,
|
|
7643
8118
|
include_document_structure: val.include_document_structure,
|
|
8119
|
+
extract_metadata: val.extract_metadata,
|
|
7644
8120
|
..Default::default()
|
|
7645
8121
|
}
|
|
7646
8122
|
}
|
|
@@ -7661,6 +8137,7 @@ impl From<crawlberg::ContentConfig> for ContentConfig {
|
|
|
7661
8137
|
wrap: val.wrap,
|
|
7662
8138
|
wrap_width: val.wrap_width,
|
|
7663
8139
|
include_document_structure: val.include_document_structure,
|
|
8140
|
+
extract_metadata: val.extract_metadata,
|
|
7664
8141
|
}
|
|
7665
8142
|
}
|
|
7666
8143
|
}
|
|
@@ -7710,6 +8187,11 @@ impl From<CrawlConfig> for crawlberg::CrawlConfig {
|
|
|
7710
8187
|
allow_subdomains: val.allow_subdomains,
|
|
7711
8188
|
include_paths: val.include_paths.into_iter().collect(),
|
|
7712
8189
|
exclude_paths: val.exclude_paths.into_iter().collect(),
|
|
8190
|
+
path_patterns_match_query: val.path_patterns_match_query,
|
|
8191
|
+
path_patterns_match_url: val.path_patterns_match_url,
|
|
8192
|
+
dedup_include_query: val.dedup_include_query,
|
|
8193
|
+
strip_tracking_params: val.strip_tracking_params,
|
|
8194
|
+
tracking_params: val.tracking_params.into_iter().collect(),
|
|
7713
8195
|
custom_headers: val
|
|
7714
8196
|
.custom_headers
|
|
7715
8197
|
.into_iter()
|
|
@@ -7720,6 +8202,9 @@ impl From<CrawlConfig> for crawlberg::CrawlConfig {
|
|
|
7720
8202
|
max_redirects: val.max_redirects,
|
|
7721
8203
|
retry_count: val.retry_count,
|
|
7722
8204
|
retry_codes: val.retry_codes.into_iter().collect(),
|
|
8205
|
+
retry_initial_delay_ms: val.retry_initial_delay_ms,
|
|
8206
|
+
retry_max_delay_ms: val.retry_max_delay_ms,
|
|
8207
|
+
rate_limit_jitter_ratio: val.rate_limit_jitter_ratio,
|
|
7723
8208
|
cookies_enabled: val.cookies_enabled,
|
|
7724
8209
|
auth: val.auth.map(Into::into),
|
|
7725
8210
|
max_body_size: val.max_body_size,
|
|
@@ -7770,6 +8255,11 @@ impl From<crawlberg::CrawlConfig> for CrawlConfig {
|
|
|
7770
8255
|
allow_subdomains: val.allow_subdomains,
|
|
7771
8256
|
include_paths: val.include_paths.into_iter().collect(),
|
|
7772
8257
|
exclude_paths: val.exclude_paths.into_iter().collect(),
|
|
8258
|
+
path_patterns_match_query: val.path_patterns_match_query,
|
|
8259
|
+
path_patterns_match_url: val.path_patterns_match_url,
|
|
8260
|
+
dedup_include_query: val.dedup_include_query,
|
|
8261
|
+
strip_tracking_params: val.strip_tracking_params,
|
|
8262
|
+
tracking_params: val.tracking_params.into_iter().collect(),
|
|
7773
8263
|
custom_headers: val
|
|
7774
8264
|
.custom_headers
|
|
7775
8265
|
.into_iter()
|
|
@@ -7780,6 +8270,9 @@ impl From<crawlberg::CrawlConfig> for CrawlConfig {
|
|
|
7780
8270
|
max_redirects: val.max_redirects,
|
|
7781
8271
|
retry_count: val.retry_count,
|
|
7782
8272
|
retry_codes: val.retry_codes.into_iter().collect(),
|
|
8273
|
+
retry_initial_delay_ms: val.retry_initial_delay_ms,
|
|
8274
|
+
retry_max_delay_ms: val.retry_max_delay_ms,
|
|
8275
|
+
rate_limit_jitter_ratio: val.rate_limit_jitter_ratio,
|
|
7783
8276
|
cookies_enabled: val.cookies_enabled,
|
|
7784
8277
|
auth: val.auth.map(Into::into),
|
|
7785
8278
|
max_body_size: val.max_body_size,
|
|
@@ -7836,6 +8329,11 @@ impl From<CrawlPageResult> for crawlberg::CrawlPageResult {
|
|
|
7836
8329
|
extraction_meta: val.extraction_meta.map(Into::into),
|
|
7837
8330
|
downloaded_document: val.downloaded_document.map(Into::into),
|
|
7838
8331
|
browser_used: val.browser_used,
|
|
8332
|
+
final_url: val.final_url,
|
|
8333
|
+
redirect_count: val.redirect_count,
|
|
8334
|
+
noindex_detected: val.noindex_detected,
|
|
8335
|
+
nofollow_detected: val.nofollow_detected,
|
|
8336
|
+
ssrf_refused_urls: val.ssrf_refused_urls.into_iter().collect(),
|
|
7839
8337
|
..Default::default()
|
|
7840
8338
|
}
|
|
7841
8339
|
}
|
|
@@ -7866,6 +8364,11 @@ impl From<crawlberg::CrawlPageResult> for CrawlPageResult {
|
|
|
7866
8364
|
extraction_meta: val.extraction_meta.map(Into::into),
|
|
7867
8365
|
downloaded_document: val.downloaded_document.map(Into::into),
|
|
7868
8366
|
browser_used: val.browser_used,
|
|
8367
|
+
final_url: val.final_url.to_string(),
|
|
8368
|
+
redirect_count: val.redirect_count,
|
|
8369
|
+
noindex_detected: val.noindex_detected,
|
|
8370
|
+
nofollow_detected: val.nofollow_detected,
|
|
8371
|
+
ssrf_refused_urls: val.ssrf_refused_urls.into_iter().collect(),
|
|
7869
8372
|
}
|
|
7870
8373
|
}
|
|
7871
8374
|
}
|
|
@@ -8143,6 +8646,7 @@ impl From<InteractionResult> for crawlberg::InteractionResult {
|
|
|
8143
8646
|
final_html: val.final_html,
|
|
8144
8647
|
final_url: val.final_url,
|
|
8145
8648
|
screenshot_base64: val.screenshot_base64,
|
|
8649
|
+
ssrf_refused_urls: val.ssrf_refused_urls.into_iter().collect(),
|
|
8146
8650
|
..Default::default()
|
|
8147
8651
|
}
|
|
8148
8652
|
}
|
|
@@ -8156,6 +8660,7 @@ impl From<crawlberg::InteractionResult> for InteractionResult {
|
|
|
8156
8660
|
final_html: val.final_html.to_string(),
|
|
8157
8661
|
final_url: val.final_url.to_string(),
|
|
8158
8662
|
screenshot_base64: val.screenshot_base64.map(|v| v.to_string()),
|
|
8663
|
+
ssrf_refused_urls: val.ssrf_refused_urls.into_iter().collect(),
|
|
8159
8664
|
}
|
|
8160
8665
|
}
|
|
8161
8666
|
}
|
|
@@ -8460,6 +8965,7 @@ impl From<ScrapeResult> for crawlberg::ScrapeResult {
|
|
|
8460
8965
|
screenshot_base64: val.screenshot_base64,
|
|
8461
8966
|
downloaded_document: val.downloaded_document.map(Into::into),
|
|
8462
8967
|
browser: val.browser.map(Into::into),
|
|
8968
|
+
ssrf_refused_urls: val.ssrf_refused_urls.into_iter().collect(),
|
|
8463
8969
|
..Default::default()
|
|
8464
8970
|
}
|
|
8465
8971
|
}
|
|
@@ -8498,6 +9004,7 @@ impl From<crawlberg::ScrapeResult> for ScrapeResult {
|
|
|
8498
9004
|
screenshot_base64: val.screenshot_base64.map(|v| v.to_string()),
|
|
8499
9005
|
downloaded_document: val.downloaded_document.map(Into::into),
|
|
8500
9006
|
browser: val.browser.map(Into::into),
|
|
9007
|
+
ssrf_refused_urls: val.ssrf_refused_urls.into_iter().collect(),
|
|
8501
9008
|
}
|
|
8502
9009
|
}
|
|
8503
9010
|
}
|
|
@@ -8534,6 +9041,7 @@ impl From<SsrfPolicy> for crawlberg::SsrfPolicy {
|
|
|
8534
9041
|
Self {
|
|
8535
9042
|
deny_private: val.deny_private,
|
|
8536
9043
|
allowlist: val.allowlist.into_iter().map(Into::into).collect(),
|
|
9044
|
+
denylist: val.denylist.into_iter().map(Into::into).collect(),
|
|
8537
9045
|
max_redirects: val.max_redirects,
|
|
8538
9046
|
scheme_allowlist: val.scheme_allowlist.into_iter().collect(),
|
|
8539
9047
|
..Default::default()
|
|
@@ -8547,6 +9055,7 @@ impl From<crawlberg::SsrfPolicy> for SsrfPolicy {
|
|
|
8547
9055
|
Self {
|
|
8548
9056
|
deny_private: val.deny_private,
|
|
8549
9057
|
allowlist: val.allowlist.into_iter().map(Into::into).collect(),
|
|
9058
|
+
denylist: val.denylist.into_iter().map(Into::into).collect(),
|
|
8550
9059
|
max_redirects: val.max_redirects,
|
|
8551
9060
|
scheme_allowlist: val.scheme_allowlist.into_iter().collect(),
|
|
8552
9061
|
}
|
|
@@ -9186,6 +9695,10 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9186
9695
|
|
|
9187
9696
|
class.define_method("timeout", method!(BrowserConfig::timeout, 0))?;
|
|
9188
9697
|
|
|
9698
|
+
class.define_method("overall_timeout", method!(BrowserConfig::overall_timeout, 0))?;
|
|
9699
|
+
|
|
9700
|
+
class.define_method("shutdown_timeout", method!(BrowserConfig::shutdown_timeout, 0))?;
|
|
9701
|
+
|
|
9189
9702
|
class.define_method("wait", method!(BrowserConfig::wait, 0))?;
|
|
9190
9703
|
|
|
9191
9704
|
class.define_method("wait_selector", method!(BrowserConfig::wait_selector, 0))?;
|
|
@@ -9207,6 +9720,10 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9207
9720
|
|
|
9208
9721
|
class.define_method("session_affinity", method!(BrowserConfig::session_affinity, 0))?;
|
|
9209
9722
|
|
|
9723
|
+
class.define_method("chrome_path", method!(BrowserConfig::chrome_path, 0))?;
|
|
9724
|
+
|
|
9725
|
+
class.define_method("chrome_args", method!(BrowserConfig::chrome_args, 0))?;
|
|
9726
|
+
|
|
9210
9727
|
let class = module.define_class("BrowserExtras", ruby.class_object())?;
|
|
9211
9728
|
|
|
9212
9729
|
class.define_singleton_method("new", function!(BrowserExtras::new, -1))?;
|
|
@@ -9268,6 +9785,8 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9268
9785
|
method!(ContentConfig::include_document_structure, 0),
|
|
9269
9786
|
)?;
|
|
9270
9787
|
|
|
9788
|
+
class.define_method("extract_metadata", method!(ContentConfig::extract_metadata, 0))?;
|
|
9789
|
+
|
|
9271
9790
|
let class = module.define_class("CookieInfo", ruby.class_object())?;
|
|
9272
9791
|
|
|
9273
9792
|
class.define_singleton_method("new", function!(CookieInfo::new, -1))?;
|
|
@@ -9314,6 +9833,22 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9314
9833
|
|
|
9315
9834
|
class.define_method("exclude_paths", method!(CrawlConfig::exclude_paths, 0))?;
|
|
9316
9835
|
|
|
9836
|
+
class.define_method(
|
|
9837
|
+
"path_patterns_match_query",
|
|
9838
|
+
method!(CrawlConfig::path_patterns_match_query, 0),
|
|
9839
|
+
)?;
|
|
9840
|
+
|
|
9841
|
+
class.define_method(
|
|
9842
|
+
"path_patterns_match_url",
|
|
9843
|
+
method!(CrawlConfig::path_patterns_match_url, 0),
|
|
9844
|
+
)?;
|
|
9845
|
+
|
|
9846
|
+
class.define_method("dedup_include_query", method!(CrawlConfig::dedup_include_query, 0))?;
|
|
9847
|
+
|
|
9848
|
+
class.define_method("strip_tracking_params", method!(CrawlConfig::strip_tracking_params, 0))?;
|
|
9849
|
+
|
|
9850
|
+
class.define_method("tracking_params", method!(CrawlConfig::tracking_params, 0))?;
|
|
9851
|
+
|
|
9317
9852
|
class.define_method("custom_headers", method!(CrawlConfig::custom_headers, 0))?;
|
|
9318
9853
|
|
|
9319
9854
|
class.define_method("request_timeout", method!(CrawlConfig::request_timeout, 0))?;
|
|
@@ -9326,6 +9861,18 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9326
9861
|
|
|
9327
9862
|
class.define_method("retry_codes", method!(CrawlConfig::retry_codes, 0))?;
|
|
9328
9863
|
|
|
9864
|
+
class.define_method(
|
|
9865
|
+
"retry_initial_delay_ms",
|
|
9866
|
+
method!(CrawlConfig::retry_initial_delay_ms, 0),
|
|
9867
|
+
)?;
|
|
9868
|
+
|
|
9869
|
+
class.define_method("retry_max_delay_ms", method!(CrawlConfig::retry_max_delay_ms, 0))?;
|
|
9870
|
+
|
|
9871
|
+
class.define_method(
|
|
9872
|
+
"rate_limit_jitter_ratio",
|
|
9873
|
+
method!(CrawlConfig::rate_limit_jitter_ratio, 0),
|
|
9874
|
+
)?;
|
|
9875
|
+
|
|
9329
9876
|
class.define_method("cookies_enabled", method!(CrawlConfig::cookies_enabled, 0))?;
|
|
9330
9877
|
|
|
9331
9878
|
class.define_method("auth", method!(CrawlConfig::auth, 0))?;
|
|
@@ -9437,6 +9984,16 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9437
9984
|
|
|
9438
9985
|
class.define_method("browser_used", method!(CrawlPageResult::browser_used, 0))?;
|
|
9439
9986
|
|
|
9987
|
+
class.define_method("final_url", method!(CrawlPageResult::final_url, 0))?;
|
|
9988
|
+
|
|
9989
|
+
class.define_method("redirect_count", method!(CrawlPageResult::redirect_count, 0))?;
|
|
9990
|
+
|
|
9991
|
+
class.define_method("noindex_detected", method!(CrawlPageResult::noindex_detected, 0))?;
|
|
9992
|
+
|
|
9993
|
+
class.define_method("nofollow_detected", method!(CrawlPageResult::nofollow_detected, 0))?;
|
|
9994
|
+
|
|
9995
|
+
class.define_method("ssrf_refused_urls", method!(CrawlPageResult::ssrf_refused_urls, 0))?;
|
|
9996
|
+
|
|
9440
9997
|
let class = module.define_class("CrawlResult", ruby.class_object())?;
|
|
9441
9998
|
|
|
9442
9999
|
class.define_singleton_method("new", function!(CrawlResult::new, -1))?;
|
|
@@ -9586,6 +10143,8 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9586
10143
|
|
|
9587
10144
|
class.define_method("screenshot_base64", method!(InteractionResult::screenshot_base64, 0))?;
|
|
9588
10145
|
|
|
10146
|
+
class.define_method("ssrf_refused_urls", method!(InteractionResult::ssrf_refused_urls, 0))?;
|
|
10147
|
+
|
|
9589
10148
|
let class = module.define_class("JsonLdEntry", ruby.class_object())?;
|
|
9590
10149
|
|
|
9591
10150
|
class.define_singleton_method("new", function!(JsonLdEntry::new, -1))?;
|
|
@@ -9814,6 +10373,8 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9814
10373
|
|
|
9815
10374
|
class.define_method("browser", method!(ScrapeResult::browser, 0))?;
|
|
9816
10375
|
|
|
10376
|
+
class.define_method("ssrf_refused_urls", method!(ScrapeResult::ssrf_refused_urls, 0))?;
|
|
10377
|
+
|
|
9817
10378
|
let class = module.define_class("SitemapUrl", ruby.class_object())?;
|
|
9818
10379
|
|
|
9819
10380
|
class.define_singleton_method("new", function!(SitemapUrl::new, -1))?;
|
|
@@ -9834,6 +10395,8 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
9834
10395
|
|
|
9835
10396
|
class.define_method("allowlist", method!(SsrfPolicy::allowlist, 0))?;
|
|
9836
10397
|
|
|
10398
|
+
class.define_method("denylist", method!(SsrfPolicy::denylist, 0))?;
|
|
10399
|
+
|
|
9837
10400
|
class.define_method("max_redirects", method!(SsrfPolicy::max_redirects, 0))?;
|
|
9838
10401
|
|
|
9839
10402
|
class.define_method("scheme_allowlist", method!(SsrfPolicy::scheme_allowlist, 0))?;
|