baserow_rs/api/
client.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use std::{error::Error, fs::File};

use reqwest::{Client, Request, Response};
use tracing::{debug, error, info, instrument, span, trace, warn, Instrument, Level};

use crate::{
    api::file::File as BaserowFile,
    error::{FileUploadError, TokenAuthError},
    BaserowTable, Configuration, TableField,
};

#[async_trait::async_trait]
pub trait RequestTracing {
    /// Trace an HTTP request and its response
    #[instrument(skip(self, client, request), fields(method = %request.method(), url = %request.url()), err)]
    async fn trace_request(&self, client: &Client, request: Request) -> reqwest::Result<Response> {
        let span = span!(
            Level::DEBUG,
            "http_request",
            method = %request.method(),
            url = %request.url(),
        );

        async move {
            debug!("Sending HTTP request");
            trace!(headers = ?request.headers(), "Request headers");
            let response = client.execute(request).await?;
            let status = response.status();

            if status.is_success() {
                info!(status = %status, "HTTP request successful");
                trace!(headers = ?response.headers(), "Response headers");
            } else {
                error!(status = %status, "HTTP request failed");
                warn!(headers = ?response.headers(), "Failed response headers");
            }

            Ok(response)
        }
        .instrument(span)
        .await
    }
}

impl<T: BaserowClient + ?Sized> RequestTracing for T {}

/// Trait defining the public API interface for Baserow
///
/// This trait includes tracing for all operations, providing detailed logs
/// about HTTP requests, responses, and any errors that occur.
///
/// All HTTP operations are automatically traced through the RequestTracing trait,
/// which provides detailed logging of request/response cycles.
#[async_trait::async_trait]
pub trait BaserowClient: RequestTracing {
    /// Authenticates an existing user based on their email and their password.
    /// If successful, an access token and a refresh token will be returned.
    ///
    /// This operation is traced with detailed logging of the authentication process,
    /// excluding sensitive information like credentials.
    async fn token_auth(&self) -> Result<Box<dyn BaserowClient>, TokenAuthError>;

    /// Retrieves all fields for a given table.
    ///
    /// This operation is traced with detailed logging of the request/response cycle
    /// and field retrieval results.
    async fn table_fields(&self, table_id: u64) -> Result<Vec<TableField>, Box<dyn Error>>;

    /// Returns a table by its ID.
    fn table_by_id(&self, id: u64) -> BaserowTable;

    /// Upload a file to Baserow
    ///
    /// This operation is traced with detailed logging of the upload process,
    /// including file metadata and upload status.
    async fn upload_file(
        &self,
        file: File,
        filename: String,
    ) -> Result<BaserowFile, FileUploadError>;

    /// Upload a file to Baserow via URL
    ///
    /// This operation is traced with detailed logging of the URL validation
    /// and upload process.
    async fn upload_file_via_url(&self, url: &str) -> Result<BaserowFile, FileUploadError>;

    /// Get the underlying configuration
    fn get_configuration(&self) -> Configuration;

    /// Get the underlying HTTP client
    fn get_client(&self) -> Client;
}