oak-nginx

Crates.iooak-nginx
lib.rsoak-nginx
version0.0.1
created_at2025-10-21 04:39:15.06617+00
updated_at2026-01-23 04:42:09.2784+00
descriptionNginx web server configuration language parser with support for web server configuration and routing processing.
homepagehttps://github.com/ygg-lang/oaks
repositoryhttps://github.com/ygg-lang/oaks
max_upload_size
id1893271
size118,115
publisher (github:ygg-lang:publisher)

documentation

https://docs.rs/oak-nginx

README

Oak Nginx Parser

Crates.io Documentation License

A comprehensive Nginx configuration parser for the Oak parsing framework, providing robust parsing capabilities for Nginx server blocks, directives, and configuration syntax.

Features

  • Complete Nginx Syntax: Parse server blocks, location blocks, upstream blocks, and all standard directives
  • Directive Support: Handle all Nginx directives including core, HTTP, server, and location contexts
  • Nested Blocks: Support for complex nested configuration structures
  • Variable Parsing: Parse Nginx variables with proper interpolation support
  • Comments: Preserve and parse inline and block comments
  • Include Files: Support for include directives and file references
  • Error Handling: Detailed error messages with line and column information
  • AST Generation: Rich Abstract Syntax Tree for configuration analysis and manipulation
  • Zero Dependencies: Pure Rust implementation with no external dependencies

Installation

Add this to your Cargo.toml:

[dependencies]
oak-nginx = "0.1.0"

Quick Start

use oak::Parser;
use oak_nginx::NginxLanguage;

fn main() {
    let config = r#"
        server {
            listen 80;
            server_name example.com www.example.com;
            
            location / {
                proxy_pass http://localhost:8080;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
            }
            
            location /static {
                root /var/www/html;
                expires 1d;
            }
            
            error_page 404 /404.html;
            error_page 500 502 503 504 /50x.html;
        }
    "#;
    
    let mut parser = Parser::new();
    let language = NginxLanguage::new();
    
    match parser.parse(&config, &language) {
        Ok(ast) => {
            println!("Successfully parsed Nginx configuration!");
            println!("AST: {:#?}", ast);
        }
        Err(error) => {
            eprintln!("Parse error: {}", error);
        }
    }
}

Advanced Usage

Parsing Complex Configurations

use oak::Parser;
use oak_nginx::NginxLanguage;

fn main() {
    let complex_config = r#"
        user nginx;
        worker_processes auto;
        error_log /var/log/nginx/error.log;
        pid /run/nginx.pid;
        
        events {
            worker_connections 1024;
            use epoll;
            multi_accept on;
        }
        
        http {
            include /etc/nginx/mime.types;
            default_type application/octet-stream;
            
            log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                           '$status $body_bytes_sent "$http_referer" '
                           '"$http_user_agent" "$http_x_forwarded_for"';
            
            access_log /var/log/nginx/access.log main;
            
            sendfile on;
            tcp_nopush on;
            tcp_nodelay on;
            keepalive_timeout 65;
            types_hash_max_size 2048;
            
            gzip on;
            gzip_vary on;
            gzip_min_length 1000;
            gzip_types text/plain text/css application/json application/javascript;
            
            upstream backend {
                server 127.0.0.1:8080 weight=3;
                server 127.0.0.1:8081 weight=2;
                server 127.0.0.1:8082 weight=1;
                keepalive 32;
            }
            
            server {
                listen 80;
                server_name api.example.com;
                
                location / {
                    proxy_pass http://backend;
                    proxy_http_version 1.1;
                    proxy_set_header Connection "";
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto $scheme;
                }
                
                location /health {
                    access_log off;
                    return 200 "healthy\n";
                    add_header Content-Type text/plain;
                }
            }
        }
    "#;
    
    let mut parser = Parser::new();
    let language = NginxLanguage::new();
    
    match parser.parse(&complex_config, &language) {
        Ok(ast) => {
            println!("Successfully parsed complex Nginx configuration!");
            // Process the AST for configuration validation or transformation
        }
        Err(error) => {
            eprintln!("Parse error at line {}: {}", error.line(), error.message());
        }
    }
}

Error Handling with Context

use oak::Parser;
use oak_nginx::NginxLanguage;

fn parse_with_diagnostics(source: &str) {
    let mut parser = Parser::new();
    let language = NginxLanguage::new();
    
    match parser.parse(source, &language) {
        Ok(ast) => {
            println!("Parsed successfully!");
        }
        Err(error) => {
            eprintln!("Parse error at line {}, column {}", error.line(), error.column());
            eprintln!("Error: {}", error.message());
            
            // Show context around the error
            let lines: Vec<&str> = source.lines().collect();
            if error.line() > 0 && error.line() <= lines.len() {
                eprintln!("Context:");
                eprintln!("  {}", lines[error.line() - 1]);
                eprintln!("  {}^", " ".repeat(error.column()));
            }
        }
    }
}

Configuration Validation

use oak::Parser;
use oak_nginx::NginxLanguage;

fn validate_nginx_config(config_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    let config = std::fs::read_to_string(config_path)?;
    
    let mut parser = Parser::new();
    let language = NginxLanguage::new();
    
    match parser.parse(&config, &language) {
        Ok(ast) => {
            println!("Configuration kind is valid!");
            
            // You can now analyze the AST for semantic issues
            check_semantic_errors(&ast)?;
            
            Ok(())
        }
        Err(error) => {
            Err(format!("Syntax error at line {}: {}", error.line(), error.message()).into())
        }
    }
}

AST Structure

The parser generates a comprehensive AST with the following main node types:

  • Configuration: Top-level container for all Nginx configuration
  • Directive: Individual configuration directives with parameters
  • Block: Nested configuration blocks (server, location, upstream, etc.)
  • Context: Configuration contexts (events, http, server, location)
  • Parameter: Directive parameters including variables and literals
  • Variable: Nginx variables with $ prefix
  • Comment: Inline and block comments
  • Include: Include file references

Block Types

  • Main Context: Global directives
  • Events Block: Connection handling configuration
  • HTTP Block: HTTP server configuration
  • Server Block: Virtual server configuration
  • Location Block: URL location configuration
  • Upstream Block: Load balancing configuration
  • Mail Block: Mail proxy configuration

Performance

  • Zero-copy parsing: Minimal string allocations during parsing
  • Streaming support: Parse large configuration files incrementally
  • Error recovery: Continue parsing after encountering errors
  • Memory efficient: Compact AST representation
  • Fast validation: Quick syntax validation for large configs

Integration

The parser integrates seamlessly with the broader Oak ecosystem:

use oak::Parser;
use oak_nginx::NginxLanguage;

// Use with other Oak tools for analysis and transformation
fn analyze_nginx_config(source: &str) -> Result<Analysis, ParseError> {
    let mut parser = Parser::new();
    let language = NginxLanguage::new();
    let ast = parser.parse(source, &language)?;
    
    // Perform semantic analysis, validation, or transformations
    perform_analysis(ast)
}

// Convert to other formats
fn convert_to_json(source: &str) -> Result<String, ParseError> {
    let mut parser = Parser::new();
    let language = NginxLanguage::new();
    let ast = parser.parse(source, &language)?;
    
    serde_json::to_string_pretty(&ast).map_err(|e| e.into())
}

Use Cases

  • Configuration Validation: Validate Nginx configuration syntax before deployment
  • Configuration Analysis: Analyze server configurations for security and performance issues
  • Migration Tools: Convert configurations between different formats or versions
  • IDE Support: Provide syntax highlighting and error checking for Nginx configs
  • Automation: Generate or modify configurations programmatically
  • Monitoring: Parse and analyze configuration changes

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Commit count: 80

cargo fmt