service/http_server/api/v0/bucket/
cat.rs1use axum::extract::{Json, State};
2use axum::response::{IntoResponse, Response};
3use base64::Engine;
4use reqwest::{Client, RequestBuilder, Url};
5use serde::{Deserialize, Serialize};
6use uuid::Uuid;
7
8use common::prelude::MountError;
9
10use crate::http_server::api::client::ApiRequest;
11use crate::ServiceState;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[cfg_attr(feature = "clap", derive(clap::Args))]
15pub struct CatRequest {
16 #[cfg_attr(feature = "clap", arg(long))]
18 pub bucket_id: Uuid,
19
20 #[cfg_attr(feature = "clap", arg(long))]
22 pub path: String,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct CatResponse {
27 pub path: String,
28 pub content: String,
30 pub size: usize,
31 pub mime_type: String,
32}
33
34#[axum::debug_handler]
35pub async fn handler(
36 State(state): State<ServiceState>,
37 Json(req): Json<CatRequest>,
38) -> Result<impl IntoResponse, CatError> {
39 let file_content = crate::mount_ops::get_file_content(req.bucket_id, req.path.clone(), &state)
41 .await
42 .map_err(|e| match e {
43 crate::mount_ops::MountOpsError::BucketNotFound(id) => CatError::BucketNotFound(id),
44 crate::mount_ops::MountOpsError::InvalidPath(msg) => CatError::InvalidPath(msg),
45 crate::mount_ops::MountOpsError::Mount(me) => CatError::Mount(me),
46 e => CatError::MountOps(e.to_string()),
47 })?;
48
49 let content = base64::engine::general_purpose::STANDARD.encode(&file_content.data);
51 let size = file_content.data.len();
52
53 Ok((
54 http::StatusCode::OK,
55 Json(CatResponse {
56 path: req.path,
57 content,
58 size,
59 mime_type: file_content.mime_type,
60 }),
61 )
62 .into_response())
63}
64
65#[derive(Debug, thiserror::Error)]
66pub enum CatError {
67 #[error("Bucket not found: {0}")]
68 BucketNotFound(Uuid),
69 #[error("Invalid path: {0}")]
70 InvalidPath(String),
71 #[error("MountOps error: {0}")]
72 MountOps(String),
73 #[error("Mount error: {0}")]
74 Mount(#[from] MountError),
75}
76
77impl IntoResponse for CatError {
78 fn into_response(self) -> Response {
79 match self {
80 CatError::BucketNotFound(id) => (
81 http::StatusCode::NOT_FOUND,
82 format!("Bucket not found: {}", id),
83 )
84 .into_response(),
85 CatError::InvalidPath(msg) => (
86 http::StatusCode::BAD_REQUEST,
87 format!("Invalid path: {}", msg),
88 )
89 .into_response(),
90 CatError::MountOps(_) | CatError::Mount(_) => (
91 http::StatusCode::INTERNAL_SERVER_ERROR,
92 "Unexpected error".to_string(),
93 )
94 .into_response(),
95 }
96 }
97}
98
99impl ApiRequest for CatRequest {
101 type Response = CatResponse;
102
103 fn build_request(self, base_url: &Url, client: &Client) -> RequestBuilder {
104 let full_url = base_url.join("/api/v0/bucket/cat").unwrap();
105 client.post(full_url).json(&self)
106 }
107}