Skip to content

Commit

Permalink
resolves #5: rework blob endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
PetoMPP committed Feb 13, 2024
1 parent e3a9c36 commit 555fa0e
Show file tree
Hide file tree
Showing 15 changed files with 352 additions and 345 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jwt = "0.16"
lazy_static = "1.4"
num-traits = "0.2"
num-derive = "0.4"
petompp-web-models = { git = "https://github.com/PetoMPP/petompp-web-models.git", branch = "0.5.5", features = [
petompp-web-models = { git = "https://github.com/PetoMPP/petompp-web-models.git", branch = "0.7.0", features = [
"api-errors",
] }
r2d2 = "0.8"
Expand Down
1 change: 1 addition & 0 deletions Rocket.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[default.limits]
form = "64 kB"
bytes = "20 MiB"
json = "1 MiB"
msgpack = "2 MiB"
file = "20 MiB"
Expand Down
129 changes: 129 additions & 0 deletions src/controllers/blob.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use super::controller::Controller;
use crate::services::azure_blob::AzureBlobService;
use azure_storage_blobs::prelude::ClientBuilder;
use petompp_web_models::{
error::ApiError,
models::{
api_response::ApiResponse,
blob::blob_meta::{BlobMetaData, BlobMetaDto},
},
};
use rocket::{
delete,
form::{Form, FromFormField},
get,
http::uri::{fmt::Path, Segments},
post, routes,
serde::json::Json,
FromForm, State,
};
use serde::{Deserialize, Serialize};

pub struct BlobController;

impl Controller for BlobController {
fn path(&self) -> &'static str {
"/blob"
}

fn routes(&self) -> Vec<rocket::Route> {
routes![get, get_all, create_or_update, delete]
}
}

pub enum BlobDataMode {
Full,
Name,
}

#[derive(Clone, Serialize, Deserialize)]
pub enum BlobsResponse {
Full(Vec<BlobMetaData>),
Name(Vec<String>),
}

impl<'a> FromFormField<'a> for BlobDataMode {
fn from_value(field: rocket::form::ValueField<'a>) -> rocket::form::Result<'a, Self> {
match field.value {
"full" => Ok(BlobDataMode::Full),
"name" => Ok(BlobDataMode::Name),
_ => Err(rocket::form::Error::validation("Invalid blob data mode".to_string()).into()),
}
}
}

#[get("/<container>/<filename..>")]
async fn get<'a>(
container: &'a str,
filename: Segments<'a, Path>,
blob_service: &'a State<ClientBuilder>,
) -> Result<Json<ApiResponse<'a, BlobMetaData>>, ApiError<'a>> {
let filename = filename
.into_iter()
.fold(String::new(), |f, s| format!("{}/{}", f, s))[1..]
.to_string();
Ok(Json(ApiResponse::ok(
blob_service
.get(container.to_string(), filename.to_string())
.await?,
)))
}

#[get("/<container>?<data>&<prefix>")]
async fn get_all<'a>(
container: &'a str,
data: BlobDataMode,
prefix: Option<&'a str>,
blob_service: &'a State<ClientBuilder>,
) -> Result<Json<ApiResponse<'a, BlobsResponse>>, ApiError<'a>> {
match data {
BlobDataMode::Full => Ok(Json(ApiResponse::ok(BlobsResponse::Full(
blob_service
.get_all(container.to_string(), prefix.map(|s| s.to_string()))
.await?,
)))),
BlobDataMode::Name => Ok(Json(ApiResponse::ok(BlobsResponse::Name(
blob_service
.get_all(container.to_string(), prefix.map(|s| s.to_string()))
.await?
.into_iter()
.map(|b| b.filename)
.collect(),
)))),
}
}

#[derive(FromForm)]
struct BlobUploadForm<'a> {
meta: BlobMetaDto,
content: &'a [u8],
}

#[post("/<container>", data = "<value>")]
async fn create_or_update<'a>(
container: &'a str,
blob_service: &'a State<ClientBuilder>,
value: Form<BlobUploadForm<'a>>,
) -> Result<Json<ApiResponse<'a, String>>, ApiError<'a>> {
Ok(Json(ApiResponse::ok(
blob_service
.create_or_update(container.to_string(), value.meta.clone(), value.content)
.await?,
)))
}

#[delete("/<container>/<prefix..>")]
async fn delete<'a>(
container: &'a str,
prefix: Segments<'a, Path>,
blob_service: &'a State<ClientBuilder>,
) -> Result<Json<ApiResponse<'a, String>>, ApiError<'a>> {
let prefix = prefix
.into_iter()
.fold(String::new(), |f, s| format!("{}/{}", f, s))[1..]
.to_string();
let deleted = blob_service
.delete(container.to_string(), prefix.to_string())
.await?;
Ok(Json(ApiResponse::ok(format!("deleted: {} blobs", deleted))))
}
86 changes: 0 additions & 86 deletions src/controllers/blog.rs

This file was deleted.

5 changes: 3 additions & 2 deletions src/controllers/health.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::controller::Controller;
use crate::{services::azure_blob::AzureBlobService, PgPool};
use crate::{services::azure_test::AzureTestService, PgPool};
use azure_storage_blobs::prelude::ClientBuilder;
use diesel::r2d2::R2D2Connection;
use petompp_web_models::{
error::{ApiError, Error},
Expand All @@ -22,7 +23,7 @@ impl Controller for HealthController {
#[get("/")]
async fn health<'a>(
pool: &'a rocket::State<PgPool>,
azure_blob_service: &'a rocket::State<AzureBlobService>,
azure_blob_service: &'a rocket::State<ClientBuilder>,
) -> Result<Json<ApiResponse<'a, &'a str>>, ApiError<'a>> {
// test database connection
let mut conn = pool.get().map_err::<Error, _>(|e| e.into())?;
Expand Down
86 changes: 0 additions & 86 deletions src/controllers/image.rs

This file was deleted.

3 changes: 1 addition & 2 deletions src/controllers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub mod blog;
pub mod blob;
pub mod controller;
pub mod health;
pub mod image;
pub mod resources;
pub mod user_settings;
pub mod users;
Loading

0 comments on commit 555fa0e

Please sign in to comment.