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;
}