php-crossplane - Reliable and fast NGINX configuration file parser and builder

Overview

crossplane

php-crossplane

Reliable and fast NGINX configuration file parser and builder

ℹ️ This is a PHP port of the Nginx Python crossplane package which can be found here.

Packagist Version Packagist PHP Version Support Build Status License

Install

Install in project

composer require nelexa/crossplane

Global install

composer require --global nelexa/crossplane

Use in PHP

$crossplane = new \Nelexa\NginxParser\Crossplane();

$lexer = $crossplane->lexer(); // gets \Nelexa\NginxParser\Lexer instance
$builder = $crossplane->builder(); // gets \Nelexa\NginxParser\Builder instance
$parser = $crossplane->parser(); // gets \Nelexa\NginxParser\Parser instance
$analyzer = $crossplane->analyzer(); // gets \Nelexa\NginxParser\Analyzer instance
$formatter = $crossplane->formatter(); // gets \Nelexa\NginxParser\Formatter instance

Parse config

$nginxConfigFile = '/etc/nginx/nginx.conf';
$crossplane = new \Nelexa\NginxParser\Crossplane();
$payload = $crossplane->parser()->parse($nginxConfigFile, $parseOptions = [
    \Nelexa\NginxParser\Parser::OPTION_COMMENTS => true,
    \Nelexa\NginxParser\Parser::OPTION_COMBINE => true,
    // etc...
]);

This will return the same payload as described in the crossplane parse section.

Build config from payload

$crossplane = new \Nelexa\NginxParser\Crossplane();
$config = $crossplane->builder()->build(
    [[
        'directive' => 'events',
        'args' => [],
        'block' => [[
            'directive' => 'worker_connections',
            'args' => ['1024'],
        ]],
    ]]
);

This will return a single string that contains an entire NGINX config file.

events {
    worker_connections 1024;
}

Lex config

$crossplane = new \Nelexa\NginxParser\Crossplane();
$tokensIterator = $crossplane->lexer()->lex('/etc/nginx/nginx.conf');
$tokensArray = iterator_to_array($tokensIterator);

$crossplane->lexer()->lex() generates 3-tuples.

[
    [
        'user', // token
        1,      // line
        false,  // quote
    ],
    [
        'www-data',
        1,
        false,
    ],
    [
        ';',
        1,
        false,
    ],
    [
        'worker_processes',
        2,
        false,
    ],
    [
        'auto',
        2,
        false,
    ],
    [
        ';',
        2,
        false,
    ],
    [
        'pid',
        3,
        false,
    ],
    [
        '/run/nginx.pid',
        3,
        false,
    ],
    [
        ';',
        3,
        false,
    ],
    // etc
]

Register custom Lexer / Builder directives

$crossplane->registerExtension(new class() implements \Nelexa\NginxParser\Ext\CrossplaneExtension {
public function registerExtension(\Nelexa\NginxParser\Crossplane $crossplane): void
{
$crossplane->lexer()->registerExternalLexer(/* args */);
$crossplane->builder()->registerExternalBuilder(/* args */);
}

    public function lex(\Iterator $charIterator, string $directive): ?\Generator
    {
    }

    public function build(array $stmt, string $padding, int $indent = 4, bool $tabs = false): string
    {
    }
});

Command Line Interface

To invoke commands in the command line interface, use vendor/bin/crossplane if you have installed the package locally in the project, and crossplane if you have installed the package globally.

Usage:
  vendor/bin/crossplane command [options] [arguments]

Options:
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  build   builds an nginx config from a json payload
  format  formats an nginx config file
  help    Display help for a command
  lex     lexes tokens from an nginx config file
  minify  removes all whitespace from an nginx config
  parse   parses a json payload for an nginx config

crossplane parse

This command will take a path to a main NGINX config file as input, then parse the entire config into the schema defined below, and dumps the entire thing as a JSON payload.

Description:
  parses a json payload for an nginx config

Usage:
  vendor/bin/crossplane parse [options] [--] 

Arguments:
  filename                the nginx config file

Options:
  -o, --out[=OUT]         write output to a file
  -i, --indent[=INDENT]   number of spaces to indent output [default: 0]
      --ignore[=IGNORE]   ignore directives (comma-separated) (multiple values allowed)
      --no-catch          only collect first error in file
      --tb-onerror        include tracebacks in config errors
      --combine           use includes to create one single file
      --single-file       do not include other config files
      --include-comments  include comments in json
      --strict            raise errors for unknown directives
  -h, --help              Display this help message
  -q, --quiet             Do not output any message
  -V, --version           Display this application version
      --ansi              Force ANSI output
      --no-ansi           Disable ANSI output
  -n, --no-interaction    Do not ask any interactive question
  -v|vv|vvv, --verbose    Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Privacy and Security

Since crossplane is usually used to create payloads that are sent to different servers, it's important to keep security in mind. For that reason, the --ignore option was added. It can be used to keep certain sensitive directives out of the payload output entirely.

For example, we always use the equivalent of this flag in the NGINX Amplify Agent out of respect for our users' privacy:

--ignore=auth_basic_user_file,secure_link_secret,ssl_certificate_key,ssl_client_certificate,ssl_password_file,ssl_stapling_file,ssl_trusted_certificate

Schema

Response Object

{
    "status": String, // "ok" or "failed" if "errors" is not empty
    "errors": Array,  // aggregation of "errors" from Config objects
    "config": Array   // Array of Config objects
}

Config Object

{
    "file": String,   // the full path of the config file
    "status": String, // "ok" or "failed" if errors is not empty array
    "errors": Array,  // Array of Error objects
    "parsed": Array   // Array of Directive objects
}

Directive Object

{
    "directive": String, // the name of the directive
    "line": Number,      // integer line number the directive started on
    "args": Array,       // Array of String arguments
    "includes": Array,   // Array of integers (included iff this is an include directive)
    "block": Array       // Array of Directive Objects (included iff this is a block)
}

Note

If this is an include directive and the --single-file flag was not used, an "includes" value will be used that holds an Array of indices of the configs that are included by this directive.

If this is a block directive, a "block" value will be used that holds an Array of more Directive Objects that define the block context.

Error Object

{
    "file": String,     // the full path of the config file
    "line": Number,     // integer line number the directive that caused the error
    "error": String,    // the error message
    "callback": Object  // only included iff an "onerror" function was passed to parse()
}

Note

If the --tb-onerror flag was used by crossplane parse, "callback" will contain a string that represents the traceback that the error caused.

Example

The main NGINX config file is at /etc/nginx/nginx.conf:

events {
    worker_connections 1024;
}

http {
    include conf.d/*.conf;
}

And this config file is at /etc/nginx/conf.d/servers.conf:

server {
    listen 8080;
    location / {
        try_files 'foo bar' baz;
    }
}

server {
    listen 8081;
    location / {
        return 200 'success!';
    }
}

So then if you run this:

vendor/bin/crossplane parse --indent=4 /etc/nginx/nginx.conf

The prettified JSON output would look like this:

{
    "status": "ok",
    "errors": [],
    "config": [
        {
            "file": "/etc/nginx/nginx.conf",
            "status": "ok",
            "errors": [],
            "parsed": [
                {
                    "directive": "events",
                    "line": 1,
                    "args": [],
                    "block": [
                        {
                            "directive": "worker_connections",
                            "line": 2,
                            "args": [
                                "1024"
                            ]
                        }
                    ]
                },
                {
                    "directive": "http",
                    "line": 5,
                    "args": [],
                    "block": [
                        {
                            "directive": "include",
                            "line": 6,
                            "args": [
                                "conf.d/*.conf"
                            ],
                            "includes": [
                                1
                            ]
                        }
                    ]
                }
            ]
        },
        {
            "file": "/etc/nginx/conf.d/servers.conf",
            "status": "ok",
            "errors": [],
            "parsed": [
                {
                    "directive": "server",
                    "line": 1,
                    "args": [],
                    "block": [
                        {
                            "directive": "listen",
                            "line": 2,
                            "args": [
                                "8080"
                            ]
                        },
                        {
                            "directive": "location",
                            "line": 3,
                            "args": [
                                "/"
                            ],
                            "block": [
                                {
                                    "directive": "try_files",
                                    "line": 4,
                                    "args": [
                                        "foo bar",
                                        "baz"
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    "directive": "server",
                    "line": 8,
                    "args": [],
                    "block": [
                        {
                            "directive": "listen",
                            "line": 9,
                            "args": [
                                "8081"
                            ]
                        },
                        {
                            "directive": "location",
                            "line": 10,
                            "args": [
                                "/"
                            ],
                            "block": [
                                {
                                    "directive": "return",
                                    "line": 11,
                                    "args": [
                                        "200",
                                        "success!"
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

crossplane parse (advanced)

This tool uses two flags that can change how crossplane handles errors.

The first, --no-catch, can be used if you'd prefer that crossplane quit parsing after the first error it finds.

The second, --tb-onerror, will add a "callback" key to all error objects in the JSON output, each containing a string representation of the traceback that would have been raised by the parser if the exception had not been caught. This can be useful for logging purposes.

crossplane build

This command will take a path to a file as input. The file should contain a JSON representation of an NGINX config that has the structure defined above. Saving and using the output from crossplane parse to rebuild your config files should not cause any differences in content except for the formatting.

Description:
  builds an nginx config from a json payload

Usage:
  vendor/bin/crossplane build [options] [--] 

Arguments:
  filename               the file with the config payload

Options:
  -d, --dir[=DIR]        the base directory to build in [default: $PWD]
  -f, --force            overwrite existing files
  -i, --indent[=INDENT]  number of spaces to indent output [default: 4]
  -t, --tabs             indent with tabs instead of spaces
      --no-headers       do not write header to configs
      --stdout           write configs to stdout instead
  -h, --help             Display this help message
  -q, --quiet            Do not output any message
  -V, --version          Display this application version
      --ansi             Force ANSI output
      --no-ansi          Disable ANSI output
  -n, --no-interaction   Do not ask any interactive question
  -v|vv|vvv, --verbose   Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

crossplane lex

This command takes an NGINX config file, splits it into tokens by removing whitespace and comments, and dumps the list of tokens as a JSON array.

Description:
  lexes tokens from an nginx config file

Usage:
  vendor/bin/crossplane lex [options] [--] 

Arguments:
  filename               the nginx config file

Options:
  -o, --out[=OUT]        write output to a file
  -i, --indent[=INDENT]  number of spaces to indent output [default: 0]
  -l, --line-numbers     include line numbers in json payload
  -h, --help             Display this help message
  -q, --quiet            Do not output any message
  -V, --version          Display this application version
      --ansi             Force ANSI output
      --no-ansi          Disable ANSI output
  -n, --no-interaction   Do not ask any interactive question
  -v|vv|vvv, --verbose   Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Example

Passing in this NGINX config file at /etc/nginx/nginx.conf:

events {
    worker_connections 1024;
}

http {
    include conf.d/*.conf;
}

By running:

vendor/bin/crossplane lex /etc/nginx/nginx.conf

Will result in this JSON output:

["events","{","worker_connections","1024",";","}","http","{","include","conf.d/*.conf",";","}"]

However, if you decide to use the --line-numbers flag, your output will look like:

[["events",1],["{",1],["worker_connections",2],["1024",2],[";",2],["}",3],["http",5],["{",5],["include",6],["conf.d/*.conf",6],[";",6],["}",7]]

crossplane format

This is a quick and dirty tool that uses crossplane parse internally to format an NGINX config file. It serves the purpose of demonstrating what you can do with crossplane's parsing abilities. It is not meant to be a fully fleshed out, feature-rich formatting tool. If that is what you are looking for, then you may want to look writing your own using crossplane's PHP API.

Description:
  formats an nginx config file

Usage:
  vendor/bin/crossplane format [options] [--] 

Arguments:
  filename               the nginx config file

Options:
  -o, --out[=OUT]        write output to a file
  -i, --indent[=INDENT]  number of spaces to indent output [default: 4]
  -t, --tabs             indent with tabs instead of spaces
  -h, --help             Display this help message
  -q, --quiet            Do not output any message
  -V, --version          Display this application version
      --ansi             Force ANSI output
      --no-ansi          Disable ANSI output
  -n, --no-interaction   Do not ask any interactive question
  -v|vv|vvv, --verbose   Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

crossplane minify

This is a simple and fun little tool that uses crossplane lex internally to remove as much whitespace from an NGINX config file as possible without affecting what it does. It can't imagine it will have much of a use to most people, but it demonstrates the kinds of things you can do with crossplane's lexing abilities.

Description:
  removes all whitespace from an nginx config

Usage:
  vendor/bin/crossplane minify [options] [--] 

Arguments:
  filename              the nginx config file

Options:
  -o, --out[=OUT]       write output to a file
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
You might also like...
ColorJizz is a PHP library for manipulating and converting colors.

#Getting started: ColorJizz-PHP uses the PSR-0 standards for namespaces, so there should be no trouble using with frameworks like Symfony 2. ###Autolo

:clamp: HtmlMin: HTML Compressor and Minifier via PHP

🗜️ HtmlMin: HTML Compressor and Minifier for PHP Description HtmlMin is a fast and very easy to use PHP library that minifies given HTML5 source by r

A lightweight php class for formatting sql statements. Handles automatic indentation and syntax highlighting.

SqlFormatter A lightweight php class for formatting sql statements. It can automatically indent and add line breaks in addition to syntax highlighting

Tutorial for computer vision and machine learning in PHP 7/8 by opencv (installation + examples + documentation)
Tutorial for computer vision and machine learning in PHP 7/8 by opencv (installation + examples + documentation)

Examples detect face by cascade classifier detect face by pretrained caffe model res10_300x300_ssd by ddn module detect facemarks by LBF algorithm rec

Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets). It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.
Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets). It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.

Motto: "Every business should have a detection script to detect mobile readers." About Mobile Detect is a lightweight PHP class for detecting mobile d

A PHP library for generating universally unique identifiers (UUIDs).

ramsey/uuid A PHP library for generating and working with UUIDs. ramsey/uuid is a PHP library for generating and working with universally unique ident

A PHP string manipulation library with multibyte support

A PHP string manipulation library with multibyte support. Compatible with PHP 5.4+, PHP 7+, and HHVM. s('string')-toTitleCase()-ensureRight('y') ==

A sane interface for php's built in preg_* functions
A sane interface for php's built in preg_* functions

Making regex great again Php's built in preg_* functions require some odd patterns like passing variables by reference and treating false or null valu

🉑 Portable UTF-8 library - performance optimized (unicode) string functions for php.

🉑 Portable UTF-8 Description It is written in PHP (PHP 7+) and can work without "mbstring", "iconv" or any other extra encoding php-extension on your

Comments
Releases(1.0.3)
Owner
null
A PHP parser for TOML

TOML parser for PHP A PHP parser for TOML compatible with TOML v0.4.0. Support: Installation Requires PHP >= 7.1. Use Composer to install this package

Yo! Symfony 175 Dec 26, 2022
A fast PHP slug generator and transliteration library that converts non-ascii characters for use in URLs.

URLify for PHP A fast PHP slug generator and transliteration library, started as a PHP port of URLify.js from the Django project. Handles symbols from

Aband*nthecar 667 Dec 20, 2022
A tiny PHP class-based program to analyze an input file and extract all of that words and detect how many times every word is repeated

A tiny PHP class-based program to analyze an input file and extract all of that words and detect how many times every word is repeated

Max Base 4 Feb 22, 2022
A PHP string manipulation library with multibyte support. Compatible with PHP 5.4+, PHP 7+, and HHVM.

A PHP string manipulation library with multibyte support. Compatible with PHP 5.4+, PHP 7+, and HHVM. s('string')->toTitleCase()->ensureRight('y') ==

Daniel St. Jules 2.5k Dec 28, 2022
"結巴"中文分詞:做最好的 PHP 中文分詞、中文斷詞組件。 / "Jieba" (Chinese for "to stutter") Chinese text segmentation: built to be the best PHP Chinese word segmentation module.

jieba-php "結巴"中文分詞:做最好的 PHP 中文分詞、中文斷詞組件,目前翻譯版本為 jieba-0.33 版本,未來再慢慢往上升級,效能也需要再改善,請有興趣的開發者一起加入開發!若想使用 Python 版本請前往 fxsjy/jieba 現在已經可以支援繁體中文!只要將字典切換為 bi

Fukuball Lin 1.2k Dec 31, 2022
highlight.php is a server-side syntax highlighter written in PHP that currently supports 185 languages

highlight.php is a server-side syntax highlighter written in PHP that currently supports 185 languages. It's a port of highlight.js by Ivan Sagalaev that makes full use of the language and style definitions of the original JavaScript project.

Geert Bergman 633 Dec 27, 2022
Extensive, portable and performant handling of UTF-8 and grapheme clusters for PHP

Patchwork UTF-8 for PHP Patchwork UTF-8 gives PHP developpers extensive, portable and performant handling of UTF-8 and grapheme clusters. It provides

Nicolas Grekas 80 Sep 28, 2022
PHP library to detect and manipulate indentation of strings and files

indentation PHP library to detect and manipulate the indentation of files and strings Installation composer require --dev colinodell/indentation Usage

Colin O'Dell 34 Nov 28, 2022
A PHP class which allows the decoding and encoding of a wider variety of characters compared to the standard htmlentities and html_entity_decode functions.

The ability to encode and decode a certain set of characters called 'Html Entities' has existed since PHP4. Amongst the vast number of functions built into PHP, there are 4 nearly identical functions that are used to encode and decode html entities; despite their similarities, however, 2 of them do provide additional capabilities not available to the others.

Gavin G Gordon (Markowski) 2 Nov 12, 2022
A lightweight php class for formatting sql statements. Handles automatic indentation and syntax highlighting.

SqlFormatter A lightweight php class for formatting sql statements. It can automatically indent and add line breaks in addition to syntax highlighting

Jeremy Dorn 3.9k Jan 1, 2023