1use thiserror::Error;
14
15#[derive(Debug, Clone, Error)]
16#[error("Reqwest error: {message}")]
17pub struct ReqwestErrorDetails {
18 pub message: String,
19 pub is_connect: bool,
20 pub is_timeout: bool,
21 }
23
24impl From<reqwest::Error> for ReqwestErrorDetails {
25 fn from(err: reqwest::Error) -> Self {
26 ReqwestErrorDetails {
27 is_connect: err.is_connect(),
28 is_timeout: err.is_timeout(),
29 message: err.to_string(),
30 }
31 }
32}
33
34#[derive(Debug, Clone, Error)] pub enum SpiderError {
37 #[error("Reqwest error: {0}")]
38 ReqwestError(#[from] ReqwestErrorDetails), #[error("Url parsing error: {0}")]
40 UrlParseError(#[from] url::ParseError),
41 #[error("Json parsing error: {0}")]
42 JsonError(String), #[error("Io error: {0}")]
44 IoError(String), #[error("Configuration error: {0}")]
46 ConfigurationError(String),
47 #[error("General error: {0}")]
48 GeneralError(String),
49 #[error("Failed to convert item to string: {0}")]
50 ItemToStringError(String),
51 #[error("Error during item serialization: {0}")]
52 ItemSerializationError(String),
53 #[error("Unknown error")]
54 Unknown,
55 #[error("Header value error: {0}")]
56 HeaderValueError(String),
57 #[error("HTML parsing error: {0}")]
58 HtmlParseError(String),
59 #[error("UTF-8 parsing error: {0}")]
60 Utf8Error(#[from] std::str::Utf8Error),
61 #[error("Pipeline error: {0}")]
62 PipelineError(#[from] PipelineError),
63 #[error("Request blocked by robots.txt")]
64 BlockedByRobotsTxt,
65}
66
67impl From<bincode::Error> for SpiderError {
68 fn from(err: bincode::Error) -> Self {
69 SpiderError::GeneralError(format!("Bincode error: {}", err))
70 }
71}
72
73impl From<reqwest::Error> for SpiderError {
74 fn from(err: reqwest::Error) -> Self {
75 SpiderError::ReqwestError(err.into())
76 }
77}
78
79impl From<std::io::Error> for SpiderError {
80 fn from(err: std::io::Error) -> Self {
81 SpiderError::IoError(err.to_string())
82 }
83}
84
85impl From<serde_json::Error> for SpiderError {
86 fn from(err: serde_json::Error) -> Self {
87 SpiderError::JsonError(err.to_string())
88 }
89}
90
91#[derive(Error, Debug, Clone)] pub enum PipelineError {
94 #[error("I/O error: {0}")]
95 IoError(String), #[error("Item processing error: {0}")]
97 ItemError(String),
98 #[cfg(feature = "pipeline-sqlite")]
99 #[error("Database error: {0}")]
100 DatabaseError(String), #[error("Serialization error: {0}")]
102 SerializationError(String), #[error("CSV error: {0}")]
104 CsvError(String), #[error("Other pipeline error: {0}")]
106 Other(String),
107}
108
109impl From<csv::Error> for PipelineError {
110 fn from(err: csv::Error) -> Self {
111 PipelineError::CsvError(err.to_string())
112 }
113}
114
115impl From<std::io::Error> for PipelineError {
116 fn from(err: std::io::Error) -> Self {
117 PipelineError::IoError(err.to_string())
118 }
119}
120
121impl From<serde_json::Error> for PipelineError {
122 fn from(err: serde_json::Error) -> Self {
123 PipelineError::SerializationError(err.to_string())
124 }
125}
126
127#[cfg(feature = "pipeline-sqlite")]
128impl From<rusqlite::Error> for PipelineError {
129 fn from(err: rusqlite::Error) -> Self {
130 PipelineError::DatabaseError(err.to_string())
131 }
132}
133#[cfg(feature = "pipeline-sqlite")]
134impl From<rusqlite::Error> for SpiderError {
135 fn from(err: rusqlite::Error) -> Self {
136 SpiderError::PipelineError(PipelineError::DatabaseError(err.to_string()))
137 }
138}