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// High-level API
137mod discovery;
138pub use discovery::NginxDiscovery;
139
140// Re-exports for convenience
141pub use error::{Error, Result};
142pub use parser::parse;
143
144/// Commonly used imports for quick setup
145///
146/// ```rust
147/// use nginx_discovery::prelude::*;
148/// ```
149pub mod prelude {
150    pub use crate::discovery::NginxDiscovery;
151    pub use crate::error::{Error, Result};
152    pub use crate::error_builder::ErrorBuilder;
153    pub use crate::parser::{Lexer, Parser, Token, TokenKind};
154    pub use crate::types::*;
155}
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_basic_parse() {
163        let config = r"
164            user nginx;
165            worker_processes auto;
166        ";
167
168        let result = parse(config);
169        assert!(result.is_ok());
170
171        let config = result.unwrap();
172        assert_eq!(config.directives.len(), 2);
173        assert_eq!(config.directives[0].name(), "user");
174        assert_eq!(config.directives[1].name(), "worker_processes");
175    }
176
177    #[test]
178    fn test_discovery_from_text() {
179        let config = "user nginx;";
180        let discovery = NginxDiscovery::from_config_text(config);
181        assert!(discovery.is_ok());
182    }
183
184    #[test]
185    fn test_prelude_imports() {
186        use crate::prelude::*;
187
188        let config = "user nginx;";
189        let discovery = NginxDiscovery::from_config_text(config).unwrap();
190        assert_eq!(discovery.config().directives.len(), 1);
191    }
192}