mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
update
This commit is contained in:
Generated
+6
-6
@@ -2266,9 +2266,9 @@ checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libmimalloc-sys"
|
name = "libmimalloc-sys"
|
||||||
version = "0.1.48"
|
version = "0.1.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2892ae4ea6fa2cb7acb0e236a6880d39523239cd9089de71d220910ccc806790"
|
checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
@@ -2479,9 +2479,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mimalloc"
|
name = "mimalloc"
|
||||||
version = "0.1.51"
|
version = "0.1.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ebca48a43116bc25f18a61360f1be98412f50cc218f5e52c823086b999a4a21a"
|
checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libmimalloc-sys",
|
"libmimalloc-sys",
|
||||||
]
|
]
|
||||||
@@ -3943,9 +3943,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.149"
|
version = "1.0.150"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@ members = [
|
|||||||
"crates/server",
|
"crates/server",
|
||||||
"crates/cli",
|
"crates/cli",
|
||||||
"crates/admin",
|
"crates/admin",
|
||||||
|
"crates/smtp",
|
||||||
]
|
]
|
||||||
|
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
@@ -17,12 +18,12 @@ edition = "2021"
|
|||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
chrono = "0.4.44"
|
chrono = "0.4.44"
|
||||||
clap = { version = "4.6.1", features = ["derive", "env"] }
|
clap = { version = "4.6.1", features = ["derive", "env"] }
|
||||||
mimalloc = "0.1.51"
|
mimalloc = "0.1.52"
|
||||||
memdb = { path = "crates/memdb" }
|
memdb = { path = "crates/memdb" }
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
ring = { version = "0.17.14", features = ["std"] }
|
ring = { version = "0.17.14", features = ["std"] }
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.150"
|
||||||
tokio = { version = "1.52.3", features = ["full"] }
|
tokio = { version = "1.52.3", features = ["full"] }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
tracing-appender = "0.2.3"
|
tracing-appender = "0.2.3"
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2025-2026 rustmailer.com (https://rustmailer.com)
|
||||||
|
//
|
||||||
|
// This file is part of the Bichon Email Archiving Project
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
pub mod common;
|
||||||
|
pub mod error;
|
||||||
|
pub mod rest;
|
||||||
|
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
use bichon_core::{
|
||||||
|
bichon_version,
|
||||||
|
cache::imap::task::SYNC_TASKS,
|
||||||
|
common::{rustls::BichonTls, signal::SignalManager},
|
||||||
|
context::{executors::BichonContext, Initialize},
|
||||||
|
error::{code::ErrorCode, BichonResult},
|
||||||
|
logger,
|
||||||
|
migrate::check_data_status,
|
||||||
|
raise_error,
|
||||||
|
settings::{cli::SETTINGS, dir::DataDirManager},
|
||||||
|
store::{
|
||||||
|
blob::BLOB_MANAGER,
|
||||||
|
tantivy::{attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER},
|
||||||
|
},
|
||||||
|
tasks::PeriodicTasks,
|
||||||
|
users::manager::UserManager,
|
||||||
|
};
|
||||||
|
use bichon_smtp::server::{start_smtp_server, SmtpServer};
|
||||||
|
use tracing::{error, info};
|
||||||
|
|
||||||
|
pub async fn run() -> BichonResult<()> {
|
||||||
|
logger::initialize_logging();
|
||||||
|
info!(
|
||||||
|
r#"
|
||||||
|
_ _ _
|
||||||
|
| | (_) | |
|
||||||
|
| |__ _ ___ | |__ ___ _ __
|
||||||
|
| '_ \ | | / __|| '_ \ / _ \ | '_ \
|
||||||
|
| |_) || || (__ | | | || (_) || | | |
|
||||||
|
|_.__/ |_| \___||_| |_| \___/ |_| |_|
|
||||||
|
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
info!("Starting bichon-server");
|
||||||
|
info!("Version: {}", bichon_version!());
|
||||||
|
info!("Git: [{}]", env!("GIT_HASH"));
|
||||||
|
info!("GitHub: https://github.com/rustmailer/bichon");
|
||||||
|
|
||||||
|
match check_data_status() {
|
||||||
|
Ok(false) => {
|
||||||
|
error!("Incompatible data format detected.");
|
||||||
|
error!("Your data was created by an older version of Bichon and must be migrated before use.");
|
||||||
|
error!("Please stop the Bichon v0.3.7 service before migration.");
|
||||||
|
error!("Please run: bichon-admin");
|
||||||
|
error!("Documentation: https://github.com/rustmailer/bichon/wiki/Bichon-Data-Migration:-v0.3.7-%E2%86%92-v1.0");
|
||||||
|
return Err(raise_error!(
|
||||||
|
"Legacy data layout detected".into(),
|
||||||
|
ErrorCode::InternalError
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to check data layout: {:#?}", e);
|
||||||
|
return Err(raise_error!(format!("{:#?}", e), ErrorCode::InternalError));
|
||||||
|
}
|
||||||
|
Ok(true) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(error) = initialize().await {
|
||||||
|
eprintln!("{:?}", error);
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let periodic_tasks = PeriodicTasks::setup();
|
||||||
|
let mut smtp_service: Option<SmtpServer> = None;
|
||||||
|
if SETTINGS.bichon_enable_smtp {
|
||||||
|
info!("SMTP service is enabled, starting...");
|
||||||
|
match start_smtp_server().await {
|
||||||
|
Ok(server) => {
|
||||||
|
info!("SMTP server listening on: {}", server.smtp_addr);
|
||||||
|
smtp_service = Some(server);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to start SMTP server: {}", e);
|
||||||
|
return Err(raise_error!(format!("{:#?}", e), ErrorCode::InternalError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info!("SMTP service is disabled by configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
rest::start_http_server().await?;
|
||||||
|
periodic_tasks.shutdown().await;
|
||||||
|
|
||||||
|
if let Some(server) = smtp_service {
|
||||||
|
info!("Shutting down SMTP server...");
|
||||||
|
server.stop().await;
|
||||||
|
info!("SMTP server stopped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SYNC_TASKS.shutdown().await;
|
||||||
|
ENVELOPE_MANAGER.shutdown().await;
|
||||||
|
ATTACHMENT_MANAGER.shutdown().await;
|
||||||
|
BLOB_MANAGER.shutdown().await;
|
||||||
|
info!("Bichon server stopped.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn initialize() -> BichonResult<()> {
|
||||||
|
SignalManager::initialize().await?;
|
||||||
|
DataDirManager::initialize().await?;
|
||||||
|
UserManager::initialize().await?;
|
||||||
|
BichonTls::initialize().await?;
|
||||||
|
BichonContext::initialize().await?;
|
||||||
|
LazyLock::force(&BLOB_MANAGER);
|
||||||
|
LazyLock::force(&ENVELOPE_MANAGER);
|
||||||
|
LazyLock::force(&ATTACHMENT_MANAGER);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+2
-193
@@ -16,205 +16,14 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
|
||||||
|
|
||||||
use bichon_core::{
|
use bichon_core::error::BichonResult;
|
||||||
bichon_version,
|
|
||||||
cache::imap::task::SYNC_TASKS,
|
|
||||||
common::rustls::BichonTls,
|
|
||||||
context::{executors::BichonContext, Initialize},
|
|
||||||
error::{code::ErrorCode, BichonResult},
|
|
||||||
logger,
|
|
||||||
migrate::check_data_status,
|
|
||||||
raise_error,
|
|
||||||
settings::cli::SETTINGS,
|
|
||||||
store::{
|
|
||||||
blob::BLOB_MANAGER,
|
|
||||||
tantivy::{attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER},
|
|
||||||
},
|
|
||||||
tasks::PeriodicTasks,
|
|
||||||
};
|
|
||||||
use bichon_smtp::server::{start_smtp_server, SmtpServer};
|
|
||||||
use mimalloc::MiMalloc;
|
use mimalloc::MiMalloc;
|
||||||
use tracing::{error, info};
|
|
||||||
|
|
||||||
use bichon_core::{
|
|
||||||
common::signal::SignalManager, settings::dir::DataDirManager, users::manager::UserManager,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::rest::start_http_server;
|
|
||||||
|
|
||||||
pub mod common;
|
|
||||||
pub mod error;
|
|
||||||
pub mod rest;
|
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: MiMalloc = MiMalloc;
|
static GLOBAL: MiMalloc = MiMalloc;
|
||||||
|
|
||||||
static LOGO: &str = r#"
|
|
||||||
_ _ _
|
|
||||||
| | (_) | |
|
|
||||||
| |__ _ ___ | |__ ___ _ __
|
|
||||||
| '_ \ | | / __|| '_ \ / _ \ | '_ \
|
|
||||||
| |_) || || (__ | | | || (_) || | | |
|
|
||||||
|_.__/ |_| \___||_| |_| \___/ |_| |_|
|
|
||||||
|
|
||||||
"#;
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> BichonResult<()> {
|
async fn main() -> BichonResult<()> {
|
||||||
logger::initialize_logging();
|
bichon_server::run().await
|
||||||
info!("{}", LOGO);
|
|
||||||
info!("Starting bichon-server");
|
|
||||||
info!("Version: {}", bichon_version!());
|
|
||||||
info!("Git: [{}]", env!("GIT_HASH"));
|
|
||||||
info!("GitHub: https://github.com/rustmailer/bichon");
|
|
||||||
|
|
||||||
match check_data_status() {
|
|
||||||
Ok(false) => {
|
|
||||||
error!("Incompatible data format detected.");
|
|
||||||
error!("Your data was created by an older version of Bichon and must be migrated before use.");
|
|
||||||
error!("Please stop the Bichon v0.3.7 service before migration.");
|
|
||||||
error!("Please run: bichon-admin");
|
|
||||||
error!("Documentation: https://github.com/rustmailer/bichon/wiki/Bichon-Data-Migration:-v0.3.7-%E2%86%92-v1.0");
|
|
||||||
return Err(raise_error!(
|
|
||||||
"Legacy data layout detected".into(),
|
|
||||||
ErrorCode::InternalError
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Failed to check data layout: {:#?}", e);
|
|
||||||
return Err(raise_error!(format!("{:#?}", e), ErrorCode::InternalError));
|
|
||||||
}
|
|
||||||
Ok(true) => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(error) = initialize().await {
|
|
||||||
eprintln!("{:?}", error);
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
let periodic_tasks = PeriodicTasks::setup();
|
|
||||||
let mut smtp_service: Option<SmtpServer> = None;
|
|
||||||
if SETTINGS.bichon_enable_smtp {
|
|
||||||
info!("SMTP service is enabled, starting...");
|
|
||||||
match start_smtp_server().await {
|
|
||||||
Ok(server) => {
|
|
||||||
info!("SMTP server listening on: {}", server.smtp_addr);
|
|
||||||
smtp_service = Some(server);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Failed to start SMTP server: {}", e);
|
|
||||||
return Err(raise_error!(format!("{:#?}", e), ErrorCode::InternalError));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
info!("SMTP service is disabled by configuration.");
|
|
||||||
}
|
|
||||||
|
|
||||||
start_http_server().await?;
|
|
||||||
periodic_tasks.shutdown().await;
|
|
||||||
|
|
||||||
if let Some(server) = smtp_service {
|
|
||||||
info!("Shutting down SMTP server...");
|
|
||||||
server.stop().await;
|
|
||||||
info!("SMTP server stopped.");
|
|
||||||
}
|
|
||||||
|
|
||||||
SYNC_TASKS.shutdown().await;
|
|
||||||
ENVELOPE_MANAGER.shutdown().await;
|
|
||||||
ATTACHMENT_MANAGER.shutdown().await;
|
|
||||||
BLOB_MANAGER.shutdown().await;
|
|
||||||
info!("Bichon server stopped.");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialize the system by validating settings and starting necessary tasks.
|
|
||||||
async fn initialize() -> BichonResult<()> {
|
|
||||||
SignalManager::initialize().await?;
|
|
||||||
DataDirManager::initialize().await?;
|
|
||||||
UserManager::initialize().await?;
|
|
||||||
BichonTls::initialize().await?;
|
|
||||||
BichonContext::initialize().await?;
|
|
||||||
LazyLock::force(&BLOB_MANAGER);
|
|
||||||
LazyLock::force(&ENVELOPE_MANAGER);
|
|
||||||
LazyLock::force(&ATTACHMENT_MANAGER);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod api_tests {
|
|
||||||
use super::rest::api::create_openapi_service;
|
|
||||||
use poem::test::TestClient;
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn openapi_spec_json_is_served() {
|
|
||||||
let api_service = create_openapi_service();
|
|
||||||
let spec_endpoint = api_service.spec_endpoint();
|
|
||||||
let cli = TestClient::new(spec_endpoint);
|
|
||||||
|
|
||||||
let resp = cli.get("/").send().await;
|
|
||||||
resp.assert_status_is_ok();
|
|
||||||
|
|
||||||
let body = resp.json().await;
|
|
||||||
let obj = body.value().object();
|
|
||||||
assert!(obj.get_opt("openapi").is_some(), "missing openapi version");
|
|
||||||
assert!(obj.get_opt("info").is_some(), "missing info section");
|
|
||||||
assert!(obj.get_opt("paths").is_some(), "missing paths section");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn openapi_spec_yaml_is_served() {
|
|
||||||
let api_service = create_openapi_service();
|
|
||||||
let spec_endpoint = api_service.spec_endpoint_yaml();
|
|
||||||
let cli = TestClient::new(spec_endpoint);
|
|
||||||
|
|
||||||
let resp = cli.get("/").send().await;
|
|
||||||
resp.assert_status_is_ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn swagger_ui_is_served() {
|
|
||||||
let api_service = create_openapi_service();
|
|
||||||
let swagger = api_service.swagger_ui();
|
|
||||||
let cli = TestClient::new(swagger);
|
|
||||||
|
|
||||||
let resp = cli.get("/").send().await;
|
|
||||||
resp.assert_status_is_ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn openapi_spec_lists_all_tag_groups() {
|
|
||||||
let api_service = create_openapi_service();
|
|
||||||
let spec_endpoint = api_service.spec_endpoint();
|
|
||||||
let cli = TestClient::new(spec_endpoint);
|
|
||||||
|
|
||||||
let resp = cli.get("/").send().await;
|
|
||||||
let body = resp.json().await;
|
|
||||||
let value = body.value();
|
|
||||||
|
|
||||||
let tag_names: Vec<&str> = value
|
|
||||||
.object()
|
|
||||||
.get("tags")
|
|
||||||
.array()
|
|
||||||
.iter()
|
|
||||||
.map(|v| v.object().get("name").string())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
tag_names.contains(&"AccessToken"),
|
|
||||||
"missing AccessToken tag"
|
|
||||||
);
|
|
||||||
assert!(tag_names.contains(&"Attachment"), "missing Attachment tag");
|
|
||||||
assert!(tag_names.contains(&"AutoConfig"), "missing AutoConfig tag");
|
|
||||||
assert!(tag_names.contains(&"Account"), "missing Account tag");
|
|
||||||
assert!(tag_names.contains(&"System"), "missing System tag");
|
|
||||||
assert!(tag_names.contains(&"Mailbox"), "missing Mailbox tag");
|
|
||||||
assert!(tag_names.contains(&"OAuth2"), "missing OAuth2 tag");
|
|
||||||
assert!(tag_names.contains(&"Message"), "missing Message tag");
|
|
||||||
assert!(tag_names.contains(&"Import"), "missing Import tag");
|
|
||||||
assert!(tag_names.contains(&"Users"), "missing Users tag");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,26 +19,25 @@
|
|||||||
use crate::common::error::ErrorCapture;
|
use crate::common::error::ErrorCapture;
|
||||||
use crate::common::log::Tracing;
|
use crate::common::log::Tracing;
|
||||||
use crate::common::tls::rustls_config;
|
use crate::common::tls::rustls_config;
|
||||||
|
use crate::common::timeout::{Timeout, TIMEOUT_HEADER};
|
||||||
use crate::error::handler::error_handler;
|
use crate::error::handler::error_handler;
|
||||||
use crate::rest::public::login::login;
|
use crate::rest::public::login::login;
|
||||||
use crate::rest::public::status::get_status;
|
use crate::rest::public::status::get_status;
|
||||||
use bichon_core::common::signal::SIGNAL_MANAGER;
|
use bichon_core::common::signal::SIGNAL_MANAGER;
|
||||||
use bichon_core::error::code::ErrorCode;
|
use bichon_core::error::code::ErrorCode;
|
||||||
use bichon_core::error::BichonResult;
|
use bichon_core::error::BichonResult;
|
||||||
|
use bichon_core::raise_error;
|
||||||
use bichon_core::settings::cli::SETTINGS;
|
use bichon_core::settings::cli::SETTINGS;
|
||||||
|
|
||||||
use super::error::ApiErrorResponse;
|
use super::error::ApiErrorResponse;
|
||||||
use crate::common::auth::ApiGuard;
|
use crate::common::auth::ApiGuard;
|
||||||
use crate::common::timeout::{Timeout, TIMEOUT_HEADER};
|
|
||||||
use api::create_openapi_service;
|
use api::create_openapi_service;
|
||||||
use assets::FrontEndAssets;
|
use assets::FrontEndAssets;
|
||||||
use bichon_core::raise_error;
|
|
||||||
use http::{HeaderValue, Method};
|
use http::{HeaderValue, Method};
|
||||||
use poem::endpoint::EmbeddedFilesEndpoint;
|
use poem::endpoint::EmbeddedFilesEndpoint;
|
||||||
use poem::listener::{Listener, TcpListener};
|
use poem::listener::{Listener, TcpListener};
|
||||||
use poem::middleware::{CatchPanic, Compression, SetHeader};
|
use poem::middleware::{CatchPanic, Compression, Cors, SetHeader};
|
||||||
use poem::{get, handler, post, IntoResponse};
|
use poem::{get, handler, post, Endpoint, EndpointExt, IntoResponse, Route, Server};
|
||||||
use poem::{middleware::Cors, EndpointExt, Route, Server};
|
|
||||||
use public::oauth2::oauth2_callback;
|
use public::oauth2::oauth2_callback;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -49,18 +48,9 @@ pub mod public;
|
|||||||
|
|
||||||
pub type ApiResult<T, E = ApiErrorResponse> = std::result::Result<T, E>;
|
pub type ApiResult<T, E = ApiErrorResponse> = std::result::Result<T, E>;
|
||||||
|
|
||||||
pub async fn start_http_server() -> BichonResult<()> {
|
/// Build the community route tree. Pro/Enterprise servers can call this
|
||||||
let listener = TcpListener::bind((
|
/// and then add their own routes before passing the tree to the server.
|
||||||
SETTINGS.bichon_bind_ip.clone().unwrap_or("0.0.0.0".into()),
|
pub fn build_routes() -> impl Endpoint {
|
||||||
SETTINGS.bichon_http_port as u16,
|
|
||||||
));
|
|
||||||
|
|
||||||
let listener = if SETTINGS.bichon_enable_rest_https {
|
|
||||||
listener.rustls(rustls_config()?).boxed()
|
|
||||||
} else {
|
|
||||||
listener.boxed()
|
|
||||||
};
|
|
||||||
|
|
||||||
let api_service = create_openapi_service()
|
let api_service = create_openapi_service()
|
||||||
.summary("A lightweight, high-performance Rust email archiver with WebUI");
|
.summary("A lightweight, high-performance Rust email archiver with WebUI");
|
||||||
|
|
||||||
@@ -79,7 +69,6 @@ pub async fn start_http_server() -> BichonResult<()> {
|
|||||||
.with(Tracing);
|
.with(Tracing);
|
||||||
|
|
||||||
let cors_origins: Option<HashSet<String>> = SETTINGS.bichon_cors_origins.clone();
|
let cors_origins: Option<HashSet<String>> = SETTINGS.bichon_cors_origins.clone();
|
||||||
|
|
||||||
let cors_origins: Vec<String> = cors_origins.unwrap_or_default().into_iter().collect();
|
let cors_origins: Vec<String> = cors_origins.unwrap_or_default().into_iter().collect();
|
||||||
|
|
||||||
let cors = Cors::new()
|
let cors = Cors::new()
|
||||||
@@ -92,7 +81,6 @@ pub async fn start_http_server() -> BichonResult<()> {
|
|||||||
}
|
}
|
||||||
cors_origins.iter().any(|o| o == origin)
|
cors_origins.iter().any(|o| o == origin)
|
||||||
})
|
})
|
||||||
//.allow_origins(cors_origins)
|
|
||||||
.allow_credentials(true)
|
.allow_credentials(true)
|
||||||
.allow_methods(&[
|
.allow_methods(&[
|
||||||
Method::GET,
|
Method::GET,
|
||||||
@@ -131,11 +119,26 @@ pub async fn start_http_server() -> BichonResult<()> {
|
|||||||
)
|
)
|
||||||
.at("/*", serve_index_with_base);
|
.at("/*", serve_index_with_base);
|
||||||
|
|
||||||
let route = Route::new()
|
Route::new()
|
||||||
.nest(&SETTINGS.bichon_base_url, app_logic)
|
.nest(&SETTINGS.bichon_base_url, app_logic)
|
||||||
.with(cors)
|
.with(cors)
|
||||||
.with_if(SETTINGS.bichon_http_compression_enabled, Compression::new())
|
.with_if(SETTINGS.bichon_http_compression_enabled, Compression::new())
|
||||||
.with(CatchPanic::new());
|
.with(CatchPanic::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_http_server() -> BichonResult<()> {
|
||||||
|
let listener = TcpListener::bind((
|
||||||
|
SETTINGS.bichon_bind_ip.clone().unwrap_or("0.0.0.0".into()),
|
||||||
|
SETTINGS.bichon_http_port as u16,
|
||||||
|
));
|
||||||
|
|
||||||
|
let listener = if SETTINGS.bichon_enable_rest_https {
|
||||||
|
listener.rustls(rustls_config()?).boxed()
|
||||||
|
} else {
|
||||||
|
listener.boxed()
|
||||||
|
};
|
||||||
|
|
||||||
|
let route = build_routes();
|
||||||
|
|
||||||
let mut rx = SIGNAL_MANAGER.subscribe();
|
let mut rx = SIGNAL_MANAGER.subscribe();
|
||||||
let shutdown_fut = async move {
|
let shutdown_fut = async move {
|
||||||
|
|||||||
Reference in New Issue
Block a user