apify_client/
client.rs

1use reqwest;
2use serde::Deserialize;
3
4use std::fmt::{Display, Formatter};
5
6pub struct ResourceName {
7    pub user_name_or_user_id: String,
8    pub resource_name: String
9}
10
11pub enum IdOrName {
12    Id(String),
13    Name(ResourceName),
14}
15
16pub struct ApifyClient {
17    // The token is optional
18    pub optional_token: Option<String>,
19    pub http_client: reqwest::Client,
20    pub base_time_to_retry: u32,
21    pub debug_log: bool,
22}
23
24#[derive(Deserialize, Debug)]
25pub struct ApifyClientResult<T> {
26    pub data: T
27}
28
29/// Errors returned by Apify API
30#[derive(Debug, PartialEq)]
31pub enum ApifyApiError {
32    // The variant here is "type" and the param is "message"
33    NotFound(String),
34    // We don't have types for all statuses now so we just pass a message
35    // TODO: Get rid of this after implementing all possibillitites
36    RawError(String),
37    MaxTimeoutRetriesReached(u8),
38    MaxRateLimitRetriesReached(u8),
39    MaxServerFailedRetriesReached(u8),
40    /// Something is broken in the API or breaking change happened
41    ApiFailure(String),
42    MissingToken,
43}
44
45impl Display for ApifyApiError {
46    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47        write!(f, "Apify API returned an error: {:?}", self)
48    }
49}
50
51impl std::error::Error for ApifyApiError {}
52
53/// Errors can either be returned by Apify API or happen due to wrong JSON parsing logic.
54/// Only few endpoints that include parsing JSON can return Parse error
55#[derive(Debug)]
56pub enum ApifyClientError {
57    ApifyApi(ApifyApiError),
58    Parse(serde_json::error::Error)
59}
60
61impl Display for ApifyClientError {
62    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
63        match self {
64            ApifyClientError::ApifyApi(apify_api_error) => write!(f, "{}", apify_api_error),
65            ApifyClientError::Parse(parse_error) => write!(f, "JSON parsing failed, please fix your (de)serialization {}", parse_error),
66        }
67    }
68}
69
70impl std::error::Error for ApifyClientError {}
71
72impl From<serde_json::error::Error> for ApifyClientError {
73    fn from(e: serde_json::error::Error) -> Self {
74        ApifyClientError::Parse(e)
75    }
76}
77
78impl From<ApifyApiError> for ApifyClientError {
79    fn from(e: ApifyApiError) -> Self {
80        ApifyClientError::ApifyApi(e)
81    }
82}
83
84impl ApifyClient {
85    /// Creates a new Apify client with an optional token
86    /// Be aware that all write operations requires token 
87    /// Some read operations require token, some have optional token and some don't
88    /// Using a method that requires token without a token in a client will result in Error
89    pub fn new (optional_token: Option<String>) -> ApifyClient {
90        let http_client = reqwest::Client::new();
91        ApifyClient {
92            optional_token,
93            http_client,
94            base_time_to_retry: 500,
95            debug_log: true,
96        }
97    }
98
99    /// Sets a token on the client
100    pub fn token (&mut self, token: String) -> () {
101        self.optional_token = Some(token);
102    }
103}