Skip to main content

nginx_discovery/
lib.rs

1//! # nginx-discovery
2//!
3//! Discover and introspect NGINX configurations with ease.
4//!
5//! This crate provides three levels of API for working with NGINX configurations:
6//!
7//! 1. **High-level Discovery API**: Simple methods for common use cases
8//! 2. **Mid-level Extractors**: Type-safe directive extraction
9//! 3. **Low-level Parser**: Direct AST access for custom processing
10//!
11//! ## Quick Start
12//!
13//! ```
14//! use nginx_discovery::prelude::*;
15//!
16//! # fn main() -> nginx_discovery::Result<()> {
17//! // Parse configuration text
18//! let config = r"
19//!     http {
20//!         access_log /var/log/nginx/access.log;
21//!     }
22//! ";
23//!
24//! let discovery = NginxDiscovery::from_config_text(config)?;
25//!
26//! // Get access logs
27//! for log in discovery.access_logs() {
28//!     println!("Log: {}", log.path.display());
29//! }
30//!
31//! // Get all server names
32//! for name in discovery.server_names() {
33//!     println!("Server: {}", name);
34//! }
35//! # Ok(())
36//! # }
37//! ```
38//!
39//! ## Feature Flags
40//!
41//! - `system` (default): System interaction (detect nginx, run nginx -T)
42//! - `serde`: JSON/YAML serialization support
43//! - `visitor`: Visitor pattern for AST traversal
44//! - `includes`: Include directive resolution
45//! - `cli`: Command-line interface (binary only)
46//!
47//! ## Examples
48//!
49//! ### Extract Log Files
50//!
51//! ```
52//! use nginx_discovery::prelude::*;
53//!
54//! # fn main() -> nginx_discovery::Result<()> {
55//! let config = r"
56//!     access_log /var/log/nginx/access.log combined;
57//!     log_format combined '$remote_addr $request';
58//! ";
59//!
60//! let discovery = NginxDiscovery::from_config_text(config)?;
61//! let logs = discovery.access_logs();
62//!
63//! for log in logs {
64//!     println!("Path: {}", log.path.display());
65//!     if let Some(format_name) = &log.format_name {
66//!         println!("Format: {}", format_name);
67//!     }
68//! }
69//! # Ok(())
70//! # }
71//! ```
72//!
73//! ### Parse from File
74//!
75//! ```no_run
76//! use nginx_discovery::prelude::*;
77//!
78//! # fn main() -> nginx_discovery::Result<()> {
79//! let discovery = NginxDiscovery::from_config_file("/etc/nginx/nginx.conf")?;
80//! let logs = discovery.access_logs();
81//! println!("Found {} access logs", logs.len());
82//! # Ok(())
83//! # }
84//! ```
85//!
86//! ### Mid-level API
87//!
88//! ```
89//! use nginx_discovery::{parse, extract};
90//!
91//! # fn main() -> nginx_discovery::Result<()> {
92//! let config_text = "access_log /var/log/nginx/access.log;";
93//! let config = parse(config_text)?;
94//!
95//! let logs = extract::access_logs(&config)?;
96//! assert_eq!(logs.len(), 1);
97//! # Ok(())
98//! # }
99//! ```
100//!
101//! ### Low-level Parser
102//!
103//! ```
104//! use nginx_discovery::parse;
105//!
106//! # fn main() -> nginx_discovery::Result<()> {
107//! let config = parse("user nginx;")?;
108//! assert_eq!(config.directives.len(), 1);
109//! assert_eq!(config.directives[0].name(), "user");
110//! # Ok(())
111//! # }
112//! ```
113
114#![warn(missing_docs)]
115#![warn(clippy::all)]
116#![warn(clippy::pedantic)]
117#![cfg_attr(docsrs, feature(doc_cfg))]
118
119// Public modules
120pub mod ast;
121pub mod error;
122pub mod error_builder;
123pub mod extract;
124pub mod parser;
125
126#[cfg(feature = "system")]
127#[cfg_attr(docsrs, doc(cfg(feature = "system")))]
128pub mod system;
129
130pub mod types;
131
132#[cfg(feature = "visitor")]
133#[cfg_attr(docsrs, doc(cfg(feature = "visitor")))]
134pub mod visitor;
135
136#[cfg(feature = "serde")]
137pub mod export;
138
139#[cfg(feature = "network")]
140pub mod network;
141
142// High-level API
143mod discovery;
144pub use discovery::NginxDiscovery;
145
146// Re-exports for convenience
147pub use error::{Error, Result};
148pub use parser::parse;
149
150/// Commonly used imports for quick setup
151///
152/// ```rust
153/// use nginx_discovery::prelude::*;
154/// ```
155pub mod prelude {
156    pub use crate::discovery::NginxDiscovery;
157    pub use crate::error::{Error, Result};
158    pub use crate::error_builder::ErrorBuilder;
159    pub use crate::parser::{Lexer, Parser, Token, TokenKind};
160    pub use crate::types::*;
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn test_basic_parse() {
169        let config = r"
170            user nginx;
171            worker_processes auto;
172        ";
173
174        let result = parse(config);
175        assert!(result.is_ok());
176
177        let config = result.unwrap();
178        assert_eq!(config.directives.len(), 2);
179        assert_eq!(config.directives[0].name(), "user");
180        assert_eq!(config.directives[1].name(), "worker_processes");
181    }
182
183    #[test]
184    fn test_discovery_from_text() {
185        let config = "user nginx;";
186        let discovery = NginxDiscovery::from_config_text(config);
187        assert!(discovery.is_ok());
188    }
189
190    #[test]
191    fn test_prelude_imports() {
192        use crate::prelude::*;
193
194        let config = "user nginx;";
195        let discovery = NginxDiscovery::from_config_text(config).unwrap();
196        assert_eq!(discovery.config().directives.len(), 1);
197    }
198}