Skip to main content

docspec_http/
lib.rs

1#![forbid(unsafe_code)]
2//! HTTP API server for `DocSpec` document conversion.
3
4extern crate alloc;
5
6pub mod cache;
7pub mod cli;
8pub mod error;
9pub mod format;
10pub mod handlers;
11pub mod metrics;
12pub mod mime_parser;
13pub mod router;
14pub mod server;
15pub mod telemetry;
16pub mod tracing_init;
17
18pub use cli::Args;
19pub use server::{serve, ServerError};
20
21/// Initialize Sentry (if DSN env var set) and return a guard that flushes Sentry on drop.
22/// MUST be called BEFORE building the tokio runtime; `main()` MUST hold the returned guard for the entire process lifetime.
23#[must_use]
24#[inline]
25pub fn init_telemetry() -> telemetry::TelemetryGuard {
26    telemetry::init()
27}
28
29/// Initialize the global tracing subscriber. Called internally by [`run_server`].
30///
31/// Idempotent: if a global subscriber is already installed, this is a no-op so library
32/// consumers can safely call [`run_server`] more than once per process.
33#[inline]
34pub fn init_tracing() {
35    // Discard the "already initialized" error — the global subscriber is a process-wide
36    // singleton, so subsequent calls are correctly handled as no-ops.
37    drop(tracing_init::try_init());
38}
39
40/// Synchronous server entrypoint. Builds a multi-threaded tokio runtime, installs the
41/// global tracing subscriber, and runs the HTTP server until SIGINT/SIGTERM.
42///
43/// # Lifetime requirement
44///
45/// The caller MUST call [`init_telemetry`] BEFORE this function and hold the returned
46/// `TelemetryGuard` for the entire process lifetime.
47///
48/// # Errors
49///
50/// Returns [`ServerError`] if runtime construction fails or the HTTP server fails.
51#[inline]
52pub fn run_server(args: cli::Args) -> Result<(), ServerError> {
53    let config = args.into_config();
54    let runtime = tokio::runtime::Builder::new_multi_thread()
55        .enable_all()
56        .build()
57        .map_err(ServerError::RuntimeBuild)?;
58
59    runtime.block_on(async {
60        init_tracing();
61        serve(config).await
62    })
63}