mirror of https://github.com/LemmyNet/lemmy.git
Make conditional compilation gates for utils
parent
a9e6f33038
commit
75f0bde6b2
|
@ -2872,6 +2872,7 @@ version = "0.19.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"cfg-if",
|
||||||
"deser-hjson",
|
"deser-hjson",
|
||||||
"diesel",
|
"diesel",
|
||||||
"doku",
|
"doku",
|
||||||
|
|
|
@ -13,42 +13,95 @@ name = "lemmy_utils"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "lemmy_util_bin"
|
||||||
|
path = "src/main.rs"
|
||||||
|
required-features = ["default"]
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
full = ["ts-rs"]
|
default = [
|
||||||
|
"error",
|
||||||
|
"request",
|
||||||
|
"response",
|
||||||
|
"settings",
|
||||||
|
"misc",
|
||||||
|
"rate-limit",
|
||||||
|
"apub",
|
||||||
|
"cache-header",
|
||||||
|
"email"
|
||||||
|
]
|
||||||
|
full = ["default", "ts-rs"]
|
||||||
|
ts-rs = ["dep:ts-rs"]
|
||||||
|
error-type = ["dep:serde", "dep:strum"]
|
||||||
|
error = [
|
||||||
|
"error-type",
|
||||||
|
"dep:serde_json",
|
||||||
|
"dep:anyhow",
|
||||||
|
"dep:tracing-error",
|
||||||
|
"dep:diesel",
|
||||||
|
"dep:http",
|
||||||
|
"dep:actix-web"
|
||||||
|
]
|
||||||
|
request = ["dep:reqwest-middleware", "dep:tracing", "dep:strum"]
|
||||||
|
response = ["error", "dep:actix-web"]
|
||||||
|
settings = [
|
||||||
|
"error",
|
||||||
|
"dep:deser-hjson",
|
||||||
|
"dep:regex",
|
||||||
|
"dep:urlencoding",
|
||||||
|
"dep:doku",
|
||||||
|
"dep:url",
|
||||||
|
"dep:once_cell",
|
||||||
|
"dep:smart-default"
|
||||||
|
]
|
||||||
|
rate-limit = [
|
||||||
|
"error",
|
||||||
|
"dep:enum-map",
|
||||||
|
"dep:tracing",
|
||||||
|
"dep:actix-web",
|
||||||
|
"dep:futures",
|
||||||
|
"dep:tokio",
|
||||||
|
"dep:once_cell"
|
||||||
|
]
|
||||||
|
apub = ["dep:openssl"]
|
||||||
|
cache-header = ["dep:actix-web"]
|
||||||
|
email = ["error", "settings", "dep:html2text", "dep:lettre", "dep:uuid", "dep:rosetta-i18n"]
|
||||||
|
misc = ["settings", "dep:itertools", "dep:markdown-it", "dep:tokio", "dep:futures", "dep:tracing"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = { workspace = true }
|
regex = { workspace = true, optional = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true, optional = true }
|
||||||
tracing-error = { workspace = true }
|
tracing-error = { workspace = true, optional = true }
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true, optional = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true, optional = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true, optional = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true, optional = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true, optional = true }
|
||||||
actix-web = { workspace = true }
|
actix-web = { workspace = true, optional = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true, optional = true }
|
||||||
reqwest-middleware = { workspace = true }
|
reqwest-middleware = { workspace = true, optional = true }
|
||||||
strum = { workspace = true }
|
strum = { workspace = true, optional = true }
|
||||||
strum_macros = { workspace = true }
|
strum_macros = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true, optional = true }
|
||||||
diesel = { workspace = true, features = ["chrono"] }
|
diesel = { workspace = true, features = ["chrono"], optional = true }
|
||||||
http = { workspace = true }
|
http = { workspace = true, optional = true }
|
||||||
doku = { workspace = true, features = ["url-2"] }
|
doku = { workspace = true, features = ["url-2"], optional = true }
|
||||||
uuid = { workspace = true, features = ["serde", "v4"] }
|
uuid = { workspace = true, features = ["serde", "v4"], optional = true}
|
||||||
rosetta-i18n = { workspace = true }
|
rosetta-i18n = { workspace = true, optional = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true, optional = true }
|
||||||
urlencoding = { workspace = true }
|
urlencoding = { workspace = true, optional = true }
|
||||||
openssl = "0.10.63"
|
openssl = { version = "0.10.63", optional = true }
|
||||||
html2text = "0.6.0"
|
html2text = { version = "0.6.0", optional = true }
|
||||||
deser-hjson = "2.2.4"
|
deser-hjson = { version = "2.2.4", optional = true }
|
||||||
smart-default = "0.7.1"
|
smart-default = { version = "0.7.1", optional = true }
|
||||||
lettre = { version = "0.11.3", features = ["tokio1", "tokio1-native-tls"] }
|
lettre = { version = "0.11.3", features = ["tokio1", "tokio1-native-tls"], optional = true }
|
||||||
markdown-it = "0.6.0"
|
markdown-it = { version = "0.6.0", optional = true }
|
||||||
ts-rs = { workspace = true, optional = true }
|
ts-rs = { workspace = true, optional = true }
|
||||||
enum-map = { workspace = true }
|
enum-map = { workspace = true, optional = true }
|
||||||
|
cfg-if = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
reqwest = { workspace = true }
|
reqwest = { workspace = true }
|
||||||
|
|
|
@ -1,78 +1,13 @@
|
||||||
|
use cfg_if::cfg_if;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::fmt::Debug;
|
||||||
fmt,
|
use strum_macros::{Display, EnumIter};
|
||||||
fmt::{Debug, Display},
|
#[cfg(feature = "ts-rs")]
|
||||||
};
|
|
||||||
use tracing_error::SpanTrace;
|
|
||||||
#[cfg(feature = "full")]
|
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
pub type LemmyResult<T> = Result<T, LemmyError>;
|
|
||||||
|
|
||||||
pub struct LemmyError {
|
|
||||||
pub error_type: LemmyErrorType,
|
|
||||||
pub inner: anyhow::Error,
|
|
||||||
pub context: SpanTrace,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Maximum number of items in an array passed as API parameter. See [[LemmyErrorType::TooManyItems]]
|
|
||||||
pub const MAX_API_PARAM_ELEMENTS: usize = 10_000;
|
|
||||||
|
|
||||||
impl<T> From<T> for LemmyError
|
|
||||||
where
|
|
||||||
T: Into<anyhow::Error>,
|
|
||||||
{
|
|
||||||
fn from(t: T) -> Self {
|
|
||||||
let cause = t.into();
|
|
||||||
LemmyError {
|
|
||||||
error_type: LemmyErrorType::Unknown(format!("{}", &cause)),
|
|
||||||
inner: cause,
|
|
||||||
context: SpanTrace::capture(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for LemmyError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.debug_struct("LemmyError")
|
|
||||||
.field("message", &self.error_type)
|
|
||||||
.field("inner", &self.inner)
|
|
||||||
.field("context", &self.context)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for LemmyError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}: ", &self.error_type)?;
|
|
||||||
// print anyhow including trace
|
|
||||||
// https://docs.rs/anyhow/latest/anyhow/struct.Error.html#display-representations
|
|
||||||
// this will print the anyhow trace (only if it exists)
|
|
||||||
// and if RUST_BACKTRACE=1, also a full backtrace
|
|
||||||
writeln!(f, "{:?}", self.inner)?;
|
|
||||||
fmt::Display::fmt(&self.context, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl actix_web::error::ResponseError for LemmyError {
|
|
||||||
fn status_code(&self) -> http::StatusCode {
|
|
||||||
if self.error_type == LemmyErrorType::IncorrectLogin {
|
|
||||||
return http::StatusCode::UNAUTHORIZED;
|
|
||||||
}
|
|
||||||
match self.inner.downcast_ref::<diesel::result::Error>() {
|
|
||||||
Some(diesel::result::Error::NotFound) => http::StatusCode::NOT_FOUND,
|
|
||||||
_ => http::StatusCode::BAD_REQUEST,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn error_response(&self) -> actix_web::HttpResponse {
|
|
||||||
actix_web::HttpResponse::build(self.status_code()).json(&self.error_type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Display, Debug, Serialize, Deserialize, Clone, PartialEq, EnumIter)]
|
#[derive(Display, Debug, Serialize, Deserialize, Clone, PartialEq, EnumIter)]
|
||||||
#[cfg_attr(feature = "full", derive(TS))]
|
#[cfg_attr(feature = "ts-rs", derive(TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "ts-rs", ts(export))]
|
||||||
#[serde(tag = "error", content = "message", rename_all = "snake_case")]
|
#[serde(tag = "error", content = "message", rename_all = "snake_case")]
|
||||||
// TODO: order these based on the crate they belong to (utils, federation, db, api)
|
// TODO: order these based on the crate they belong to (utils, federation, db, api)
|
||||||
pub enum LemmyErrorType {
|
pub enum LemmyErrorType {
|
||||||
|
@ -231,6 +166,74 @@ pub enum LemmyErrorType {
|
||||||
Unknown(String),
|
Unknown(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "error")] {
|
||||||
|
|
||||||
|
use tracing_error::SpanTrace;
|
||||||
|
use std::fmt;
|
||||||
|
pub type LemmyResult<T> = Result<T, LemmyError>;
|
||||||
|
|
||||||
|
pub struct LemmyError {
|
||||||
|
pub error_type: LemmyErrorType,
|
||||||
|
pub inner: anyhow::Error,
|
||||||
|
pub context: SpanTrace,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Maximum number of items in an array passed as API parameter. See [[LemmyErrorType::TooManyItems]]
|
||||||
|
pub const MAX_API_PARAM_ELEMENTS: usize = 10_000;
|
||||||
|
|
||||||
|
impl<T> From<T> for LemmyError
|
||||||
|
where
|
||||||
|
T: Into<anyhow::Error>,
|
||||||
|
{
|
||||||
|
fn from(t: T) -> Self {
|
||||||
|
let cause = t.into();
|
||||||
|
LemmyError {
|
||||||
|
error_type: LemmyErrorType::Unknown(format!("{}", &cause)),
|
||||||
|
inner: cause,
|
||||||
|
context: SpanTrace::capture(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for LemmyError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("LemmyError")
|
||||||
|
.field("message", &self.error_type)
|
||||||
|
.field("inner", &self.inner)
|
||||||
|
.field("context", &self.context)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for LemmyError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}: ", &self.error_type)?;
|
||||||
|
// print anyhow including trace
|
||||||
|
// https://docs.rs/anyhow/latest/anyhow/struct.Error.html#display-representations
|
||||||
|
// this will print the anyhow trace (only if it exists)
|
||||||
|
// and if RUST_BACKTRACE=1, also a full backtrace
|
||||||
|
writeln!(f, "{:?}", self.inner)?;
|
||||||
|
fmt::Display::fmt(&self.context, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl actix_web::error::ResponseError for LemmyError {
|
||||||
|
fn status_code(&self) -> http::StatusCode {
|
||||||
|
if self.error_type == LemmyErrorType::IncorrectLogin {
|
||||||
|
return http::StatusCode::UNAUTHORIZED;
|
||||||
|
}
|
||||||
|
match self.inner.downcast_ref::<diesel::result::Error>() {
|
||||||
|
Some(diesel::result::Error::NotFound) => http::StatusCode::NOT_FOUND,
|
||||||
|
_ => http::StatusCode::BAD_REQUEST,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error_response(&self) -> actix_web::HttpResponse {
|
||||||
|
actix_web::HttpResponse::build(self.status_code()).json(&self.error_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<LemmyErrorType> for LemmyError {
|
impl From<LemmyErrorType> for LemmyError {
|
||||||
fn from(error_type: LemmyErrorType) -> Self {
|
fn from(error_type: LemmyErrorType) -> Self {
|
||||||
let inner = anyhow::anyhow!("{}", error_type);
|
let inner = anyhow::anyhow!("{}", error_type);
|
||||||
|
@ -273,6 +276,9 @@ impl<T> LemmyErrorExt2<T> for Result<T, LemmyError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
#[macro_use]
|
#[cfg(feature = "apub")]
|
||||||
extern crate strum_macros;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate smart_default;
|
|
||||||
|
|
||||||
pub mod apub;
|
pub mod apub;
|
||||||
|
#[cfg(feature = "cache-header")]
|
||||||
pub mod cache_header;
|
pub mod cache_header;
|
||||||
|
#[cfg(feature = "email")]
|
||||||
pub mod email;
|
pub mod email;
|
||||||
|
#[cfg(feature = "error-type")]
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
#[cfg(feature = "rate-limit")]
|
||||||
pub mod rate_limit;
|
pub mod rate_limit;
|
||||||
|
#[cfg(feature = "request")]
|
||||||
pub mod request;
|
pub mod request;
|
||||||
|
#[cfg(feature = "response")]
|
||||||
pub mod response;
|
pub mod response;
|
||||||
|
#[cfg(feature = "settings")]
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
#[cfg(feature = "misc")]
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|
||||||
use error::LemmyError;
|
|
||||||
use futures::Future;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing::Instrument;
|
|
||||||
|
|
||||||
pub type ConnectionId = usize;
|
pub type ConnectionId = usize;
|
||||||
|
|
||||||
|
@ -35,10 +36,14 @@ macro_rules! location_info {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "misc")]
|
||||||
/// tokio::spawn, but accepts a future that may fail and also
|
/// tokio::spawn, but accepts a future that may fail and also
|
||||||
/// * logs errors
|
/// * logs errors
|
||||||
/// * attaches the spawned task to the tracing span of the caller for better logging
|
/// * attaches the spawned task to the tracing span of the caller for better logging
|
||||||
pub fn spawn_try_task(task: impl Future<Output = Result<(), LemmyError>> + Send + 'static) {
|
pub fn spawn_try_task(
|
||||||
|
task: impl futures::Future<Output = Result<(), error::LemmyError>> + Send + 'static,
|
||||||
|
) {
|
||||||
|
use tracing::Instrument;
|
||||||
tokio::spawn(
|
tokio::spawn(
|
||||||
async {
|
async {
|
||||||
if let Err(e) = task.await {
|
if let Err(e) = task.await {
|
||||||
|
|
|
@ -2,8 +2,7 @@ use crate::error::{LemmyError, LemmyErrorType};
|
||||||
use actix_web::dev::{ConnectionInfo, Service, ServiceRequest, ServiceResponse, Transform};
|
use actix_web::dev::{ConnectionInfo, Service, ServiceRequest, ServiceResponse, Transform};
|
||||||
use enum_map::{enum_map, EnumMap};
|
use enum_map::{enum_map, EnumMap};
|
||||||
use futures::future::{ok, Ready};
|
use futures::future::{ok, Ready};
|
||||||
pub use rate_limiter::{ActionType, BucketConfig};
|
use rate_limiter::{ActionType, BucketConfig, InstantSecs, RateLimitState};
|
||||||
use rate_limiter::{InstantSecs, RateLimitState};
|
|
||||||
use std::{
|
use std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::{
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
use strum_macros::AsRefStr;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
static START_TIME: Lazy<Instant> = Lazy::new(Instant::now);
|
static START_TIME: Lazy<Instant> = Lazy::new(Instant::now);
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
use crate::{
|
use crate::{error::LemmyError, location_info};
|
||||||
error::LemmyError,
|
|
||||||
location_info,
|
|
||||||
settings::structs::{PictrsConfig, Settings},
|
|
||||||
};
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use deser_hjson::from_str;
|
use deser_hjson::from_str;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
@ -12,8 +8,7 @@ use urlencoding::encode;
|
||||||
|
|
||||||
pub mod structs;
|
pub mod structs;
|
||||||
|
|
||||||
use crate::settings::structs::PictrsImageMode;
|
use structs::{DatabaseConnection, PictrsConfig, PictrsImageMode, Settings};
|
||||||
use structs::DatabaseConnection;
|
|
||||||
|
|
||||||
static DEFAULT_CONFIG_FILE: &str = "config/config.hjson";
|
static DEFAULT_CONFIG_FILE: &str = "config/config.hjson";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use doku::Document;
|
use doku::Document;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use smart_default::SmartDefault;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
net::{IpAddr, Ipv4Addr},
|
net::{IpAddr, Ipv4Addr},
|
||||||
|
|
Loading…
Reference in New Issue