1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-02-23 13:02:28 +00:00

add optional fs support

This commit is contained in:
Dominic 2020-04-29 20:45:31 +02:00
parent e013af8e18
commit 66e9ce96b9
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
4 changed files with 96 additions and 11 deletions

View file

@ -32,6 +32,7 @@ mime = "0.3.16"
openapiv3 = { version = "0.3", optional = true } openapiv3 = { version = "0.3", optional = true }
serde = { version = "1.0.106", features = ["derive"] } serde = { version = "1.0.106", features = ["derive"] }
serde_json = "1.0.51" serde_json = "1.0.51"
tokio = { version = "0.2.20", optional = true }
thiserror = "1.0.15" thiserror = "1.0.15"
uuid = { version = ">= 0.1, < 0.9", optional = true } uuid = { version = ">= 0.1, < 0.9", optional = true }
@ -40,8 +41,9 @@ futures-executor = "0.3.4"
paste = "0.1.10" paste = "0.1.10"
[features] [features]
default = [] default = ["fs"]
auth = ["gotham_restful_derive/auth", "base64", "cookie", "jsonwebtoken"] auth = ["gotham_restful_derive/auth", "base64", "cookie", "jsonwebtoken"]
fs = ["tokio", "tokio/fs"]
errorlog = [] errorlog = []
database = ["gotham_restful_derive/database", "gotham_middleware_diesel"] database = ["gotham_restful_derive/database", "gotham_middleware_diesel"]
openapi = ["gotham_restful_derive/openapi", "indexmap", "openapiv3"] openapi = ["gotham_restful_derive/openapi", "indexmap", "openapiv3"]

78
gotham_restful/src/fs.rs Normal file
View file

@ -0,0 +1,78 @@
use crate::{
result::{errorlog, into_response_helper, ResourceError},
OpenapiSchema, ResourceResult, Response
};
use futures_util::future::{FutureExt, TryFutureExt};
use gotham::hyper::StatusCode;
use mime::Mime;
use openapiv3::{SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty};
use std::{
future::Future,
path::PathBuf,
pin::Pin
};
use thiserror::Error;
pub struct File
{
path : PathBuf,
content_type : Option<Mime>
}
impl ResourceResult for File
{
type Err = tokio::io::Error;
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>
{
async move {
let data = tokio::fs::read(self.path).await?;
let res = Response::new(StatusCode::OK, data, self.content_type);
Ok(res)
}.boxed()
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
format: VariantOrUnknownOrEmpty::Item(StringFormat::Binary),
..Default::default()
})))
}
}
#[derive(Debug, Error)]
pub enum IoOrJsonError
{
#[error("{0}")]
IoError(#[from] tokio::io::Error),
#[error("{0}")]
JsonError(#[from] serde_json::Error)
}
impl<E : std::error::Error + Send + 'static> ResourceResult for Result<File, E>
{
type Err = IoOrJsonError;
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, IoOrJsonError>> + Send>>
{
match self {
Ok(f) => f.into_response().map_err(|e| e.into()).boxed(),
Err(e) => into_response_helper(|| {
errorlog(&e);
let err : ResourceError = e.into();
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
})
}
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
format: VariantOrUnknownOrEmpty::Item(StringFormat::Binary),
..Default::default()
})))
}
}

View file

@ -152,6 +152,11 @@ pub use auth::{
StaticAuthHandler StaticAuthHandler
}; };
#[cfg(feature = "fs")]
mod fs;
#[cfg(feature = "fs")]
pub use fs::File;
pub mod matcher; pub mod matcher;
#[cfg(feature = "openapi")] #[cfg(feature = "openapi")]

View file

@ -132,7 +132,7 @@ impl<T : ToString> From<T> for ResourceError
} }
} }
fn into_response_helper<Err, F>(create_response : F) -> Pin<Box<dyn Future<Output = Result<Response, Err>> + Send>> pub fn into_response_helper<Err, F>(create_response : F) -> Pin<Box<dyn Future<Output = Result<Response, Err>> + Send>>
where where
Err : Send + 'static, Err : Send + 'static,
F : FnOnce() -> Result<Response, Err> F : FnOnce() -> Result<Response, Err>
@ -142,13 +142,13 @@ where
} }
#[cfg(feature = "errorlog")] #[cfg(feature = "errorlog")]
fn errorlog<E : std::fmt::Display>(e : E) pub fn errorlog<E : std::fmt::Display>(e : E)
{ {
error!("The handler encountered an error: {}", e); error!("The handler encountered an error: {}", e);
} }
#[cfg(not(feature = "errorlog"))] #[cfg(not(feature = "errorlog"))]
fn errorlog<E>(_e : E) {} pub fn errorlog<E>(_e : E) {}
impl<R : ResponseBody, E : Error> ResourceResult for Result<R, E> impl<R : ResponseBody, E : Error> ResourceResult for Result<R, E>
where where
@ -413,13 +413,11 @@ impl<T : ResourceResult<Err = SerdeJsonError>, E : Error> ResourceResult for Res
{ {
match self { match self {
Ok(r) => r.into_response(), Ok(r) => r.into_response(),
Err(e) => { Err(e) => into_response_helper(|| {
into_response_helper(|| { errorlog(&e);
errorlog(&e); let err : ResourceError = e.into();
let err : ResourceError = e.into(); Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?)) })
})
}
} }
} }
@ -514,6 +512,7 @@ where
match self { match self {
Ok(nc) => nc.into_response(), Ok(nc) => nc.into_response(),
Err(e) => into_response_helper(|| { Err(e) => into_response_helper(|| {
errorlog(&e);
let err : ResourceError = e.into(); let err : ResourceError = e.into();
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?)) Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
}) })
@ -603,6 +602,7 @@ where
match self { match self {
Ok(raw) => raw.into_response(), Ok(raw) => raw.into_response(),
Err(e) => into_response_helper(|| { Err(e) => into_response_helper(|| {
errorlog(&e);
let err : ResourceError = e.into(); let err : ResourceError = e.into();
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?)) Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
}) })