nextcloud_preview/
client.rs1use nextcloud_sdk_core::{
4 ApiPath, AuthProvider, Error, Headers, HttpMethod, Request, Response, StatusError, Transport,
5};
6
7use crate::options::PreviewOptions;
8use crate::query::{build_file_id_query, build_path_query};
9
10#[cfg(test)]
11mod tests;
12
13pub const PREVIEW_ENDPOINT: &str = "core/preview.png";
15
16#[derive(Clone, Copy, Debug)]
30pub struct PreviewClient<'a, T: Transport, A: AuthProvider> {
31 transport: &'a T,
32 auth: &'a A,
33}
34
35impl<'a, T: Transport, A: AuthProvider> PreviewClient<'a, T, A> {
36 pub const fn new(transport: &'a T, auth: &'a A) -> Self {
38 Self { transport, auth }
39 }
40
41 pub const fn transport(&self) -> &'a T {
43 self.transport
44 }
45
46 pub const fn auth(&self) -> &'a A {
48 self.auth
49 }
50
51 pub async fn get_by_file_id(
61 &self,
62 file_id: u64,
63 options: &PreviewOptions,
64 ) -> Result<Vec<u8>, Error> {
65 tracing::debug!(file_id, "Fetching file preview by ID");
66 let query = build_file_id_query(file_id, options);
67 self.fetch_preview(&query).await
68 }
69
70 pub async fn get_by_path(
80 &self,
81 path: &str,
82 options: &PreviewOptions,
83 ) -> Result<Vec<u8>, Error> {
84 tracing::debug!(path, "Fetching file preview by path");
85 let query = build_path_query(path, options);
86 self.fetch_preview(&query).await
87 }
88
89 async fn fetch_preview(&self, query: &str) -> Result<Vec<u8>, Error> {
90 let api_path = ApiPath::public(format!("{PREVIEW_ENDPOINT}{query}"))?;
91 let headers = self.authenticated_headers();
92 let request = Request::get(api_path.clone()).with_headers(headers);
93
94 let response = self.transport.execute(request).await?;
95 ensure_success(HttpMethod::Get, api_path, response)
96 }
97
98 fn authenticated_headers(&self) -> Headers {
99 let mut headers = Headers::new();
100 self.auth.authenticate(&mut headers);
101 headers
102 }
103}
104
105fn ensure_success(method: HttpMethod, path: ApiPath, response: Response) -> Result<Vec<u8>, Error> {
106 if response.status().is_success() {
107 Ok(response.into_body())
108 } else {
109 tracing::error!(
110 method = ?method,
111 path = %path.as_str(),
112 status = %response.status(),
113 "Preview request failed"
114 );
115 Err(Error::Status(StatusError::new(
116 method.as_str(),
117 path,
118 response.status(),
119 response.body(),
120 )))
121 }
122}