1use std::{error::Error, fs::File};
2
3use reqwest::{Client, Request, Response};
4use tracing::{debug, error, info, instrument, span, trace, warn, Instrument, Level};
5
6use crate::{
7 api::file::File as BaserowFile,
8 error::{FileUploadError, TokenAuthError},
9 BaserowTable, Configuration, TableField,
10};
11
12#[async_trait::async_trait]
13pub trait RequestTracing {
14 #[instrument(skip(self, client, request), fields(method = %request.method(), url = %request.url()), err)]
16 async fn trace_request(&self, client: &Client, request: Request) -> reqwest::Result<Response> {
17 let span = span!(
18 Level::DEBUG,
19 "http_request",
20 method = %request.method(),
21 url = %request.url(),
22 );
23
24 async move {
25 debug!("Sending HTTP request");
26 trace!(headers = ?request.headers(), "Request headers");
27 let response = client.execute(request).await?;
28 let status = response.status();
29
30 if status.is_success() {
31 info!(status = %status, "HTTP request successful");
32 trace!(headers = ?response.headers(), "Response headers");
33 } else {
34 error!(status = %status, "HTTP request failed");
35 warn!(headers = ?response.headers(), "Failed response headers");
36 }
37
38 Ok(response)
39 }
40 .instrument(span)
41 .await
42 }
43}
44
45impl<T: BaserowClient + ?Sized> RequestTracing for T {}
46
47#[async_trait::async_trait]
55pub trait BaserowClient: RequestTracing {
56 async fn token_auth(&self) -> Result<Box<dyn BaserowClient>, TokenAuthError>;
62
63 async fn table_fields(&self, table_id: u64) -> Result<Vec<TableField>, Box<dyn Error>>;
68
69 fn table_by_id(&self, id: u64) -> BaserowTable;
71
72 async fn upload_file(
77 &self,
78 file: File,
79 filename: String,
80 ) -> Result<BaserowFile, FileUploadError>;
81
82 async fn upload_file_via_url(&self, url: &str) -> Result<BaserowFile, FileUploadError>;
87
88 fn get_configuration(&self) -> Configuration;
90
91 fn get_client(&self) -> Client;
93}