├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── cicd.yml │ └── release.yml ├── .gitignore ├── .golangci.yml ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CREDITS ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── analyze.go ├── analyze_appProtectWAFv4_directives.gen.go ├── analyze_appProtectWAFv5_directives.gen.go ├── analyze_geoip2_directives.gen.go ├── analyze_headersMore_directives.gen.go ├── analyze_lua_directives.gen.go ├── analyze_map.go ├── analyze_map_test.go ├── analyze_njs_directives.gen.go ├── analyze_nplus_R30_directives.go ├── analyze_nplus_R31_directives.go ├── analyze_nplus_R33_directives.gen.go ├── analyze_nplus_latest_directives.gen.go ├── analyze_oss_124_directives.gen.go ├── analyze_oss_126_directives.gen.go ├── analyze_oss_latest_directives.gen.go ├── analyze_otel_directives.gen.go ├── analyze_test.go ├── buffer.go ├── build.go ├── build_test.go ├── cmd └── generate │ ├── cmd_util.go │ ├── cmd_util_test.go │ └── main.go ├── errors.go ├── errors_test.go ├── go.mod ├── go.sum ├── internal └── generator │ ├── generator.go │ ├── generator_util.go │ ├── generator_util_test.go │ ├── testdata │ ├── expected │ │ ├── commentsInDefinition │ │ ├── filter │ │ ├── filterAndOverride │ │ ├── fullNgxBitmaskCover │ │ ├── normalDefinition │ │ ├── override │ │ ├── repeatDefine │ │ ├── single_file │ │ └── withMatchFuncComment │ └── source_codes │ │ ├── commentsInDefinition │ │ └── with_comments.c │ │ ├── filter │ │ └── filter.c │ │ ├── filterAndOverride │ │ └── filter_and_override.c │ │ ├── fullNgxBitmaskCover │ │ └── all_bitmask.c │ │ ├── noDirectives │ │ └── noDirectives.c │ │ ├── normalDefinition │ │ └── normal.c │ │ ├── override │ │ └── override.c │ │ ├── repeatDefine │ │ ├── definition1.c │ │ └── definition2.c │ │ ├── single_file.c │ │ ├── unknownBitmask │ │ └── unknownBitmask.c │ │ └── withMatchFuncComment │ │ └── commentOnMatchFn.c │ └── tmpl │ └── support_file.tmpl ├── lex.go ├── lex_test.go ├── lua.go ├── parse.go ├── parse_bench_test.go ├── parse_test.go ├── scripts └── generate │ ├── configs │ ├── geoip2_config.json │ ├── headersmore_config.json │ ├── lua_config.json │ ├── nap_v4_config.json │ ├── nap_v5_config.json │ ├── njs_config.json │ ├── nplus_R33_config.json │ ├── nplus_latest_config.json │ ├── oss_124_config.json │ ├── oss_126_config.json │ ├── oss_latest_config.json │ └── otel_config.json │ └── generate.sh ├── testdata └── configs │ ├── bad-args │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── braces │ ├── extra-brace.conf │ └── missing-brace.conf │ ├── broken1 │ ├── nginx.conf │ └── nginx2.conf │ ├── comments-between-args-disable-parse │ └── nginx.conf │ ├── comments-between-args │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── directive-with-space │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── emptiness │ └── nginx.conf │ ├── empty-braces │ └── nginx.conf │ ├── empty-config │ └── nginx.conf │ ├── empty-value-map │ ├── nginx.conf │ └── nginx.json │ ├── geo │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── geoip2 │ └── nginx.conf │ ├── if-check │ └── nginx.conf │ ├── if-expr │ ├── empty-parens.conf │ ├── empty-spaced-parens.conf │ ├── missing-closing-paren.conf │ ├── missing-opening-paren.conf │ ├── nginx.conf │ ├── no-parens.conf │ └── spaced-parens.conf │ ├── includes-cycle │ ├── invalid │ │ ├── location1.conf │ │ ├── location2.conf │ │ └── nginx.conf │ └── valid │ │ ├── location1.conf │ │ ├── location2.conf │ │ └── nginx.conf │ ├── includes-globbed │ ├── http.conf │ ├── http.json │ ├── locations │ │ ├── location1.conf │ │ ├── location1.json │ │ ├── location2.conf │ │ └── location2.json │ ├── nginx.conf │ ├── nginx.json │ ├── servers │ │ ├── locations │ │ │ ├── not-included.conf │ │ │ └── not-included.json │ │ ├── server1.conf │ │ ├── server1.json │ │ ├── server2.conf │ │ └── server2.json │ └── xp.json │ ├── includes-regular │ ├── conf.d │ │ ├── bar.conf │ │ ├── details.conf │ │ ├── foo.conf │ │ ├── http-inner.conf │ │ └── server.conf │ ├── foo.conf │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── invalid-map │ └── nginx.conf │ ├── large-config │ ├── nginx.conf.bz2 │ └── nginx.conf.kld │ ├── limit-req-zone │ └── nginx.conf │ ├── lua-basic │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── lua-block-larger │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── lua-block-simple │ ├── nginx.conf │ ├── nginx.json │ ├── simple.conf │ └── xp.json │ ├── lua-block-tricky │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── master.sh │ ├── messy │ ├── nginx.conf │ ├── nginx.json │ └── off │ ├── missing-semicolon-above │ └── nginx.conf │ ├── missing-semicolon-below │ └── nginx.conf │ ├── missing-semicolon │ ├── broken-above.conf │ ├── broken-above.json │ ├── broken-below.conf │ └── broken-below.json │ ├── nap-waf-v4 │ └── nginx.conf │ ├── nap-waf-v5 │ └── nginx.conf │ ├── premature-eof │ └── nginx.conf │ ├── quote-behavior │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── quoted-right-brace │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── returns │ ├── nginx.conf │ └── nginx.json │ ├── russian-text │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── simple-variable-with-braces │ └── nginx.conf │ ├── simple │ ├── nginx.conf │ ├── nginx.json │ └── xp.json │ ├── spelling-mistake │ ├── nginx.conf │ └── nginx.json │ ├── testdata │ ├── braces │ │ ├── extra-brace.conf │ │ └── missing-brace.conf │ ├── broken1 │ │ ├── nginx.conf │ │ └── nginx2.conf │ ├── comments-between-args │ │ └── nginx.conf │ ├── directive-with-space │ │ └── nginx.conf │ ├── empty-config │ │ └── nginx.conf │ ├── empty-value-map │ │ └── nginx.conf │ ├── if-expr │ │ ├── empty-parens.conf │ │ ├── empty-spaced-parens.conf │ │ ├── missing-closing-paren.conf │ │ ├── missing-opening-paren.conf │ │ ├── nginx.conf │ │ ├── no-parens.conf │ │ └── spaced-parens.conf │ ├── includes-globbed │ │ ├── http.conf │ │ ├── locations │ │ │ ├── location1.conf │ │ │ └── location2.conf │ │ ├── nginx.conf │ │ └── servers │ │ │ ├── locations │ │ │ └── not-included.conf │ │ │ ├── server1.conf │ │ │ └── server2.conf │ ├── includes-regular │ │ ├── conf.d │ │ │ ├── bar.conf │ │ │ ├── foo.conf │ │ │ └── server.conf │ │ ├── foo.conf │ │ └── nginx.conf │ ├── large-config │ │ ├── nginx.conf.bz2 │ │ └── nginx.conf.kld │ ├── lua-block-larger │ │ └── nginx.conf │ ├── lua-block-simple │ │ └── nginx.conf │ ├── lua-block-tricky │ │ └── nginx.conf │ ├── messy │ │ └── nginx.conf │ ├── missing-semicolon-above │ │ └── nginx.conf │ ├── missing-semicolon-below │ │ └── nginx.conf │ ├── quote-behavior │ │ └── nginx.conf │ ├── quoted-right-brace │ │ └── nginx.conf │ ├── russian-text │ │ └── nginx.conf │ ├── simple │ │ └── nginx.conf │ ├── spelling-mistake │ │ └── nginx.conf │ ├── upstream_resolver_directive │ │ ├── multiple_resolvers.conf │ │ ├── multiple_resolvers.conf.golden │ │ ├── multiple_resolvers_with_ports.conf │ │ ├── multiple_resolvers_with_ports.conf.golden │ │ ├── simple.conf │ │ └── simple.conf.golden │ └── with-comments │ │ └── nginx.conf │ ├── types │ └── nginx.conf │ ├── ubuntu-default │ ├── mime.types │ ├── modules-enabled │ │ ├── 50-mod-http-image-filter.conf │ │ └── 50-mod-http-xslt-filter.conf │ ├── nginx.conf │ └── sites-enabled │ │ └── default │ ├── upstream_resolver_directive │ ├── multiple_resolvers.conf │ ├── multiple_resolvers.conf.golden │ ├── multiple_resolvers_with_ports.conf │ ├── multiple_resolvers_with_ports.conf.golden │ ├── simple.conf │ └── simple.conf.golden │ └── with-comments │ ├── nginx.conf │ ├── nginx.json │ └── xp.json ├── tools.go ├── types.go ├── types_test.go ├── util.go └── util_test.go /.dockerignore: -------------------------------------------------------------------------------- 1 | build -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | ### Describe the bug 9 | 10 | A clear and concise description of what the bug is. 11 | 12 | ### To reproduce 13 | 14 | Steps to reproduce the behavior: 15 | 16 | 1. Deploy {{REPOSITORY_NAME}} using 17 | 2. View output/logs/configuration on '...' 18 | 3. See error 19 | 20 | ### Expected behavior 21 | 22 | A clear and concise description of what you expected to happen. 23 | 24 | ### Your environment 25 | 26 | - Version of the {{REPOSITORY_NAME}} or specific commit 27 | 28 | - Target deployment platform 29 | 30 | ### Additional context 31 | 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | ### Is your feature request related to a problem? Please describe 9 | 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when ... 11 | 12 | ### Describe the solution you'd like 13 | 14 | A clear and concise description of what you want to happen. 15 | 16 | ### Describe alternatives you've considered 17 | 18 | A clear and concise description of any alternative solutions or features you've considered. 19 | 20 | ### Additional context 21 | 22 | Add any other context or screenshots about the feature request here. 23 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | - package-ecosystem: "gomod" 8 | directory: "/" 9 | schedule: 10 | interval: weekly 11 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Proposed changes 2 | 3 | Describe the use case and detail of the change. If this PR addresses an issue on GitHub, make sure to include a link to that issue using one of the [supported keywords](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) here in this description (not in the title of the PR). 4 | 5 | ### Checklist 6 | 7 | Before creating a PR, run through this checklist and mark each as complete. 8 | 9 | - [ ] I have read the [`CONTRIBUTING`](https://github.com/nginxinc/nginx-go-crossplane/blob/main/CONTRIBUTING.md) document 10 | - [ ] If applicable, I have added tests that prove my fix is effective or that my feature works 11 | - [ ] If applicable, I have checked that any relevant tests pass after adding my changes 12 | - [ ] I have updated any relevant documentation ([`README.md`](https://github.com/nginxinc/nginx-go-crossplane/blob/main/README.md)) 13 | -------------------------------------------------------------------------------- /.github/workflows/cicd.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - 'v[0-9]+.[0-9]+.[0-9]+' 9 | pull_request: 10 | branches: 11 | - main 12 | types: 13 | - opened 14 | - reopened 15 | - synchronize 16 | 17 | jobs: 18 | checks: 19 | name: Linting 20 | runs-on: ubuntu-22.04 21 | steps: 22 | - name: Checkout code 23 | uses: actions/checkout@v4 24 | - name: Setup Golang Environment 25 | uses: actions/setup-go@v5 26 | with: 27 | go-version-file: go.mod 28 | - name: Lint Code 29 | uses: golangci/golangci-lint-action@v6 30 | with: 31 | version: v1.64.2 32 | only-new-issues: true 33 | verify: false 34 | 35 | unit-tests: 36 | name: Unit Tests 37 | runs-on: ubuntu-22.04 38 | needs: checks 39 | steps: 40 | - name: Checkout Repository 41 | uses: actions/checkout@v4 42 | - name: Setup Golang Environment 43 | uses: actions/setup-go@v5 44 | - name: Run Tests 45 | run: make test 46 | - name: Upload coverage to Codecov 47 | uses: codecov/codecov-action@v5 48 | with: 49 | files: ./results/crossplane-go-coverage.out 50 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - uses: actions-ecosystem/action-get-latest-tag@v1 15 | id: get-latest-tag 16 | 17 | - uses: actions-ecosystem/action-bump-semver@v1 18 | id: bump-semver 19 | with: 20 | current_version: ${{ steps.get-latest-tag.outputs.tag }} 21 | level: patch 22 | 23 | - uses: actions-ecosystem/action-push-tag@v1 24 | with: 25 | tag: ${{ steps.bump-semver.outputs.new_version }} 26 | message: 'chore: version bump for ${{ steps.bump-semver.outputs.new_version }}' 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | bin 3 | build 4 | results 5 | _tmp 6 | .DS_store 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Python Byte-compiled / optimized / DLL files 12 | __pycache__/ 13 | *.py[cod] 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | coverage.* 18 | 19 | # editor and IDE paraphernalia 20 | .idea 21 | .vscode 22 | *.code-workspace 23 | *.swp 24 | *.swo 25 | *~ 26 | *.orig 27 | *.go-e 28 | *.iml 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | # GolangCI-Lint settings 2 | 3 | # Disable all linters and enable the required ones 4 | linters: 5 | enable-all: true 6 | disable: 7 | - cyclop 8 | - depguard 9 | - varnamelen 10 | - goimports # handled by `make format` 11 | - gofmt # handled by `make format` 12 | - wsl # hyper specific to a the creator and not configurable enough to be useful - https://github.com/bombsimon/wsl 13 | - dupl 14 | - gomnd 15 | - godox 16 | - nlreturn 17 | - wrapcheck 18 | - thelper 19 | - testpackage 20 | - nestif 21 | - gofumpt 22 | - goerr113 23 | - errorlint 24 | - ifshort 25 | - paralleltest 26 | - interfacer 27 | - golint 28 | - maligned 29 | - scopelint 30 | - exhaustruct 31 | # deprecated 32 | - deadcode 33 | - varcheck 34 | - structcheck 35 | - nosnakecase 36 | - exhaustivestruct 37 | 38 | 39 | # Run options 40 | run: 41 | # 10 minute timeout for analysis 42 | timeout: 10m 43 | modules-download-mode: mod 44 | skip-dirs-use-default: true 45 | 46 | 47 | # Specific linter settings 48 | linters-settings: 49 | gocyclo: 50 | # Minimal code complexity to report 51 | min-complexity: 16 52 | maligned: 53 | # Print struct with more effective memory layout 54 | suggest-new: true 55 | govet: 56 | # Report shadowed variables 57 | check-shadowing: true 58 | misspell: 59 | # Correct spellings using locale preferences for US 60 | locale: US 61 | goimports: 62 | # Put imports beginning with prefix after 3rd-party packages 63 | local-prefixes: gitswarm.f5net.com/indigo,gitlab.com/f5 64 | errcheck: 65 | ignore: ^Close.*,os:^Setenv.*,fmt:.*,io/ioutil:^Read.*,github.com/spf13/viper:.*,github.com/pkg/errors:^Wrap.* 66 | funclen: 67 | skip-ifles: 68 | - ".*\\.gen\\.go" 69 | 70 | lll: 71 | line-length: 140 72 | 73 | issues: 74 | # Exclude configuration 75 | exclude-rules: 76 | # Exclude gochecknoinits and gosec from running on tests files 77 | - path: _test\.go 78 | linters: 79 | - gochecknoinits 80 | - gosec 81 | - path: test/* 82 | linters: 83 | - gochecknoinits 84 | - gosec 85 | # Exclude lll issues for long lines with go:generate 86 | - linters: 87 | - lll 88 | source: "^//go:generate " 89 | - path: _desiredstatehistory(|_test)\.go 90 | linters: 91 | - dupl 92 | 93 | # Disable maximum issues count per one linter 94 | max-issues-per-linter: 0 95 | 96 | # Disable maximum count of issues with the same text 97 | max-same-issues: 0 98 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @nginxinc/plaform-tech-leads 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the moderation team at nginx-oss-community@f5.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, 71 | available at 72 | 73 | For answers to common questions about this code of conduct, see 74 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | The following is a set of guidelines for contributing to the {{REPOSITORY_NAME}}. We really appreciate that you are considering contributing! 4 | 5 | #### Table Of Contents 6 | 7 | [Getting Started](#getting-started) 8 | 9 | [Contributing](#contributing) 10 | 11 | [Code Guidelines](#code-guidelines) 12 | 13 | [Code of Conduct](https://github.com/{{REPOSITORY_OWNER}}/{{REPOSITORY_URL}}/blob/main/CODE_OF_CONDUCT.md) 14 | 15 | ## Getting Started 16 | 17 | Follow our [Installation Guide](https://github.com/{{REPOSITORY_OWNER}}/{{REPOSITORY_URL}}/blob/main/README.md#Installation) to get the {{REPOSITORY_NAME}} up and running. 18 | 19 | 20 | 21 | ## Contributing 22 | 23 | ### Report a Bug 24 | 25 | To report a bug, open an issue on GitHub with the label `bug` using the available bug report issue template. Please ensure the bug has not already been reported. **If the bug is a potential security vulnerability, please report using our security policy.** 26 | 27 | ### Suggest a Feature or Enhancement 28 | 29 | To suggest a feature or enhancement, please create an issue on GitHub with the label `feature` or `enhancement` using the available feature request issue template. Please ensure the feature or enhancement has not already been suggested. 30 | 31 | ### Open a Pull Request 32 | 33 | * Fork the repo, create a branch, implement your changes, add any relevant tests, submit a PR when your changes are **tested** and ready for review. 34 | * Fill in [our pull request template](https://github.com/{{REPOSITORY_OWNER}}/{{REPOSITORY_URL}}/blob/main/.github/pull_request_template.md). 35 | 36 | Note: if you'd like to implement a new feature, please consider creating a feature request issue first to start a discussion about the feature. 37 | 38 | ## Code Guidelines 39 | 40 | 41 | 42 | ### Git Guidelines 43 | 44 | * Keep a clean, concise and meaningful git commit history on your branch (within reason), rebasing locally and squashing before submitting a PR. 45 | * If possible and/or relevant, use the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format when writing a commit message, so that changelogs can be automatically generated 46 | * Follow the guidelines of writing a good commit message as described here and summarised in the next few points: 47 | * In the subject line, use the present tense ("Add feature" not "Added feature"). 48 | * In the subject line, use the imperative mood ("Move cursor to..." not "Moves cursor to..."). 49 | * Limit the subject line to 67 characters or less. 50 | * Limit the rest of the commit message to 72 characters or less. 51 | * Reference issues and pull requests liberally after the subject line. 52 | * Add more detailed description in the body of the git message (`git commit -a` to give you more space and time in your text editor to write a good message instead of `git commit -am`). 53 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | This library was originally forked from https://github.com/aluttik/go-crossplane. Credit goes to aluttik (https://github.com/aluttik) and we are grateful for his effort. 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PACKAGE = $(notdir $(patsubst %/,%,$(dir $(realpath $(lastword $(MAKEFILE_LIST)))))) 2 | OUT_DIR ?= build 3 | RESULTS_DIR ?= results 4 | DOCKER_REGISTRY ?= local 5 | DOCKER_TAG ?= latest 6 | LINT_BIN := ./bin/golangci-lint 7 | 8 | SHELL=/bin/bash 9 | .SHELLFLAGS=-c -eo pipefail 10 | 11 | ####################################### 12 | ## Local set up. 13 | ####################################### 14 | 15 | .PHONY: init deps deps-upgrade fmt test lint lint-shell gen 16 | 17 | init: 18 | git config core.hooksPath .githooks 19 | go install golang.org/x/tools/cmd/goimports 20 | go install github.com/jstemmer/go-junit-report 21 | 22 | deps: 23 | go mod download 24 | go mod tidy 25 | go mod verify 26 | 27 | deps-upgrade: 28 | GOFLAGS="" go get -u ./... 29 | $(MAKE) deps 30 | 31 | ####################################### 32 | ## Tests, codegen, lint and format. 33 | ####################################### 34 | fmt: 35 | $(info Running goimports...) 36 | @goimports -w -e $$(find . -type f -name '*.go') 37 | 38 | test: 39 | $(info Running unit tests...) 40 | mkdir -p $(RESULTS_DIR) 41 | CGO_ENABLED=1 go test -race -v -cover ./... -coverprofile=$(RESULTS_DIR)/$(PACKAGE)-coverage.out 2>&1 | tee >(go-junit-report > $(RESULTS_DIR)/report.xml) 42 | @echo "Total code coverage:" 43 | @go tool cover -func=$(RESULTS_DIR)/$(PACKAGE)-coverage.out | grep 'total:' | tee $(RESULTS_DIR)/anybadge.out 44 | @go tool cover -html=$(RESULTS_DIR)/$(PACKAGE)-coverage.out -o $(RESULTS_DIR)/coverage.html 45 | 46 | test-only-failed: 47 | $(info Running unit tests (showing only failed ones with context)...) 48 | go test -v -race ./... | grep --color -B 45 -A 5 -E '^FAIL.+' 49 | 50 | $(LINT_BIN): 51 | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.51.2 52 | 53 | lint: $(LINT_BIN) 54 | $(LINT_BIN) run 55 | 56 | lint-docker: 57 | docker run --rm -v "${PWD}":/app -w /app golangci/golangci-lint:v1.51.2 golangci-lint run 58 | 59 | lint-shell: 60 | shellcheck -x $$(find . -name "*.sh" -type f) 61 | 62 | gen: 63 | go generate -x ./... 64 | $(MAKE) fmt 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nginx-go-crossplane 2 | A Go port of the NGINX config/JSON converter [crossplane](https://github.com/nginxinc/crossplane). 3 | 4 | ## Parse 5 | This is an example that takes a path to an NGINX config file, converts it to JSON, and prints the result to stdout. 6 | ```go 7 | package main 8 | 9 | import ( 10 | "encoding/json" 11 | "fmt" 12 | "os" 13 | 14 | "github.com/nginxinc/nginx-go-crossplane" 15 | ) 16 | 17 | func main() { 18 | path := os.Args[1] 19 | 20 | payload, err := crossplane.Parse(path, &crossplane.ParseOptions{}) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, err := json.Marshal(payload) 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | fmt.Println(string(b)) 31 | } 32 | ``` 33 | 34 | ## Build 35 | This is an example that takes a path to a JSON file, converts it to an NGINX config, and prints the result to stdout. 36 | ```go 37 | package main 38 | 39 | import ( 40 | "bytes" 41 | "encoding/json" 42 | "fmt" 43 | "io/ioutil" 44 | "os" 45 | 46 | "github.com/nginxinc/nginx-go-crossplane" 47 | ) 48 | 49 | func main() { 50 | path := os.Args[1] 51 | 52 | file, err := os.Open(path) 53 | if err != nil { 54 | panic(err) 55 | } 56 | 57 | content, err := ioutil.ReadAll(file) 58 | if err != nil { 59 | panic(err) 60 | } 61 | 62 | var payload crossplane.Payload 63 | if err = json.Unmarshal(content, &payload); err != nil { 64 | panic(err) 65 | } 66 | 67 | var buf bytes.Buffer 68 | if err = crossplane.Build(&buf, payload.Config[0], &crossplane.BuildOptions{}); err != nil { 69 | panic(err) 70 | } 71 | 72 | fmt.Println(buf.String()) 73 | } 74 | ``` 75 | 76 | # Generate support for third-party modules 77 | This is a simple example that takes the path of a third-party module source code to generate support for it. For detailed usage of the tool, please run 78 | `go run ./cmd/generate/ --help`. 79 | Assuming the source code path of that module is `./src`, you can call `go run ./cmd/generate/ --src-path=./src -directive-map-name=directives -match-func-name=Match -match-func-comment=comment`. The output will be similar to: 80 | 81 | ```go 82 | /** 83 | * Copyright (c) F5, Inc. 84 | * 85 | * This source code is licensed under the Apache License, Version 2.0 license found in the 86 | * LICENSE file in the root directory of this source tree. 87 | */ 88 | 89 | // Code generated by generator; DO NOT EDIT. 90 | // All the definitions are extracted from the source code 91 | // Each bit mask describes these behaviors: 92 | // - how many arguments the directive can take 93 | // - whether or not it is a block directive 94 | // - whether this is a flag (takes one argument that's either "on" or "off") 95 | // - which contexts it's allowed to be in 96 | 97 | package crossplane 98 | 99 | var directives = map[string][]uint{ 100 | "my_directive_1": { 101 | bitmask01|bitmask02|..., 102 | bitmask11|bitmask12|..., 103 | ... 104 | }, 105 | "my_directive_2": { 106 | bitmask01|bitmask02|..., 107 | bitmask11|bitmask12|..., 108 | ... 109 | }, 110 | } 111 | 112 | // comment 113 | func Match(directive string) ([]uint, bool) { 114 | m, ok := directives[directive] 115 | return m, ok 116 | } 117 | ``` 118 | You can redirect the stdout into a `.go` file, and pass the generated `matchFunc` to `ParseOptions.DirectiveSources` when invoking `Parse`. 119 | 120 | ## Contributing 121 | 122 | If you'd like to contribute to the project, please read our [Contributing guide](CONTRIBUTING.md). 123 | 124 | ## License 125 | 126 | [Apache License, Version 2.0](https://github.com/nginxinc/nginx-go-crossplane/blob/main/LICENSE) 127 | 128 | © [F5 Networks, Inc.](https://www.f5.com/) 2022 129 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Latest Versions 4 | 5 | We advise users to run or update to the most recent release of the {{REPOSITORY_NAME}}. Older versions of the {{REPOSITORY_NAME}} may not have all enhancements and/or bug fixes applied to them. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | The F5 Security Incident Response Team (F5 SIRT) has an email alias that makes it easy to report potential security vulnerabilities. 10 | 11 | * If you’re an F5 customer with an active support contract, please contact [F5 Technical Support](https://www.f5.com/services/support). 12 | * If you aren’t an F5 customer, please report any potential or current instances of security vulnerabilities with any F5 product to the F5 Security Incident Response Team at F5SIRT@f5.com 13 | 14 | For more information visit [https://www.f5.com/services/support/report-a-vulnerability](https://www.f5.com/services/support/report-a-vulnerability) 15 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## Ask a Question 4 | 5 | We use GitHub for tracking bugs and feature requests related to this project. 6 | 7 | Don't know how something in the {{REPOSITORY_NAME}} works? Curious if the {{REPOSITORY_NAME}} can achieve your desired functionality? Please open an Issue on GitHub with the label `question`. 8 | 9 | ## NGINX Specific Questions and/or Issues 10 | 11 | This isn't the right place to get support for NGINX specific questions, but the following resources are available below. Thanks for your understanding! 12 | 13 | ### Community Slack 14 | 15 | We have a community [Slack](https://nginxcommunity.slack.com/)! 16 | 17 | If you are not a member click [here](https://join.slack.com/t/nginxcommunity/shared_invite/zt-1aaa22w80-~_~wSMNyPxLPLp5xunOC7w) to sign up (and let us know if the link does not seem to be working!) 18 | 19 | Once you join, check out the `#beginner-questions` and `nginx-users` channels :) 20 | 21 | ### Documentation 22 | 23 | For a comprehensive list of all NGINX directives, check out . 24 | 25 | For a comprehensive list of admin and deployment guides for all NGINX products, check out . 26 | 27 | ### Mailing List 28 | 29 | Want to get in touch with the NGINX dev team directly? Try using the relevant mailing list found at ! 30 | -------------------------------------------------------------------------------- /analyze_appProtectWAFv4_directives.gen.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var appProtectWAFv4Directives = map[string][]uint{ 19 | "app_protect_app_name": { 20 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 21 | }, 22 | "app_protect_compressed_requests_action": { 23 | ngxHTTPMainConf | ngxConfTake1, 24 | }, 25 | "app_protect_config_set_timeout": { 26 | ngxHTTPMainConf | ngxConfTake1, 27 | }, 28 | "app_protect_cookie_seed": { 29 | ngxHTTPMainConf | ngxConfTake1, 30 | }, 31 | "app_protect_cpu_thresholds": { 32 | ngxHTTPMainConf | ngxConfTake2, 33 | }, 34 | "app_protect_custom_log_attribute": { 35 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2, 36 | }, 37 | "app_protect_enable": { 38 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfFlag, 39 | }, 40 | "app_protect_enforcer_address": { 41 | ngxHTTPMainConf | ngxConfTake1, 42 | }, 43 | "app_protect_enforcer_memory_limit_mb": { 44 | ngxHTTPMainConf | ngxConfTake1, 45 | }, 46 | "app_protect_failure_mode_action": { 47 | ngxHTTPMainConf | ngxConfTake1, 48 | }, 49 | "app_protect_global_settings": { 50 | ngxHTTPMainConf | ngxConfTake1, 51 | }, 52 | "app_protect_logging_str": { 53 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 54 | }, 55 | "app_protect_physical_memory_util_thresholds": { 56 | ngxHTTPMainConf | ngxConfTake2, 57 | }, 58 | "app_protect_policy_file": { 59 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 60 | }, 61 | "app_protect_reconnect_period_seconds": { 62 | ngxHTTPMainConf | ngxConfTake1, 63 | }, 64 | "app_protect_request_buffer_overflow_action": { 65 | ngxHTTPMainConf | ngxConfTake1, 66 | }, 67 | "app_protect_response_enforcement_disable": { 68 | ngxHTTPMainConf | ngxConfTake1, 69 | }, 70 | "app_protect_security_log": { 71 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2, 72 | }, 73 | "app_protect_security_log_enable": { 74 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfFlag, 75 | }, 76 | "app_protect_streaming_buffer_watermarks": { 77 | ngxHTTPMainConf | ngxConfTake2, 78 | }, 79 | "app_protect_user_defined_signatures": { 80 | ngxHTTPMainConf | ngxConfTake1, 81 | }, 82 | } 83 | 84 | // MatchAppProtectWAFv4 is a MatchFunc for App Protect v4 module. 85 | func MatchAppProtectWAFv4(directive string) ([]uint, bool) { 86 | m, ok := appProtectWAFv4Directives[directive] 87 | return m, ok 88 | } 89 | -------------------------------------------------------------------------------- /analyze_appProtectWAFv5_directives.gen.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var appProtectWAFv5Directives = map[string][]uint{ 19 | "app_protect_app_name": { 20 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 21 | }, 22 | "app_protect_compressed_requests_action": { 23 | ngxHTTPMainConf | ngxConfTake1, 24 | }, 25 | "app_protect_config_set_timeout": { 26 | ngxHTTPMainConf | ngxConfTake1, 27 | }, 28 | "app_protect_cookie_seed": { 29 | ngxHTTPMainConf | ngxConfTake1, 30 | }, 31 | "app_protect_cpu_thresholds": { 32 | ngxHTTPMainConf | ngxConfTake2, 33 | }, 34 | "app_protect_custom_log_attribute": { 35 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2, 36 | }, 37 | "app_protect_enable": { 38 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfFlag, 39 | }, 40 | "app_protect_enforcer_address": { 41 | ngxHTTPMainConf | ngxConfTake1, 42 | }, 43 | "app_protect_enforcer_memory_limit_mb": { 44 | ngxHTTPMainConf | ngxConfTake1, 45 | }, 46 | "app_protect_failure_mode_action": { 47 | ngxHTTPMainConf | ngxConfTake1, 48 | }, 49 | "app_protect_global_settings": { 50 | ngxHTTPMainConf | ngxConfTake1, 51 | }, 52 | "app_protect_logging_str": { 53 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 54 | }, 55 | "app_protect_physical_memory_util_thresholds": { 56 | ngxHTTPMainConf | ngxConfTake2, 57 | }, 58 | "app_protect_policy_file": { 59 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 60 | }, 61 | "app_protect_reconnect_period_seconds": { 62 | ngxHTTPMainConf | ngxConfTake1, 63 | }, 64 | "app_protect_request_buffer_overflow_action": { 65 | ngxHTTPMainConf | ngxConfTake1, 66 | }, 67 | "app_protect_response_enforcement_disable": { 68 | ngxHTTPMainConf | ngxConfTake1, 69 | }, 70 | "app_protect_security_log": { 71 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2, 72 | }, 73 | "app_protect_security_log_enable": { 74 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfFlag, 75 | }, 76 | "app_protect_streaming_buffer_watermarks": { 77 | ngxHTTPMainConf | ngxConfTake2, 78 | }, 79 | "app_protect_user_defined_signatures": { 80 | ngxHTTPMainConf | ngxConfTake1, 81 | }, 82 | } 83 | 84 | // MatchAppProtectWAFv5 is a MatchFunc for App Protect v5 module. 85 | func MatchAppProtectWAFv5(directive string) ([]uint, bool) { 86 | m, ok := appProtectWAFv5Directives[directive] 87 | return m, ok 88 | } 89 | -------------------------------------------------------------------------------- /analyze_geoip2_directives.gen.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var geoip2Directives = map[string][]uint{ 19 | "geoip2": { 20 | ngxHTTPMainConf | ngxConfBlock | ngxConfTake1, 21 | ngxStreamMainConf | ngxConfBlock | ngxConfTake1, 22 | }, 23 | "geoip2_proxy": { 24 | ngxHTTPMainConf | ngxConfTake1, 25 | }, 26 | "geoip2_proxy_recursive": { 27 | ngxHTTPMainConf | ngxConfFlag, 28 | }, 29 | } 30 | 31 | // MatchGeoip2Latest is a MatchFunc for the latest version of geoip2. 32 | func MatchGeoip2Latest(directive string) ([]uint, bool) { 33 | m, ok := geoip2Directives[directive] 34 | return m, ok 35 | } 36 | -------------------------------------------------------------------------------- /analyze_headersMore_directives.gen.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var headersMoreDirectives = map[string][]uint{ 19 | "more_clear_headers": { 20 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf1More, 21 | }, 22 | "more_clear_input_headers": { 23 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf1More, 24 | }, 25 | "more_set_headers": { 26 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf1More, 27 | }, 28 | "more_set_input_headers": { 29 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf1More, 30 | }, 31 | } 32 | 33 | // MatchHeadersMoreLatest is a MatchFunc for the latest version of headersmore. 34 | func MatchHeadersMoreLatest(directive string) ([]uint, bool) { 35 | m, ok := headersMoreDirectives[directive] 36 | return m, ok 37 | } 38 | -------------------------------------------------------------------------------- /analyze_map.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package crossplane 9 | 10 | import "fmt" 11 | 12 | // mapParameterMasks holds bit masks that define the behavior of the body of map-like directives. 13 | // Some map directives have "special parameter" with different behaviors than the default. 14 | type mapParameterMasks struct { 15 | specialParameterMasks map[string]uint 16 | defaultMasks uint 17 | } 18 | 19 | //nolint:gochecknoglobals 20 | var mapBodies = map[string]mapParameterMasks{ 21 | "charset_map": { 22 | defaultMasks: ngxConfTake1, 23 | }, 24 | "geo": { 25 | specialParameterMasks: map[string]uint{"ranges": ngxConfNoArgs, "proxy_recursive": ngxConfNoArgs}, 26 | defaultMasks: ngxConfTake1, 27 | }, 28 | "map": { 29 | specialParameterMasks: map[string]uint{"volatile": ngxConfNoArgs, "hostnames": ngxConfNoArgs}, 30 | defaultMasks: ngxConfTake1, 31 | }, 32 | "match": { 33 | defaultMasks: ngxConf1More, 34 | }, 35 | "types": { 36 | defaultMasks: ngxConf1More, 37 | }, 38 | "split_clients": { 39 | defaultMasks: ngxConfTake1, 40 | }, 41 | "geoip2": { 42 | specialParameterMasks: map[string]uint{"auto_reload": ngxConfTake1}, 43 | defaultMasks: ngxConf1More, 44 | }, 45 | "otel_exporter": { 46 | defaultMasks: ngxConfTake1, 47 | }, 48 | } 49 | 50 | // analyzeMapBody validates the body of a map-like directive. Map-like directives are block directives 51 | // that don't contain nginx directives, and therefore cannot be analyzed in the same way as other blocks. 52 | func analyzeMapBody(fname string, parameter *Directive, term string, mapCtx string) error { 53 | masks, known := mapBodies[mapCtx] 54 | // if we're not inside a known map-like directive, don't bother analyzing 55 | if !known { 56 | return nil 57 | } 58 | if term != ";" { 59 | return &ParseError{ 60 | What: fmt.Sprintf(`unexpected "%s"`, term), 61 | File: &fname, 62 | Line: ¶meter.Line, 63 | Statement: parameter.String(), 64 | BlockCtx: mapCtx, 65 | } 66 | } 67 | 68 | if mask, ok := masks.specialParameterMasks[parameter.Directive]; ok { 69 | // use mask to check the parameter's arguments 70 | if hasValidArguments(mask, parameter.Args) { 71 | return nil 72 | } 73 | 74 | return &ParseError{ 75 | What: "invalid number of parameters", 76 | File: &fname, 77 | Line: ¶meter.Line, 78 | Statement: parameter.String(), 79 | BlockCtx: mapCtx, 80 | } 81 | } 82 | 83 | mask := masks.defaultMasks 84 | 85 | // use mask to check the parameter's arguments 86 | if hasValidArguments(mask, parameter.Args) { 87 | return nil 88 | } 89 | 90 | return &ParseError{ 91 | What: "invalid number of parameters", 92 | File: &fname, 93 | Line: ¶meter.Line, 94 | Statement: parameter.String(), 95 | BlockCtx: mapCtx, 96 | } 97 | } 98 | 99 | func hasValidArguments(mask uint, args []string) bool { 100 | return ((mask>>len(args)&1) != 0 && len(args) <= 7) || // NOARGS to TAKE7 101 | ((mask&ngxConfFlag) != 0 && len(args) == 1 && validFlag(args[0])) || 102 | ((mask & ngxConfAny) != 0) || 103 | ((mask&ngxConf1More) != 0 && len(args) >= 1) || 104 | ((mask&ngxConf2More) != 0 && len(args) >= 2) 105 | } 106 | -------------------------------------------------------------------------------- /analyze_otel_directives.gen.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var otelDirectives = map[string][]uint{ 19 | "otel_exporter": { 20 | ngxHTTPMainConf | ngxConfBlock | ngxConfNoArgs, 21 | }, 22 | "otel_service_name": { 23 | ngxHTTPMainConf | ngxConfTake1, 24 | }, 25 | "otel_span_attr": { 26 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2, 27 | }, 28 | "otel_span_name": { 29 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 30 | }, 31 | "otel_trace": { 32 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 33 | }, 34 | "otel_trace_context": { 35 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, 36 | }, 37 | } 38 | 39 | // MatchOtelLatest is a MatchFunc for latest version of otel. 40 | func MatchOtelLatest(directive string) ([]uint, bool) { 41 | m, ok := otelDirectives[directive] 42 | return m, ok 43 | } 44 | -------------------------------------------------------------------------------- /buffer.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package crossplane 9 | 10 | import ( 11 | "io" 12 | "strings" 13 | ) 14 | 15 | // Creator abstracts file creation (to write configs to something other than files). 16 | type Creator interface { 17 | Create(path string) (io.WriteCloser, error) 18 | Reset() 19 | } 20 | 21 | // FileString is a string representation of a file. 22 | type FileString struct { 23 | Name string 24 | w strings.Builder 25 | } 26 | 27 | // Write makes this an io.Writer. 28 | func (fs *FileString) Write(b []byte) (int, error) { 29 | return fs.w.Write(b) 30 | } 31 | 32 | // Close makes this an io.Closer. 33 | func (fs *FileString) Close() error { 34 | fs.w.WriteByte('\n') 35 | return nil 36 | } 37 | 38 | // String makes this a Stringer. 39 | func (fs *FileString) String() string { 40 | return fs.w.String() 41 | } 42 | 43 | // StringsCreator is an option for rendering config files to strings(s). 44 | type StringsCreator struct { 45 | Files []*FileString 46 | } 47 | 48 | // Create makes this a Creator. 49 | func (sc *StringsCreator) Create(file string) (io.WriteCloser, error) { 50 | wc := &FileString{Name: file} 51 | sc.Files = append(sc.Files, wc) 52 | return wc, nil 53 | } 54 | 55 | // Reset returns the Creator to its initial state. 56 | func (sc *StringsCreator) Reset() { 57 | sc.Files = []*FileString{} 58 | } 59 | -------------------------------------------------------------------------------- /cmd/generate/cmd_util.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package main 9 | 10 | import ( 11 | "errors" 12 | "fmt" 13 | "strings" 14 | 15 | "github.com/nginxinc/nginx-go-crossplane/internal/generator" 16 | ) 17 | 18 | type filterFlag struct { 19 | filter map[string]struct{} 20 | } 21 | 22 | func (f *filterFlag) Set(value string) error { 23 | if f.filter == nil { 24 | f.filter = make(map[string]struct{}) 25 | } 26 | f.filter[value] = struct{}{} 27 | return nil 28 | } 29 | 30 | func (f *filterFlag) String() string { 31 | return fmt.Sprintf("%v", *f) 32 | } 33 | 34 | type overrideItem struct { 35 | directive string 36 | masks []generator.Mask 37 | } 38 | 39 | func (item *overrideItem) UnmarshalText(text []byte) error { 40 | rawOverride := string(text) 41 | 42 | // rawStr should follow the format: directive:bitmask00|bitmask01|...,bitmask10|bitmask11|... 43 | directive, definition, found := strings.Cut(rawOverride, ":") 44 | if !found { 45 | return errors.New("colon not found") 46 | } 47 | directive = strings.TrimSpace(directive) 48 | 49 | item.directive = directive 50 | if directive == "" { 51 | return errors.New("directive name is empty") 52 | } 53 | 54 | definition = strings.TrimSpace(definition) 55 | if definition == "" { 56 | return errors.New("directive definition is empty") 57 | } 58 | 59 | for _, varNamesStr := range strings.Split(definition, ",") { 60 | varNamesList := strings.Split(varNamesStr, "|") 61 | varNamesNum := len(varNamesList) 62 | directiveMask := make(generator.Mask, varNamesNum) 63 | 64 | for idx, varName := range varNamesList { 65 | trimmedName := strings.TrimSpace(varName) 66 | if trimmedName == "" { 67 | return errors.New("one directive bitmask is empty, check if there are unnecessary |") 68 | } 69 | 70 | directiveMask[idx] = trimmedName 71 | } 72 | item.masks = append(item.masks, directiveMask) 73 | } 74 | 75 | return nil 76 | } 77 | 78 | type override map[string][]generator.Mask 79 | 80 | func (ov *override) String() string { 81 | if ov == nil { 82 | return "nil" 83 | } 84 | return fmt.Sprintf("%v", *ov) 85 | } 86 | 87 | func (ov *override) Set(value string) error { 88 | if *ov == nil { 89 | *ov = override{} 90 | } 91 | var item overrideItem 92 | err := item.UnmarshalText([]byte(value)) 93 | if err != nil { 94 | return fmt.Errorf("invalid override %s:%w", value, err) 95 | } 96 | 97 | (*ov)[item.directive] = item.masks 98 | return nil 99 | } 100 | -------------------------------------------------------------------------------- /cmd/generate/cmd_util_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package main 9 | 10 | import ( 11 | "testing" 12 | 13 | "github.com/nginxinc/nginx-go-crossplane/internal/generator" 14 | "github.com/stretchr/testify/require" 15 | ) 16 | 17 | //nolint:funlen 18 | func TestOverrideParser(t *testing.T) { 19 | t.Parallel() 20 | tests := []struct { 21 | name string 22 | input string 23 | expected overrideItem 24 | wantErr bool 25 | }{ 26 | { 27 | name: "normalFormat_pass", 28 | input: "location:ngxHTTPMainConf|ngxConfTake12,ngxStreamMainConf", 29 | 30 | expected: overrideItem{ 31 | directive: "location", 32 | masks: []generator.Mask{ 33 | {"ngxHTTPMainConf", "ngxConfTake12"}, 34 | {"ngxStreamMainConf"}, 35 | }, 36 | }, 37 | wantErr: false, 38 | }, 39 | { 40 | name: "withSpaces_pass", 41 | input: "hash:ngxHTTPUpsConf | ngxConfTake12, ngxStreamUpsConf | ngxConfTake12", 42 | expected: overrideItem{ 43 | directive: "hash", 44 | masks: []generator.Mask{ 45 | {"ngxHTTPUpsConf", "ngxConfTake12"}, 46 | {"ngxStreamUpsConf", "ngxConfTake12"}, 47 | }, 48 | }, 49 | wantErr: false, 50 | }, 51 | { 52 | name: "withoutColon_fail", 53 | input: "hashngxHTTPUpsConf | ngxConfTake12,ngxStreamUpsConf | ngxConfTake12", 54 | wantErr: true, 55 | }, 56 | { 57 | name: "colonLeftsideEmpty_fail", 58 | input: " :ngxHTTPUpsConf | ngxConfTake12,ngxStreamUpsConf | ngxConfTake12", 59 | wantErr: true, 60 | }, 61 | { 62 | name: "colonRightsideEmpty_fail", 63 | input: "hash: ", 64 | wantErr: true, 65 | }, 66 | { 67 | name: "emptyBitmask_fail", 68 | input: "hash: ngxHTTPUpsConf| ", 69 | wantErr: true, 70 | }, 71 | } 72 | 73 | for _, tc := range tests { 74 | tc := tc 75 | t.Run(tc.name, func(t *testing.T) { 76 | t.Parallel() 77 | var got overrideItem 78 | err := got.UnmarshalText([]byte(tc.input)) 79 | 80 | if tc.wantErr { 81 | require.Error(t, err) 82 | } else { 83 | require.NoError(t, err) 84 | } 85 | 86 | // If the testcase wants an error and there is an error, skip the output file validation. 87 | // Output makes no sense when there is an error. 88 | if err != nil { 89 | return 90 | } 91 | 92 | require.Equal(t, tc.expected, got) 93 | }) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package crossplane 9 | 10 | import ( 11 | "encoding/json" 12 | "fmt" 13 | ) 14 | 15 | type ParseError struct { 16 | What string 17 | File *string 18 | Line *int 19 | // Raw directive statement causing the parse error. 20 | Statement string 21 | // Block in which parse error occurred. 22 | BlockCtx string 23 | originalErr error 24 | } 25 | 26 | func (e *ParseError) Error() string { 27 | file := "(nofile)" 28 | if e.File != nil { 29 | file = *e.File 30 | } 31 | if e.Line != nil { 32 | return fmt.Sprintf("%s in %s:%d", e.What, file, *e.Line) 33 | } 34 | return fmt.Sprintf("%s in %s", e.What, file) 35 | } 36 | 37 | func (e *ParseError) MarshalJSON() ([]byte, error) { 38 | return json.Marshal(e.Error()) 39 | } 40 | 41 | func (e *ParseError) Unwrap() error { 42 | return e.originalErr 43 | } 44 | -------------------------------------------------------------------------------- /errors_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package crossplane 9 | 10 | import ( 11 | "testing" 12 | 13 | "github.com/stretchr/testify/assert" 14 | ) 15 | 16 | func TestErrorString(t *testing.T) { 17 | t.Parallel() 18 | tf := "test.conf" 19 | tl := 1 20 | var te error 21 | 22 | tcs := []struct { 23 | f *string 24 | w string 25 | l *int 26 | e error 27 | 28 | exp string 29 | }{ 30 | {&tf, "error", &tl, te, "error in test.conf:1"}, 31 | {nil, "error", &tl, te, "error in (nofile):1"}, 32 | {nil, "error", nil, te, "error in (nofile)"}, 33 | {&tf, "error", nil, te, "error in test.conf"}, 34 | {nil, "", nil, te, " in (nofile)"}, 35 | } 36 | 37 | for _, tc := range tcs { 38 | e := &ParseError{File: tc.f, Line: tc.l, What: tc.w, originalErr: tc.e} 39 | 40 | assert.Equal(t, tc.exp, e.Error()) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nginxinc/nginx-go-crossplane 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/jstemmer/go-junit-report v1.0.0 7 | github.com/stretchr/testify v1.10.0 8 | golang.org/x/tools v0.32.0 9 | ) 10 | 11 | require ( 12 | github.com/davecgh/go-spew v1.1.1 // indirect 13 | github.com/kr/pretty v0.3.1 // indirect 14 | github.com/pmezard/go-difflib v1.0.0 // indirect 15 | golang.org/x/mod v0.24.0 // indirect 16 | golang.org/x/sync v0.13.0 // indirect 17 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 18 | gopkg.in/yaml.v3 v3.0.1 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 5 | github.com/jstemmer/go-junit-report v1.0.0 h1:8X1gzZpR+nVQLAht+L/foqOeX2l9DTZoaIPbEQHxsds= 6 | github.com/jstemmer/go-junit-report v1.0.0/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 7 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 8 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 9 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 10 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 11 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 12 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 13 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 14 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 15 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 16 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 17 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 18 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 19 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 20 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 21 | golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= 22 | golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= 23 | golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= 24 | golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 25 | golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= 26 | golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= 27 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 28 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 29 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 30 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 31 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 32 | -------------------------------------------------------------------------------- /internal/generator/generator.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package generator 9 | 10 | import ( 11 | "encoding/json" 12 | "io" 13 | ) 14 | 15 | type Filters map[string]struct{} 16 | 17 | func (fs *Filters) UnmarshalJSON(data []byte) error { 18 | var v []string 19 | if err := json.Unmarshal(data, &v); err != nil { 20 | return err 21 | } 22 | 23 | if *fs == nil { 24 | *fs = make(Filters) 25 | } 26 | 27 | for _, s := range v { 28 | (*fs)[s] = struct{}{} 29 | } 30 | return nil 31 | } 32 | 33 | type GenerateConfig struct { 34 | // Filter is a map used to exclude directives from generator. 35 | // The key of it is the directive names. 36 | Filter Filters `json:"filter"` 37 | 38 | // Override is a map used to override the masks from source code of directives. 39 | // The key of it is the directive name. The value is the masks we want. 40 | // If a directive exists in Override, generator won't consider its definition 41 | // in source code. 42 | Override map[string][]Mask `json:"override"` 43 | 44 | // DirectiveMapName is the name assigned to the variable containing the directives 45 | // discovered by generator. The variable name generally starts with a 46 | // lowercase to avoid export. Users will use the generated function named by 47 | // MatchFuncName to validate the module directives in nginx configurations. 48 | // It should not be empty. 49 | DirectiveMapName string `json:"directiveMapName"` 50 | 51 | // MatchFuncName is the name assigned to the matchFunc generated by the generator. 52 | // It should generally start with a uppercase to export. 53 | // Users will use the generated function named by MatchFuncName 54 | // to validate the module directives in nginx configurations. 55 | // It should not be empty. 56 | MatchFuncName string `json:"matchFuncName"` 57 | 58 | // MatchFuncComment is the comment appears above the generated MatchFunc. 59 | // It may contain some information like what modules are included 60 | // in the generated MatchFunc. Generally it should start with MatchFuncName. 61 | // If it is empty, no comments will appear above the generated MatchFunc. 62 | MatchFuncComment string `json:"matchFuncComment"` 63 | } 64 | 65 | // Generate receives a string sourcePath, an io.Writer writer, and a 66 | // GenerateConfig config. It will extract all the directives definitions 67 | // from the .c and .cpp files in sourcePath and its subdirectories, 68 | // then output the corresponding directive masks map and matchFunc via writer. 69 | func Generate(sourcePath string, writer io.Writer, config GenerateConfig) error { 70 | return genFromSrcCode(sourcePath, writer, config) 71 | } 72 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/commentsInDefinition: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var directives = map[string][]uint{ 19 | "my_directive_1": { 20 | ngxHTTPMainConf | ngxConfTake2, 21 | }, 22 | "my_directive_2": { 23 | ngxHTTPMainConf | ngxConfFlag, 24 | }, 25 | "my_directive_3": { 26 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfNoArgs, 27 | }, 28 | } 29 | 30 | 31 | func Match(directive string) ([]uint, bool) { 32 | m, ok := directives[directive] 33 | return m, ok 34 | } 35 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/filter: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var directives = map[string][]uint{ 19 | "my_directive_1": { 20 | ngxHTTPMainConf | ngxConfTake2, 21 | }, 22 | "my_directive_4": { 23 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake4, 24 | }, 25 | } 26 | 27 | 28 | func Match(directive string) ([]uint, bool) { 29 | m, ok := directives[directive] 30 | return m, ok 31 | } 32 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/filterAndOverride: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var directives = map[string][]uint{ 19 | "my_directive_4": { 20 | ngxHTTPMainConf | ngxConfTake2, 21 | ngxHTTPMainConf | ngxConfTake3, 22 | }, 23 | } 24 | 25 | 26 | func Match(directive string) ([]uint, bool) { 27 | m, ok := directives[directive] 28 | return m, ok 29 | } 30 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/fullNgxBitmaskCover: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var directives = map[string][]uint{ 19 | "all_bitmask": { 20 | ngxConfNoArgs | ngxConfTake1 | ngxConfTake2 | ngxConfTake3 | ngxConfTake4 | ngxConfTake5 | ngxConfTake6 | ngxConfTake7 | ngxConfTake12 | ngxConfTake13 | ngxConfTake23 | ngxConfTake123 | ngxConfTake1234 | ngxConfBlock | ngxConfFlag | ngxConfAny | ngxConf1More | ngxConf2More | ngxDirectConf | ngxMainConf, 21 | }, 22 | } 23 | 24 | 25 | func Match(directive string) ([]uint, bool) { 26 | m, ok := directives[directive] 27 | return m, ok 28 | } 29 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/normalDefinition: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var myDirectives = map[string][]uint{ 19 | "my_directive_1": { 20 | ngxHTTPMainConf | ngxConfTake2, 21 | }, 22 | "my_directive_2": { 23 | ngxHTTPMainConf | ngxConfFlag, 24 | }, 25 | "my_directive_3": { 26 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfNoArgs, 27 | }, 28 | } 29 | 30 | 31 | func MyMatchFn(directive string) ([]uint, bool) { 32 | m, ok := myDirectives[directive] 33 | return m, ok 34 | } 35 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/override: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var directives = map[string][]uint{ 19 | "my_directive_1": { 20 | ngxHTTPMainConf | ngxConfTake1, 21 | ngxHTTPMainConf | ngxConfTake2, 22 | }, 23 | "my_directive_2": { 24 | ngxHTTPMainConf | ngxConfFlag, 25 | }, 26 | "my_directive_3": { 27 | ngxHTTPMainConf | ngxConfTake2, 28 | ngxHTTPMainConf | ngxConfTake3, 29 | }, 30 | "my_directive_4": { 31 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake4, 32 | }, 33 | } 34 | 35 | 36 | func Match(directive string) ([]uint, bool) { 37 | m, ok := directives[directive] 38 | return m, ok 39 | } 40 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/repeatDefine: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var directives = map[string][]uint{ 19 | "my_directive_1": { 20 | ngxHTTPMainConf | ngxConfTake2, 21 | ngxHTTPMainConf | ngxConfTake1, 22 | }, 23 | "my_directive_2": { 24 | ngxHTTPMainConf | ngxConfFlag, 25 | ngxHTTPMainConf | ngxConfNoArgs, 26 | }, 27 | "my_directive_3": { 28 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfNoArgs, 29 | ngxHTTPMainConf | ngxConfTake2, 30 | }, 31 | } 32 | 33 | 34 | func Match(directive string) ([]uint, bool) { 35 | m, ok := directives[directive] 36 | return m, ok 37 | } 38 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/single_file: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var directives = map[string][]uint{ 19 | "my_directive_1": { 20 | ngxHTTPMainConf | ngxConfTake2, 21 | }, 22 | "my_directive_2": { 23 | ngxHTTPMainConf | ngxConfFlag, 24 | }, 25 | } 26 | 27 | 28 | func Match(directive string) ([]uint, bool) { 29 | m, ok := directives[directive] 30 | return m, ok 31 | } 32 | -------------------------------------------------------------------------------- /internal/generator/testdata/expected/withMatchFuncComment: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var myDirectives = map[string][]uint{ 19 | "my_directive_1": { 20 | ngxHTTPMainConf | ngxConfTake2, 21 | }, 22 | "my_directive_2": { 23 | ngxHTTPMainConf | ngxConfFlag, 24 | }, 25 | "my_directive_3": { 26 | ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfNoArgs, 27 | }, 28 | } 29 | 30 | // This is a matchFunc 31 | func MyMatchFn(directive string) ([]uint, bool) { 32 | m, ok := myDirectives[directive] 33 | return m, ok 34 | } 35 | -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/commentsInDefinition/with_comments.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2/*igonre me*/, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"/*igonre me*/), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS, 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | 22 | ngx_null_command 23 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/filter/filter.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS, 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | { ngx_string("my_directive_4"), 22 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE4, 23 | 0, 24 | 0, 25 | 0, 26 | NULL }, 27 | 28 | ngx_null_command 29 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/filterAndOverride/filter_and_override.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS, 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | { ngx_string("my_directive_4"), 22 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE4, 23 | 0, 24 | 0, 25 | 0, 26 | NULL }, 27 | 28 | ngx_null_command 29 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/fullNgxBitmaskCover/all_bitmask.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("all_bitmask"), 4 | NGX_CONF_NOARGS|NGX_CONF_TAKE1| 5 | NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4|NGX_CONF_TAKE5|NGX_CONF_TAKE6|NGX_CONF_TAKE7| 6 | NGX_CONF_TAKE12|NGX_CONF_TAKE13|NGX_CONF_TAKE23|NGX_CONF_TAKE123|NGX_CONF_TAKE1234| 7 | NGX_CONF_BLOCK|NGX_CONF_FLAG|NGX_CONF_ANY|NGX_CONF_1MORE| 8 | NGX_CONF_2MORE|NGX_DIRECT_CONF|NGX_MAIN_CONF 9 | , 10 | 0, 11 | 0, 12 | NULL }, 13 | 14 | ngx_null_command 15 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/noDirectives/noDirectives.c: -------------------------------------------------------------------------------- 1 | // nothing here -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/normalDefinition/normal.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS, 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | 22 | ngx_null_command 23 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/override/override.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS, 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | { ngx_string("my_directive_4"), 22 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE4, 23 | 0, 24 | 0, 25 | 0, 26 | NULL }, 27 | 28 | ngx_null_command 29 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/repeatDefine/definition1.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, /*comments will be igored by generator*/ 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,/*comments will be igored by generator*/ 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS,//comments will be igored by generator 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | 22 | ngx_null_command 23 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/repeatDefine/definition2.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, /*comments will be igored by generator*/ 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_NOARGS,/*comments will be igored by generator*/ 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2,//comments will be igored by generator 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | 22 | ngx_null_command 23 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/single_file.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | 16 | ngx_null_command 17 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/unknownBitmask/unknownBitmask.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|FAKE_BITMASK, // unknown bitmask FAKE_BITMASK 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS, 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | 22 | ngx_null_command 23 | }; -------------------------------------------------------------------------------- /internal/generator/testdata/source_codes/withMatchFuncComment/commentOnMatchFn.c: -------------------------------------------------------------------------------- 1 | static ngx_command_t my_directives[] = { 2 | 3 | { ngx_string("my_directive_1"), 4 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 5 | 0, 6 | 0, 7 | 0, 8 | NULL }, 9 | { ngx_string("my_directive_2"), 10 | NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, 11 | 0, 12 | 0, 13 | 0, 14 | NULL }, 15 | { ngx_string("my_directive_3"), 16 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_NOARGS, 17 | 0, 18 | 0, 19 | 0, 20 | NULL }, 21 | 22 | ngx_null_command 23 | }; -------------------------------------------------------------------------------- /internal/generator/tmpl/support_file.tmpl: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Code generated by generator; DO NOT EDIT. 9 | // All the definitions are extracted from the source code 10 | // Each bit mask describes these behaviors: 11 | // - how many arguments the directive can take 12 | // - whether or not it is a block directive 13 | // - whether this is a flag (takes one argument that's either "on" or "off") 14 | // - which contexts it's allowed to be in 15 | 16 | package crossplane 17 | 18 | var {{.MapVariableName}} = map[string][]uint{ 19 | {{- range $name, $bitDefs := .Directive2Masks}} 20 | "{{$name}}": {{"{"}} 21 | {{- range $bitDef := $bitDefs}} 22 | {{Join $bitDef " | "}}, 23 | {{- end}} 24 | {{"}"}}, 25 | {{- end}} 26 | } 27 | 28 | {{if ne .MatchFnComment ""}}// {{.MatchFnComment}}{{end}} 29 | func {{.MatchFnName}}(directive string) ([]uint, bool) { 30 | m, ok := {{.MapVariableName}}[directive] 31 | return m, ok 32 | } 33 | -------------------------------------------------------------------------------- /scripts/generate/configs/geoip2_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"geoip2Directives", 3 | "matchFuncName":"MatchGeoip2Latest", 4 | "matchFuncComment":"MatchGeoip2Latest is a MatchFunc for the latest version of geoip2." 5 | } 6 | -------------------------------------------------------------------------------- /scripts/generate/configs/headersmore_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"headersMoreDirectives", 3 | "matchFuncName":"MatchHeadersMoreLatest", 4 | "matchFuncComment":"MatchHeadersMoreLatest is a MatchFunc for the latest version of headersmore." 5 | } 6 | -------------------------------------------------------------------------------- /scripts/generate/configs/lua_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"luaDirectives", 3 | "matchFuncName":"MatchLuaLatest", 4 | "override":{ 5 | "content_by_lua_block":[["ngxHTTPLocConf", "ngxHTTPLifConf", "ngxConfTake1"]], 6 | "rewrite_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxHTTPLifConf", "ngxConfTake1"]], 7 | "ssl_certificate_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxConfTake1"]], 8 | "ssl_session_fetch_by_lua_block":[["ngxHTTPMainConf", "ngxConfTake1"]], 9 | "ssl_session_store_by_lua_block":[["ngxHTTPMainConf", "ngxConfTake1"]], 10 | "set_by_lua_block": [["ngxHTTPSrvConf", "ngxHTTPSifConf", "ngxHTTPLocConf", "ngxHTTPLifConf", "ngxConfTake2"]], 11 | "ssl_client_hello_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxConfTake1"]], 12 | "body_filter_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxHTTPLifConf", "ngxConfTake1"]], 13 | "init_by_lua_block":[["ngxHTTPMainConf", "ngxConfTake1"]], 14 | "init_worker_by_lua_block":[["ngxHTTPMainConf","ngxConfTake1"]], 15 | "header_filter_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxHTTPLifConf", "ngxConfTake1"]], 16 | "log_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxHTTPLifConf", "ngxConfTake1"]], 17 | "access_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxHTTPLifConf", "ngxConfTake1"]], 18 | "balancer_by_lua_block":[["ngxHTTPUpsConf", "ngxConfTake1"]], 19 | "server_rewrite_by_lua_block":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxConfTake1"]], 20 | "exit_worker_by_lua_block":[["ngxHTTPMainConf", "ngxConfTake1"]] 21 | }, 22 | "matchFuncComment":"MatchLuaLatest is a MatchFunc for latest version of Lua." 23 | } 24 | -------------------------------------------------------------------------------- /scripts/generate/configs/nap_v4_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"appProtectWAFv4Directives", 3 | "matchFuncName":"MatchAppProtectWAFv4", 4 | "matchFuncComment":"MatchAppProtectWAFv4 is a MatchFunc for App Protect v4 module.", 5 | "override":{ 6 | "app_protect_enable":[["ngxHTTPMainConf", "ngxHTTPSrvConf" , "ngxHTTPLocConf", "ngxConfFlag"]], 7 | "app_protect_security_log_enable":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxConfFlag"]] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /scripts/generate/configs/nap_v5_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"appProtectWAFv5Directives", 3 | "matchFuncName":"MatchAppProtectWAFv5", 4 | "matchFuncComment":"MatchAppProtectWAFv5 is a MatchFunc for App Protect v5 module.", 5 | "override":{ 6 | "app_protect_enable":[["ngxHTTPMainConf", "ngxHTTPSrvConf" , "ngxHTTPLocConf", "ngxConfFlag"]], 7 | "app_protect_security_log_enable":[["ngxHTTPMainConf", "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxConfFlag"]] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /scripts/generate/configs/njs_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"njsDirectives", 3 | "matchFuncName":"MatchNjsLatest", 4 | "matchFuncComment":"MatchNjsLatest is a MatchFunc for the latest version of njs." 5 | } 6 | -------------------------------------------------------------------------------- /scripts/generate/configs/oss_124_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"oss124Directives", 3 | "matchFuncName":"MatchOss124", 4 | "filter":[ 5 | "epoll_events", 6 | "health_check_header", 7 | "body", 8 | "body_size", 9 | "proxy", 10 | "http2_pool_size", 11 | "post_action", 12 | "pcre_buffer", 13 | "degrade", 14 | "gzip_window", 15 | "proxy_downstream_buffer", 16 | "degradation", 17 | "ssi_ignore_recycled_buffers", 18 | "uwsgi_string", 19 | "proxy_ssl_session_cache", 20 | "proxy_upstream_buffer", 21 | "eventport_events", 22 | "expect", 23 | "gzip_hash", 24 | "require", 25 | "proxy_keepalive", 26 | "http2_streams_index_size", 27 | "send", 28 | "kqueue_changes", 29 | "header", 30 | "devpoll_events", 31 | "kqueue_events", 32 | "postpone_gzipping", 33 | "acceptex_read", 34 | "iocp_threads", 35 | "devpoll_changes", 36 | "post_acceptex", 37 | "open_file_cache_events", 38 | "gzip_no_buffer" 39 | ], 40 | "override":{ 41 | "if":[[ "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxConfBlock", "ngxConfExpr", "ngxConf1More"]] 42 | }, 43 | "matchFuncComment":"MatchOss124 contains directives in OSS 1.2.4 source code(including GEOIP, Perl, and XSLT)" 44 | } 45 | -------------------------------------------------------------------------------- /scripts/generate/configs/oss_126_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"oss126Directives", 3 | "matchFuncName":"MatchOss126", 4 | "filter":[ 5 | "epoll_events", 6 | "health_check_header", 7 | "body", 8 | "body_size", 9 | "proxy", 10 | "http2_pool_size", 11 | "post_action", 12 | "pcre_buffer", 13 | "degrade", 14 | "gzip_window", 15 | "proxy_downstream_buffer", 16 | "degradation", 17 | "ssi_ignore_recycled_buffers", 18 | "uwsgi_string", 19 | "proxy_ssl_session_cache", 20 | "proxy_upstream_buffer", 21 | "eventport_events", 22 | "expect", 23 | "gzip_hash", 24 | "require", 25 | "proxy_keepalive", 26 | "http2_streams_index_size", 27 | "send", 28 | "kqueue_changes", 29 | "header", 30 | "devpoll_events", 31 | "kqueue_events", 32 | "postpone_gzipping", 33 | "acceptex_read", 34 | "iocp_threads", 35 | "devpoll_changes", 36 | "post_acceptex", 37 | "open_file_cache_events", 38 | "gzip_no_buffer" 39 | ], 40 | "override":{ 41 | "if":[[ "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxConfBlock", "ngxConfExpr", "ngxConf1More"]] 42 | }, 43 | "matchFuncComment":"MatchOss126 contains directives in OSS 1.2.6 source code(including GEOIP, Perl, and XSLT)" 44 | } 45 | -------------------------------------------------------------------------------- /scripts/generate/configs/oss_latest_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"ossLatestDirectives", 3 | "matchFuncName":"MatchOssLatest", 4 | "filter":[ 5 | "epoll_events", 6 | "health_check_header", 7 | "body", 8 | "body_size", 9 | "proxy", 10 | "http2_pool_size", 11 | "post_action", 12 | "pcre_buffer", 13 | "degrade", 14 | "gzip_window", 15 | "proxy_downstream_buffer", 16 | "degradation", 17 | "ssi_ignore_recycled_buffers", 18 | "uwsgi_string", 19 | "proxy_ssl_session_cache", 20 | "proxy_upstream_buffer", 21 | "eventport_events", 22 | "expect", 23 | "gzip_hash", 24 | "require", 25 | "proxy_keepalive", 26 | "http2_streams_index_size", 27 | "send", 28 | "kqueue_changes", 29 | "header", 30 | "devpoll_events", 31 | "kqueue_events", 32 | "postpone_gzipping", 33 | "acceptex_read", 34 | "iocp_threads", 35 | "devpoll_changes", 36 | "post_acceptex", 37 | "open_file_cache_events", 38 | "gzip_no_buffer" 39 | ], 40 | "override":{ 41 | "if":[[ "ngxHTTPSrvConf", "ngxHTTPLocConf", "ngxConfBlock", "ngxConfExpr", "ngxConf1More"]] 42 | }, 43 | "matchFuncComment":"MatchOssLatest contains directives in latest version of OSS source code(including GEOIP, Perl, and XSLT)" 44 | } 45 | -------------------------------------------------------------------------------- /scripts/generate/configs/otel_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directiveMapName":"otelDirectives", 3 | "matchFuncName":"MatchOtelLatest", 4 | "filter":[ 5 | "endpoint", 6 | "interval", 7 | "batch_size", 8 | "batch_count" 9 | ], 10 | "matchFuncComment":"MatchOtelLatest is a MatchFunc for latest version of otel." 11 | } 12 | -------------------------------------------------------------------------------- /testdata/configs/bad-args/nginx.conf: -------------------------------------------------------------------------------- 1 | user; 2 | events {} 3 | http {} 4 | -------------------------------------------------------------------------------- /testdata/configs/bad-args/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "failed", 3 | "errors": [ 4 | { 5 | "file": "testdata/configs/bad-args/nginx.conf", 6 | "error": "invalid number of arguments in \"user\" directive in testdata/configs/bad-args/nginx.conf:1", 7 | "line": 1 8 | } 9 | ], 10 | "config": [ 11 | { 12 | "file": "testdata/configs/bad-args/nginx.conf", 13 | "status": "failed", 14 | "errors": [ 15 | { 16 | "error": "invalid number of arguments in \"user\" directive in testdata/configs/bad-args/nginx.conf:1", 17 | "line": 1 18 | } 19 | ], 20 | "parsed": [ 21 | { 22 | "directive": "events", 23 | "line": 2, 24 | "args": [], 25 | "block": [] 26 | }, 27 | { 28 | "directive": "http", 29 | "line": 3, 30 | "args": [], 31 | "block": [] 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /testdata/configs/bad-args/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/bad-args/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "user", 12 | "line": 1, 13 | "args": [] 14 | }, 15 | { 16 | "directive": "events", 17 | "line": 2, 18 | "args": [] 19 | }, 20 | { 21 | "directive": "http", 22 | "line": 3, 23 | "args": [] 24 | } 25 | ] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /testdata/configs/braces/extra-brace.conf: -------------------------------------------------------------------------------- 1 | # Generated by NGINX Controller 2021-02-01 17:36:11.009002952 +0000 UTC m=+230.885274373; 2 | user nginx; 3 | worker_processes auto; 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | load_module modules/ngx_http_f5_metrics_module.so; 7 | events { 8 | worker_connections 1024; 9 | 10 | ##### Extra brace 11 | }} 12 | 13 | 14 | http { 15 | server { 16 | server_name 127.0.0.1; 17 | listen 127.0.0.1:49151; 18 | access_log off; 19 | f5_metrics off; 20 | location /api { 21 | api; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /testdata/configs/braces/missing-brace.conf: -------------------------------------------------------------------------------- 1 | # Generated by NGINX Controller 2021-02-01 17:36:11.009002952 +0000 UTC m=+230.885274373; 2 | user nginx; 3 | worker_processes auto; 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | load_module modules/ngx_http_f5_metrics_module.so; 7 | events { 8 | worker_connections 1024; 9 | 10 | } 11 | 12 | http { 13 | server { 14 | server_name 127.0.0.1; 15 | listen 127.0.0.1:49151; 16 | access_log off; 17 | f5_metrics off; 18 | location /api { 19 | api; 20 | } 21 | } 22 | ### Missing brace below 23 | -------------------------------------------------------------------------------- /testdata/configs/broken1/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | 3 | http { 4 | server { 5 | server_name ${url ; 6 | } 7 | } -------------------------------------------------------------------------------- /testdata/configs/broken1/nginx2.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | 3 | http { 4 | server { 5 | server_name# ${url ; 6 | } 7 | } -------------------------------------------------------------------------------- /testdata/configs/comments-between-args-disable-parse/nginx.conf: -------------------------------------------------------------------------------- 1 | http { #comment 1 2 | log_format #comment 2 3 | \#arg\ 1 #comment 3 4 | '#arg 2' #comment 4 5 | #comment 5 6 | ; 7 | } -------------------------------------------------------------------------------- /testdata/configs/comments-between-args/nginx.conf: -------------------------------------------------------------------------------- 1 | http { #comment 1 2 | log_format #comment 2 3 | \#arg\ 1 #comment 3 4 | '#arg 2' #comment 4 5 | #comment 5 6 | ; 7 | } 8 | -------------------------------------------------------------------------------- /testdata/configs/comments-between-args/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/comments-between-args/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "#", 17 | "line": 1, 18 | "args": [], 19 | "comment": "comment 1" 20 | }, 21 | { 22 | "directive": "log_format", 23 | "line": 2, 24 | "args": [ 25 | "\\#arg\\ 1", 26 | "#arg 2" 27 | ] 28 | }, 29 | { 30 | "directive": "#", 31 | "line": 2, 32 | "args": [], 33 | "comment": "comment 2" 34 | }, 35 | { 36 | "directive": "#", 37 | "line": 2, 38 | "args": [], 39 | "comment": "comment 3" 40 | }, 41 | { 42 | "directive": "#", 43 | "line": 2, 44 | "args": [], 45 | "comment": "comment 4" 46 | }, 47 | { 48 | "directive": "#", 49 | "line": 2, 50 | "args": [], 51 | "comment": "comment 5" 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /testdata/configs/comments-between-args/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/comments-between-args/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "#", 17 | "line": 1, 18 | "args": [], 19 | "comment": "comment 1" 20 | }, 21 | { 22 | "directive": "log_format", 23 | "line": 2, 24 | "args": [ 25 | "\\#arg\\ 1", 26 | "#arg 2" 27 | ] 28 | }, 29 | { 30 | "directive": "#", 31 | "line": 2, 32 | "args": [], 33 | "comment": "comment 2" 34 | }, 35 | { 36 | "directive": "#", 37 | "line": 2, 38 | "args": [], 39 | "comment": "comment 3" 40 | }, 41 | { 42 | "directive": "#", 43 | "line": 2, 44 | "args": [], 45 | "comment": "comment 4" 46 | }, 47 | { 48 | "directive": "#", 49 | "line": 2, 50 | "args": [], 51 | "comment": "comment 5" 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /testdata/configs/directive-with-space/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | } 3 | http { 4 | map $http_user_agent $mobile { 5 | default 0; 6 | '~Opera Mini' 1; 7 | } 8 | 9 | charset_map koi8-r utf-8 { 10 | C0 D18E; 11 | C1 D0B0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/directive-with-space/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/directive-with-space/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [] 15 | }, 16 | { 17 | "directive": "http", 18 | "line": 3, 19 | "args": [], 20 | "block": [ 21 | { 22 | "directive": "map", 23 | "line": 4, 24 | "args": [ 25 | "$http_user_agent", 26 | "$mobile" 27 | ], 28 | "block": [ 29 | { 30 | "directive": "default", 31 | "line": 5, 32 | "args": [ 33 | "0" 34 | ] 35 | }, 36 | { 37 | "directive": "~Opera Mini", 38 | "line": 6, 39 | "args": [ 40 | "1" 41 | ] 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /testdata/configs/directive-with-space/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/directive-with-space/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [] 14 | }, 15 | { 16 | "directive": "http", 17 | "line": 3, 18 | "args": [], 19 | "block": [ 20 | { 21 | "directive": "map", 22 | "line": 4, 23 | "args": [ 24 | "$http_user_agent", 25 | "$mobile" 26 | ], 27 | "block": [ 28 | { 29 | "directive": "default", 30 | "line": 5, 31 | "args": [ 32 | "0" 33 | ] 34 | }, 35 | { 36 | "directive": "~Opera Mini", 37 | "line": 6, 38 | "args": [ 39 | "1" 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /testdata/configs/emptiness/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | # standard starter 3 | user xnginx; 4 | worker_processes auto; 5 | 6 | # skip some lines to test honoring line numbers 7 | 8 | 9 | # events is an exception where an empty block lives on one line 10 | 11 | events {} 12 | 13 | http { 14 | server { 15 | listen 80 default_server; 16 | listen [::]:80 default_server; 17 | server_name _; 18 | root /usr/share/nginx/html; # root comment on same line 19 | 20 | location /blah { 21 | # nothing here 22 | } 23 | 24 | location /foo { 25 | } 26 | 27 | location /rated_nginx { 28 | limit_rate 401k; 29 | return 201 "well hello there!\n"; 30 | } 31 | 32 | location /outer { 33 | location /outer/inner { 34 | } 35 | } 36 | 37 | # this will get expanded to a newline, because it's default form 38 | location /bar {} 39 | 40 | location / { 41 | return 200 "absolutely nothing here"; 42 | } 43 | 44 | location /final { 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /testdata/configs/empty-braces/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | # note this is on line 2 3 | user nginx; 4 | worker_processes auto; 5 | 6 | events {} 7 | 8 | http { 9 | server { 10 | # two ears are better than one 11 | listen 80 default_server; 12 | listen [::]:80 default_server; 13 | server_name _; # be discreet 14 | root /usr/share/nginx/html; 15 | 16 | # set apart 17 | location /foo { 18 | } 19 | 20 | # check grouping when numbered 21 | location /bunch1 { 22 | } 23 | location /bunch2 { 24 | } 25 | location /bunch3 { 26 | } 27 | 28 | # this should not have a space after it (before the closing brace) 29 | location / { 30 | return 200 "nothing here"; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /testdata/configs/empty-config/nginx.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nginxinc/nginx-go-crossplane/572130cfdf1fbfd5714d93c36855c010c4656b54/testdata/configs/empty-config/nginx.conf -------------------------------------------------------------------------------- /testdata/configs/empty-value-map/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | } 3 | http { 4 | map string $variable { 5 | '' $arg; 6 | *.example.com ''; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /testdata/configs/empty-value-map/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/empty-value-map/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [] 15 | }, 16 | { 17 | "directive": "http", 18 | "line": 3, 19 | "args": [], 20 | "block": [ 21 | { 22 | "directive": "map", 23 | "line": 4, 24 | "args": [ 25 | "string", 26 | "$variable" 27 | ], 28 | "block": [ 29 | { 30 | "directive": "", 31 | "line": 5, 32 | "args": [ 33 | "$arg" 34 | ] 35 | }, 36 | { 37 | "directive": "*.example.com", 38 | "line": 6, 39 | "args": [ 40 | "" 41 | ] 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /testdata/configs/geo/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | geo $geo { 7 | ranges; 8 | default 0; 9 | 192.168.1.0/24 1; 10 | 127.0.0.1 2; 11 | } 12 | server { 13 | listen 127.0.0.1:8080; 14 | server_name default_server; 15 | location / { 16 | if ( $geo = 2 ) { 17 | return 403; 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /testdata/configs/geo/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/geo/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "worker_connections", 17 | "line": 2, 18 | "args": [ 19 | "1024" 20 | ] 21 | } 22 | ] 23 | }, 24 | { 25 | "directive": "http", 26 | "line": 5, 27 | "args": [], 28 | "block": [ 29 | { 30 | "directive": "geo", 31 | "line": 6, 32 | "args": [ 33 | "$geo" 34 | ], 35 | "block": [ 36 | { 37 | "directive": "ranges", 38 | "line": 7, 39 | "args": [] 40 | }, 41 | { 42 | "directive": "default", 43 | "line": 8, 44 | "args": [ 45 | "0" 46 | ] 47 | }, 48 | { 49 | "directive": "192.168.1.0/24", 50 | "line": 9, 51 | "args": [ 52 | "1" 53 | ] 54 | }, 55 | { 56 | "directive": "127.0.0.1", 57 | "line": 10, 58 | "args": [ 59 | "2" 60 | ] 61 | } 62 | ] 63 | }, 64 | { 65 | "directive": "server", 66 | "line": 12, 67 | "args": [], 68 | "block": [ 69 | { 70 | "directive": "listen", 71 | "line": 13, 72 | "args": [ 73 | "127.0.0.1:8080" 74 | ] 75 | }, 76 | { 77 | "directive": "server_name", 78 | "line": 14, 79 | "args": [ 80 | "default_server" 81 | ] 82 | }, 83 | { 84 | "directive": "location", 85 | "line": 15, 86 | "args": [ 87 | "/" 88 | ], 89 | "block": [ 90 | { 91 | "directive": "if", 92 | "line": 16, 93 | "args": [ 94 | "$geo", 95 | "=", 96 | "2" 97 | ], 98 | "block": [ 99 | { 100 | "directive": "return", 101 | "line": 17, 102 | "args": [ 103 | "403" 104 | ] 105 | } 106 | ] 107 | } 108 | ] 109 | } 110 | ] 111 | } 112 | ] 113 | } 114 | ] 115 | } 116 | ] 117 | } -------------------------------------------------------------------------------- /testdata/configs/geo/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/geo/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "worker_connections", 17 | "line": 2, 18 | "args": [ 19 | "1024" 20 | ] 21 | } 22 | ] 23 | }, 24 | { 25 | "directive": "http", 26 | "line": 5, 27 | "args": [], 28 | "block": [ 29 | { 30 | "directive": "geo", 31 | "line": 6, 32 | "args": [ 33 | "$geo" 34 | ], 35 | "block": [ 36 | { 37 | "directive": "ranges", 38 | "line": 7, 39 | "args": [] 40 | }, 41 | { 42 | "directive": "default", 43 | "line": 8, 44 | "args": [ 45 | "0" 46 | ] 47 | }, 48 | { 49 | "directive": "192.168.1.0/24", 50 | "line": 9, 51 | "args": [ 52 | "1" 53 | ] 54 | }, 55 | { 56 | "directive": "127.0.0.1", 57 | "line": 10, 58 | "args": [ 59 | "2" 60 | ] 61 | } 62 | ] 63 | }, 64 | { 65 | "directive": "server", 66 | "line": 12, 67 | "args": [], 68 | "block": [ 69 | { 70 | "directive": "listen", 71 | "line": 13, 72 | "args": [ 73 | "127.0.0.1:8080" 74 | ] 75 | }, 76 | { 77 | "directive": "server_name", 78 | "line": 14, 79 | "args": [ 80 | "default_server" 81 | ] 82 | }, 83 | { 84 | "directive": "location", 85 | "line": 15, 86 | "args": [ 87 | "/" 88 | ], 89 | "block": [ 90 | { 91 | "directive": "if", 92 | "line": 16, 93 | "args": [ 94 | "$geo", 95 | "=", 96 | "2" 97 | ], 98 | "block": [ 99 | { 100 | "directive": "return", 101 | "line": 17, 102 | "args": [ 103 | "403" 104 | ] 105 | } 106 | ] 107 | } 108 | ] 109 | } 110 | ] 111 | } 112 | ] 113 | } 114 | ] 115 | } 116 | ] 117 | } -------------------------------------------------------------------------------- /testdata/configs/geoip2/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | geoip2 /etc/Geo/GeoLite2-City.mmdb { 3 | auto_reload 5s; 4 | $geoip2_city_name city names en; 5 | } 6 | geoip2_proxy 203.0.113.0/24; 7 | geoip2_proxy_recursive on; 8 | server { 9 | listen 80; 10 | server_name localhost; 11 | location / { 12 | return 200 "Hello $geoip2_city_name"; 13 | } 14 | } 15 | } 16 | 17 | 18 | stream { 19 | geoip2 /etc/Geo/GeoLite2-Country.mmdb { 20 | $geoip2_country_name country names en; 21 | } 22 | 23 | map $geoip2_country_name $backend{ 24 | "United States" us_backend; 25 | default default_backend; 26 | } 27 | 28 | server { 29 | listen 12345; 30 | proxy_pass $backend; 31 | } 32 | 33 | upstream us_backend { 34 | server 192.168.0.1:12345; 35 | } 36 | 37 | upstream default_backend { 38 | server 192.168.0.2:12345; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /testdata/configs/if-check/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | 10 | location / { 11 | return 200 "foo bar baz"; 12 | } 13 | 14 | location /wha { 15 | error_page 418 = @other; 16 | recursive_error_pages on; 17 | 18 | if ($something) { 19 | return 418; 20 | } 21 | } 22 | 23 | # this has a bad if directive 24 | location /fail { 25 | error_page 418 = @other; 26 | recursive_error_pages on; 27 | 28 | # empty if statement is an error 29 | if () { 30 | return 500; 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /testdata/configs/if-expr/empty-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if () { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/if-expr/empty-spaced-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ( ) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/if-expr/missing-closing-paren.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ($slow { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/if-expr/missing-opening-paren.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if $slow) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/if-expr/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ($slow) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/if-expr/no-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if $slow { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/if-expr/spaced-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ( $slow ) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/includes-cycle/invalid/location1.conf: -------------------------------------------------------------------------------- 1 | location /foo { 2 | include location2.conf; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-cycle/invalid/location2.conf: -------------------------------------------------------------------------------- 1 | location /bar { 2 | include location1.conf; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-cycle/invalid/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | listen 8080; 4 | include location1.conf; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /testdata/configs/includes-cycle/valid/location1.conf: -------------------------------------------------------------------------------- 1 | location /foo { 2 | include location2.conf; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-cycle/valid/location2.conf: -------------------------------------------------------------------------------- 1 | location /bar { 2 | return 200 'bar'; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-cycle/valid/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | listen 8080; 4 | include location1.conf; 5 | } 6 | 7 | server { 8 | listen 8081; 9 | include location2.conf; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/http.conf: -------------------------------------------------------------------------------- 1 | http { 2 | include servers/*.conf; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/http.json: -------------------------------------------------------------------------------- 1 | {"status":"ok","errors":[],"config":[{"file":"python/includes-globbed/http.conf","status":"ok","errors":[],"parsed":[{"directive":"http","line":1,"args":[],"block":[{"directive":"include","line":2,"args":["servers/*.conf"],"includes":[1,2]}]}]},{"file":"python/includes-globbed/servers/server1.conf","status":"ok","errors":[],"parsed":[{"directive":"server","line":1,"args":[],"block":[{"directive":"listen","line":2,"args":["8080"]},{"directive":"include","line":3,"args":["locations/*.conf"],"includes":[3,4]}]}]},{"file":"python/includes-globbed/servers/server2.conf","status":"ok","errors":[],"parsed":[{"directive":"server","line":1,"args":[],"block":[{"directive":"listen","line":2,"args":["8081"]},{"directive":"include","line":3,"args":["locations/*.conf"],"includes":[3,4]}]}]},{"file":"python/includes-globbed/locations/location1.conf","status":"ok","errors":[],"parsed":[{"directive":"location","line":1,"args":["/foo"],"block":[{"directive":"return","line":2,"args":["200","foo"]}]}]},{"file":"python/includes-globbed/locations/location2.conf","status":"ok","errors":[],"parsed":[{"directive":"location","line":1,"args":["/bar"],"block":[{"directive":"return","line":2,"args":["200","bar"]}]}]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/locations/location1.conf: -------------------------------------------------------------------------------- 1 | location /foo { 2 | return 200 'foo'; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/locations/location1.json: -------------------------------------------------------------------------------- 1 | {"status":"failed","errors":[{"file":"python/includes-globbed/locations/location1.conf","error":"\"location\" directive is not allowed here in python/includes-globbed/locations/location1.conf:1","line":1},{"file":"python/includes-globbed/locations/location1.conf","error":"\"return\" directive is not allowed here in python/includes-globbed/locations/location1.conf:2","line":2}],"config":[{"file":"python/includes-globbed/locations/location1.conf","status":"failed","errors":[{"error":"\"location\" directive is not allowed here in python/includes-globbed/locations/location1.conf:1","line":1},{"error":"\"return\" directive is not allowed here in python/includes-globbed/locations/location1.conf:2","line":2}],"parsed":[]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/locations/location2.conf: -------------------------------------------------------------------------------- 1 | location /bar { 2 | return 200 'bar'; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/locations/location2.json: -------------------------------------------------------------------------------- 1 | {"status":"failed","errors":[{"file":"python/includes-globbed/locations/location2.conf","error":"\"location\" directive is not allowed here in python/includes-globbed/locations/location2.conf:1","line":1},{"file":"python/includes-globbed/locations/location2.conf","error":"\"return\" directive is not allowed here in python/includes-globbed/locations/location2.conf:2","line":2}],"config":[{"file":"python/includes-globbed/locations/location2.conf","status":"failed","errors":[{"error":"\"location\" directive is not allowed here in python/includes-globbed/locations/location2.conf:1","line":1},{"error":"\"return\" directive is not allowed here in python/includes-globbed/locations/location2.conf:2","line":2}],"parsed":[]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | include http.conf; 3 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/includes-globbed/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [] 15 | }, 16 | { 17 | "directive": "include", 18 | "line": 2, 19 | "args": [ 20 | "http.conf" 21 | ], 22 | "includes": [ 23 | 1 24 | ] 25 | } 26 | ] 27 | }, 28 | { 29 | "file": "testdata/configs/includes-globbed/http.conf", 30 | "status": "ok", 31 | "errors": [], 32 | "parsed": [ 33 | { 34 | "directive": "http", 35 | "line": 1, 36 | "args": [], 37 | "block": [ 38 | { 39 | "directive": "include", 40 | "line": 2, 41 | "args": [ 42 | "servers/*.conf" 43 | ], 44 | "includes": [ 45 | 2, 46 | 3 47 | ] 48 | } 49 | ] 50 | } 51 | ] 52 | }, 53 | { 54 | "file": "testdata/configs/includes-globbed/servers/server1.conf", 55 | "status": "ok", 56 | "errors": [], 57 | "parsed": [ 58 | { 59 | "directive": "server", 60 | "line": 1, 61 | "args": [], 62 | "block": [ 63 | { 64 | "directive": "listen", 65 | "line": 2, 66 | "args": [ 67 | "8080" 68 | ] 69 | }, 70 | { 71 | "directive": "include", 72 | "line": 3, 73 | "args": [ 74 | "locations/*.conf" 75 | ], 76 | "includes": [ 77 | 4, 78 | 5 79 | ] 80 | } 81 | ] 82 | } 83 | ] 84 | }, 85 | { 86 | "file": "testdata/configs/includes-globbed/servers/server2.conf", 87 | "status": "ok", 88 | "errors": [], 89 | "parsed": [ 90 | { 91 | "directive": "server", 92 | "line": 1, 93 | "args": [], 94 | "block": [ 95 | { 96 | "directive": "listen", 97 | "line": 2, 98 | "args": [ 99 | "8081" 100 | ] 101 | }, 102 | { 103 | "directive": "include", 104 | "line": 3, 105 | "args": [ 106 | "locations/*.conf" 107 | ], 108 | "includes": [ 109 | 4, 110 | 5 111 | ] 112 | } 113 | ] 114 | } 115 | ] 116 | }, 117 | { 118 | "file": "testdata/configs/includes-globbed/locations/location1.conf", 119 | "status": "ok", 120 | "errors": [], 121 | "parsed": [ 122 | { 123 | "directive": "location", 124 | "line": 1, 125 | "args": [ 126 | "/foo" 127 | ], 128 | "block": [ 129 | { 130 | "directive": "return", 131 | "line": 2, 132 | "args": [ 133 | "200", 134 | "foo" 135 | ] 136 | } 137 | ] 138 | } 139 | ] 140 | }, 141 | { 142 | "file": "testdata/configs/includes-globbed/locations/location2.conf", 143 | "status": "ok", 144 | "errors": [], 145 | "parsed": [ 146 | { 147 | "directive": "location", 148 | "line": 1, 149 | "args": [ 150 | "/bar" 151 | ], 152 | "block": [ 153 | { 154 | "directive": "return", 155 | "line": 2, 156 | "args": [ 157 | "200", 158 | "bar" 159 | ] 160 | } 161 | ] 162 | } 163 | ] 164 | } 165 | ] 166 | } 167 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/servers/locations/not-included.conf: -------------------------------------------------------------------------------- 1 | # this file should never be included 2 | asdfasdfasdfasdfasdfasdfasdfasdfasdf 3 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/servers/locations/not-included.json: -------------------------------------------------------------------------------- 1 | {"status":"failed","errors":[{"file":"python/includes-globbed/servers/locations/not-included.conf","error":"","line":null}],"config":[{"file":"python/includes-globbed/servers/locations/not-included.conf","status":"failed","errors":[{"error":"","line":null}],"parsed":[]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/servers/server1.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8080; 3 | include locations/*.conf; 4 | } 5 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/servers/server1.json: -------------------------------------------------------------------------------- 1 | {"status":"failed","errors":[{"file":"python/includes-globbed/servers/server1.conf","error":"\"server\" directive is not allowed here in python/includes-globbed/servers/server1.conf:1","line":1},{"file":"python/includes-globbed/servers/server1.conf","error":"\"listen\" directive is not allowed here in python/includes-globbed/servers/server1.conf:2","line":2},{"file":"python/includes-globbed/servers/locations/not-included.conf","error":"","line":null}],"config":[{"file":"python/includes-globbed/servers/server1.conf","status":"failed","errors":[{"error":"\"server\" directive is not allowed here in python/includes-globbed/servers/server1.conf:1","line":1},{"error":"\"listen\" directive is not allowed here in python/includes-globbed/servers/server1.conf:2","line":2}],"parsed":[{"directive":"include","line":3,"args":["locations/*.conf"],"includes":[1]}]},{"file":"python/includes-globbed/servers/locations/not-included.conf","status":"failed","errors":[{"error":"","line":null}],"parsed":[]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/servers/server2.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8081; 3 | include locations/*.conf; 4 | } 5 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/servers/server2.json: -------------------------------------------------------------------------------- 1 | {"status":"failed","errors":[{"file":"python/includes-globbed/servers/server2.conf","error":"\"server\" directive is not allowed here in python/includes-globbed/servers/server2.conf:1","line":1},{"file":"python/includes-globbed/servers/server2.conf","error":"\"listen\" directive is not allowed here in python/includes-globbed/servers/server2.conf:2","line":2},{"file":"python/includes-globbed/servers/locations/not-included.conf","error":"","line":null}],"config":[{"file":"python/includes-globbed/servers/server2.conf","status":"failed","errors":[{"error":"\"server\" directive is not allowed here in python/includes-globbed/servers/server2.conf:1","line":1},{"error":"\"listen\" directive is not allowed here in python/includes-globbed/servers/server2.conf:2","line":2}],"parsed":[{"directive":"include","line":3,"args":["locations/*.conf"],"includes":[1]}]},{"file":"python/includes-globbed/servers/locations/not-included.conf","status":"failed","errors":[{"error":"","line":null}],"parsed":[]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/includes-globbed/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/includes-globbed/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [] 14 | }, 15 | { 16 | "directive": "include", 17 | "line": 2, 18 | "args": [ 19 | "http.conf" 20 | ], 21 | "includes": [ 22 | 1 23 | ] 24 | } 25 | ] 26 | }, 27 | { 28 | "file": "testdata/configs/includes-globbed/http.conf", 29 | "status": "ok", 30 | "errors": [], 31 | "parsed": [ 32 | { 33 | "directive": "http", 34 | "line": 1, 35 | "args": [], 36 | "block": [ 37 | { 38 | "directive": "include", 39 | "line": 2, 40 | "args": [ 41 | "servers/*.conf" 42 | ], 43 | "includes": [ 44 | 2, 45 | 3 46 | ] 47 | } 48 | ] 49 | } 50 | ] 51 | }, 52 | { 53 | "file": "testdata/configs/includes-globbed/servers/server1.conf", 54 | "status": "ok", 55 | "errors": [], 56 | "parsed": [ 57 | { 58 | "directive": "server", 59 | "line": 1, 60 | "args": [], 61 | "block": [ 62 | { 63 | "directive": "listen", 64 | "line": 2, 65 | "args": [ 66 | "8080" 67 | ] 68 | }, 69 | { 70 | "directive": "include", 71 | "line": 3, 72 | "args": [ 73 | "locations/*.conf" 74 | ], 75 | "includes": [ 76 | 4, 77 | 5 78 | ] 79 | } 80 | ] 81 | } 82 | ] 83 | }, 84 | { 85 | "file": "testdata/configs/includes-globbed/servers/server2.conf", 86 | "status": "ok", 87 | "errors": [], 88 | "parsed": [ 89 | { 90 | "directive": "server", 91 | "line": 1, 92 | "args": [], 93 | "block": [ 94 | { 95 | "directive": "listen", 96 | "line": 2, 97 | "args": [ 98 | "8081" 99 | ] 100 | }, 101 | { 102 | "directive": "include", 103 | "line": 3, 104 | "args": [ 105 | "locations/*.conf" 106 | ], 107 | "includes": [ 108 | 4, 109 | 5 110 | ] 111 | } 112 | ] 113 | } 114 | ] 115 | }, 116 | { 117 | "file": "testdata/configs/includes-globbed/locations/location1.conf", 118 | "status": "ok", 119 | "errors": [], 120 | "parsed": [ 121 | { 122 | "directive": "location", 123 | "line": 1, 124 | "args": [ 125 | "/foo" 126 | ], 127 | "block": [ 128 | { 129 | "directive": "return", 130 | "line": 2, 131 | "args": [ 132 | "200", 133 | "foo" 134 | ] 135 | } 136 | ] 137 | } 138 | ] 139 | }, 140 | { 141 | "file": "testdata/configs/includes-globbed/locations/location2.conf", 142 | "status": "ok", 143 | "errors": [], 144 | "parsed": [ 145 | { 146 | "directive": "location", 147 | "line": 1, 148 | "args": [ 149 | "/bar" 150 | ], 151 | "block": [ 152 | { 153 | "directive": "return", 154 | "line": 2, 155 | "args": [ 156 | "200", 157 | "bar" 158 | ] 159 | } 160 | ] 161 | } 162 | ] 163 | } 164 | ] 165 | } 166 | -------------------------------------------------------------------------------- /testdata/configs/includes-regular/conf.d/bar.conf: -------------------------------------------------------------------------------- 1 | # this file should never be included 2 | asdfasdfasdfasdfasdfasdfasdfasdfasdf 3 | -------------------------------------------------------------------------------- /testdata/configs/includes-regular/conf.d/details.conf: -------------------------------------------------------------------------------- 1 | 2 | # imported (details.conf) into server block 3 | 4 | server_tokens off; 5 | tcp_nodelay off; 6 | 7 | # and that's all for details.conf 8 | -------------------------------------------------------------------------------- /testdata/configs/includes-regular/conf.d/foo.conf: -------------------------------------------------------------------------------- 1 | # this file should never be included 2 | asdfasdfasdfasdfasdfasdfasdfasdfasdf 3 | -------------------------------------------------------------------------------- /testdata/configs/includes-regular/conf.d/http-inner.conf: -------------------------------------------------------------------------------- 1 | 2 | # this file is "conf.d/http-inner.conf", loaded in as an include under main http 3 | 4 | allow localhost; 5 | deny 192.168.1.0/24; 6 | 7 | # let's delete this as a test 8 | expires max; 9 | 10 | # end of conf.d/http-inner.conf (but still under http block) 11 | -------------------------------------------------------------------------------- /testdata/configs/includes-regular/conf.d/server.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 127.0.0.1:8080; 3 | server_name default_server; 4 | include foo.conf; 5 | include bar.conf; 6 | } 7 | -------------------------------------------------------------------------------- /testdata/configs/includes-regular/foo.conf: -------------------------------------------------------------------------------- 1 | location /foo { 2 | return 200 'foo'; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/includes-regular/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | http { 3 | include conf.d/server.conf; 4 | } 5 | -------------------------------------------------------------------------------- /testdata/configs/invalid-map/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | } 3 | http { 4 | map $http_user_agent $mobile { 5 | default 0; 6 | '~Opera Mini' 1; 7 | i_am_lost { 8 | return 500; 9 | } 10 | too many params; 11 | } 12 | 13 | charset_map koi8-r utf-8 { 14 | C0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/large-config/nginx.conf.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nginxinc/nginx-go-crossplane/572130cfdf1fbfd5714d93c36855c010c4656b54/testdata/configs/large-config/nginx.conf.bz2 -------------------------------------------------------------------------------- /testdata/configs/limit-req-zone/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes auto; 3 | 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | 7 | events { 8 | worker_connections 1024; 9 | } 10 | 11 | http { 12 | include /etc/nginx/mime.types; 13 | default_type application/octet-stream; 14 | 15 | limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s sync; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | 25 | keepalive_timeout 65; 26 | } -------------------------------------------------------------------------------- /testdata/configs/lua-basic/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | init_by_lua ' 3 | print("I need no extra escaping here, for example: \r\nblah") 4 | '; 5 | lua_shared_dict dogs 1m; 6 | server { 7 | listen 8080; 8 | location / { 9 | set_by_lua $res ' return 32 + math.cos(32) '; 10 | access_by_lua_file /path/to/lua/access.lua; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/lua-basic/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/lua-block-larger/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "init_by_lua", 17 | "line": 2, 18 | "args": [ 19 | "\n print(\"I need no extra escaping here, for example: \\r\\nblah\")\n " 20 | ] 21 | }, 22 | { 23 | "directive": "lua_shared_dict", 24 | "line": 5, 25 | "args": [ 26 | "dogs", 27 | "1m" 28 | ] 29 | }, 30 | { 31 | "directive": "server", 32 | "line": 6, 33 | "args": [], 34 | "block": [ 35 | { 36 | "directive": "listen", 37 | "line": 7, 38 | "args": [ 39 | "8080" 40 | ] 41 | }, 42 | { 43 | "directive": "location", 44 | "line": 8, 45 | "args": [ 46 | "/" 47 | ], 48 | "block": [ 49 | { 50 | "directive": "set_by_lua", 51 | "line": 9, 52 | "args": [ 53 | "$res", 54 | " return 32 + math.cos(32) " 55 | ] 56 | }, 57 | { 58 | "directive": "access_by_lua_file", 59 | "line": 10, 60 | "args": [ 61 | "/path/to/lua/access.lua" 62 | ] 63 | } 64 | ] 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /testdata/configs/lua-basic/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/lua-block-larger/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "init_by_lua", 17 | "line": 2, 18 | "args": [ 19 | "\n print(\"I need no extra escaping here, for example: \\r\\nblah\")\n " 20 | ] 21 | }, 22 | { 23 | "directive": "lua_shared_dict", 24 | "line": 5, 25 | "args": [ 26 | "dogs", 27 | "1m" 28 | ] 29 | }, 30 | { 31 | "directive": "server", 32 | "line": 6, 33 | "args": [], 34 | "block": [ 35 | { 36 | "directive": "listen", 37 | "line": 7, 38 | "args": [ 39 | "8080" 40 | ] 41 | }, 42 | { 43 | "directive": "location", 44 | "line": 8, 45 | "args": [ 46 | "/" 47 | ], 48 | "block": [ 49 | { 50 | "directive": "set_by_lua", 51 | "line": 9, 52 | "args": [ 53 | "$res", 54 | " return 32 + math.cos(32) " 55 | ] 56 | }, 57 | { 58 | "directive": "access_by_lua_file", 59 | "line": 10, 60 | "args": [ 61 | "/path/to/lua/access.lua" 62 | ] 63 | } 64 | ] 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-larger/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | access_by_lua_block { 3 | -- check the client IP address is in our black list 4 | if ngx.var.remote_addr == "132.5.72.3" then 5 | ngx.exit(ngx.HTTP_FORBIDDEN) 6 | end 7 | 8 | -- check if the URI contains bad words 9 | if ngx.var.uri and 10 | string.match(ngx.var.request_body, "evil") 11 | then 12 | return ngx.redirect("/terms_of_use.html") 13 | end 14 | 15 | -- tests passed 16 | } 17 | server { 18 | listen 127.0.0.1:8080; 19 | location / { 20 | content_by_lua_block { 21 | ngx.req.read_body() -- explicitly read the req body 22 | local data = ngx.req.get_body_data() 23 | if data then 24 | ngx.say("body data:") 25 | ngx.print(data) 26 | return 27 | end 28 | 29 | -- body may get buffered in a temp file: 30 | local file = ngx.req.get_body_file() 31 | if file then 32 | ngx.say("body is in file ", file) 33 | else 34 | ngx.say("no body found") 35 | end 36 | } 37 | return 200 "foo bar baz"; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-larger/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/lua-block-larger/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "access_by_lua_block", 17 | "line": 2, 18 | "args": [ 19 | "\n -- check the client IP address is in our black list\n if ngx.var.remote_addr == \"132.5.72.3\" then\n ngx.exit(ngx.HTTP_FORBIDDEN)\n end\n\n -- check if the URI contains bad words\n if ngx.var.uri and\n string.match(ngx.var.request_body, \"evil\")\n then\n return ngx.redirect(\"/terms_of_use.html\")\n end\n\n -- tests passed\n " 20 | ] 21 | }, 22 | { 23 | "directive": "server", 24 | "line": 17, 25 | "args": [], 26 | "block": [ 27 | { 28 | "directive": "listen", 29 | "line": 18, 30 | "args": [ 31 | "127.0.0.1:8080" 32 | ] 33 | }, 34 | { 35 | "directive": "location", 36 | "line": 19, 37 | "args": [ 38 | "/" 39 | ], 40 | "block": [ 41 | { 42 | "directive": "content_by_lua_block", 43 | "line": 20, 44 | "args": [ 45 | "\n ngx.req.read_body() -- explicitly read the req body\n ocal data = ngx.req.get_body_data()\n if data then\n ngx.say(\"body data:\")\n ngx.print(data)\n return\n end\n\n -- body may get buffered in a temp file:\n local file = ngx.req.get_body_file()\n if file then\n ngx.say(\"body is in file \", file)\n else\n ngx.say(\"no body found\")\n end\n " 46 | ] 47 | }, 48 | { 49 | "directive": "return", 50 | "line": 37, 51 | "args": [ 52 | "200", 53 | "foo bar baz" 54 | ] 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-larger/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/lua-block-larger/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "access_by_lua_block", 17 | "line": 2, 18 | "args": [ 19 | "\n -- check the client IP address is in our black list\n if ngx.var.remote_addr == \"132.5.72.3\" then\n ngx.exit(ngx.HTTP_FORBIDDEN)\n end\n\n -- check if the URI contains bad words\n if ngx.var.uri and\n string.match(ngx.var.request_body, \"evil\")\n then\n return ngx.redirect(\"/terms_of_use.html\")\n end\n\n -- tests passed\n " 20 | ] 21 | }, 22 | { 23 | "directive": "server", 24 | "line": 17, 25 | "args": [], 26 | "block": [ 27 | { 28 | "directive": "listen", 29 | "line": 18, 30 | "args": [ 31 | "127.0.0.1:8080" 32 | ] 33 | }, 34 | { 35 | "directive": "location", 36 | "line": 19, 37 | "args": [ 38 | "/" 39 | ], 40 | "block": [ 41 | { 42 | "directive": "content_by_lua_block", 43 | "line": 20, 44 | "args": [ 45 | "\n ngx.req.read_body() -- explicitly read the req body\n ocal data = ngx.req.get_body_data()\n if data then\n ngx.say(\"body data:\")\n ngx.print(data)\n return\n end\n\n -- body may get buffered in a temp file:\n local file = ngx.req.get_body_file()\n if file then\n ngx.say(\"body is in file \", file)\n else\n ngx.say(\"no body found\")\n end\n " 46 | ] 47 | }, 48 | { 49 | "directive": "return", 50 | "line": 37, 51 | "args": [ 52 | "200", 53 | "foo bar baz" 54 | ] 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-simple/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | init_by_lua_block { 3 | print("Lua block code with curly brace str {") 4 | } 5 | init_worker_by_lua_block { 6 | print("Work that every worker") 7 | } 8 | body_filter_by_lua_block { 9 | local data, eof = ngx.arg[1], ngx.arg[2] 10 | } 11 | header_filter_by_lua_block { 12 | ngx.header["content-length"] = nil 13 | } 14 | server { 15 | listen 127.0.0.1:8080; 16 | location / { 17 | content_by_lua_block { 18 | ngx.say("I need no extra escaping here, for example: \r\nblah") 19 | } 20 | return 200 "foo bar baz"; 21 | } 22 | ssl_certificate_by_lua_block { 23 | print("About to initiate a new SSL handshake!") 24 | } 25 | log_by_lua_block { 26 | print("I need no extra escaping here, for example: \r\nblah") 27 | } 28 | location /a { 29 | client_max_body_size 100k; 30 | client_body_buffer_size 100k; 31 | } 32 | } 33 | 34 | upstream foo { 35 | server 127.0.0.1; 36 | balancer_by_lua_block { 37 | -- use Lua to do something interesting here 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-simple/simple.conf: -------------------------------------------------------------------------------- 1 | http { 2 | init_by_lua_block { 3 | print("Lua block code with a line") 4 | print("Lua block code with another line") 5 | } 6 | init_worker_by_lua_block { 7 | print("Work that every worker") 8 | } 9 | body_filter_by_lua_block { 10 | local data, eof = ngx.arg[1], ngx.arg[2] 11 | } 12 | header_filter_by_lua_block { 13 | ngx.header["content-length"] = nil 14 | } 15 | server { 16 | listen 127.0.0.1:8080; 17 | location / { 18 | content_by_lua_block { 19 | ngx.say("I need no extra escaping here, for example: \r\nblah") 20 | } 21 | return 200 "foo bar baz"; 22 | } 23 | ssl_certificate_by_lua_block { 24 | print("About to initiate a new SSL handshake!") 25 | } 26 | location /a { 27 | client_max_body_size 100k; 28 | client_body_buffer_size 100k; 29 | } 30 | } 31 | 32 | upstream foo { 33 | server 127.0.0.1; 34 | balancer_by_lua_block { 35 | -- use Lua that'll do something interesting here with external bracket for testing { 36 | } 37 | log_by_lua_block { 38 | print("I need no extra escaping here, for example: \r\nblah") 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-tricky/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | listen 127.0.0.1:8080; 4 | server_name content_by_lua_block ; # make sure this doesn't trip up lexers 5 | set_by_lua_block $res { -- irregular lua block directive 6 | local a = 32 7 | local b = 56 8 | 9 | ngx.var.diff = a - b; -- write to $diff directly 10 | return a + b; -- return the $sum value normally 11 | } 12 | "rewrite_by_lua_block" { -- have valid braces in Lua code and quotes around directive 13 | do_something("hello, world!\nhiya\n") 14 | a = { 1, 2, 3 } 15 | btn = iup.button({title="ok"}) 16 | } 17 | } 18 | upstream content_by_lua_block { 19 | # stuff 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-tricky/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/lua-block-tricky/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "server", 17 | "line": 2, 18 | "args": [], 19 | "block": [ 20 | { 21 | "directive": "listen", 22 | "line": 3, 23 | "args": [ 24 | "127.0.0.1:8080" 25 | ] 26 | }, 27 | { 28 | "directive": "server_name", 29 | "line": 4, 30 | "args": [ 31 | "content_by_lua_block" 32 | ] 33 | }, 34 | { 35 | "directive": "#", 36 | "line": 4, 37 | "args": [], 38 | "comment": " make sure this doesn't trip up lexers" 39 | }, 40 | { 41 | "directive": "set_by_lua_block", 42 | "line": 5, 43 | "args": [ 44 | "$res", 45 | " -- irregular lua block directive\n local a = 32\n local b = 56\n\n ngx.var.diff = a - b; -- write to $diff directly\n return a + b; -- return the $sum value normally\n " 46 | ] 47 | }, 48 | { 49 | "directive": "rewrite_by_lua_block", 50 | "line": 12, 51 | "args": [ 52 | " -- have valid braces in Lua code and quotes around directive\n do_something(\"hello, world!\\nhiya\\n\")\n a = { 1, 2, 3 }\n btn = iup.button({title=\"ok\"})\n " 53 | ] 54 | } 55 | ] 56 | }, 57 | { 58 | "directive": "upstream", 59 | "line": 18, 60 | "args": [ 61 | "content_by_lua_block" 62 | ], 63 | "block": [ 64 | { 65 | "directive": "#", 66 | "line": 19, 67 | "args": [], 68 | "comment": " stuff" 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /testdata/configs/lua-block-tricky/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/lua-block-tricky/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "http", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "server", 17 | "line": 2, 18 | "args": [], 19 | "block": [ 20 | { 21 | "directive": "listen", 22 | "line": 3, 23 | "args": [ 24 | "127.0.0.1:8080" 25 | ] 26 | }, 27 | { 28 | "directive": "server_name", 29 | "line": 4, 30 | "args": [ 31 | "content_by_lua_block" 32 | ] 33 | }, 34 | { 35 | "directive": "#", 36 | "line": 4, 37 | "args": [], 38 | "comment": " make sure this doesn't trip up lexers" 39 | }, 40 | { 41 | "directive": "set_by_lua_block $res { -- irregular lua block directive\n local a = 32\n local b = 56\n\n ngx.var.diff = a - b; -- write to $diff directly\n return a + b; -- return the $sum value normally\n }\n \"rewrite_by_lua_block\" { -- have valid braces in Lua code and quotes around directive\n do_something(\"hello, world!\\nhiya\\n\")\n a = { 1, 2, 3 }\n btn = iup.button({title=\"ok\"})\n }\n ", 42 | "line": 17, 43 | "args": [] 44 | }, 45 | { 46 | "directive": "upstream", 47 | "line": 18, 48 | "args": [ 49 | "content_by_lua_block", 50 | "\n # stuff\n " 51 | ] 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | ] 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /testdata/configs/master.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # build reference payloads from python, 4 | # assumes crossplane is installed and in your path 5 | cd $(dirname $0)/.. 6 | for file in $(find python -name \*.conf) 7 | do 8 | into=${file%.*}.json 9 | echo crossplane parse $file $into 10 | crossplane parse $file > $into 11 | done 12 | -------------------------------------------------------------------------------- /testdata/configs/messy/nginx.conf: -------------------------------------------------------------------------------- 1 | user nobody; 2 | # hello\n\\n\\\n worlddd \#\\#\\\# dfsf\n \\n \\\n \ 3 | "events" { "worker_connections" "2048"; } 4 | 5 | "http" {#forteen 6 | # this is a comment 7 | "access_log" off;default_type "text/plain"; error_log "off"; 8 | server { 9 | "listen" "8083" ; 10 | "return" 200 "Ser\" ' ' ver\\ \ $server_addr:\$server_port\n\nTime: $time_local\n\n"; 11 | } 12 | "server" {"listen" 8080; 13 | 'root' /usr/share/nginx/html; 14 | location ~ "/hello/world;"{"return" 301 /status.html;} 15 | location /foo{}location /bar{} 16 | location /\{\;\}\ #\ ab {}# hello 17 | if ($request_method = P\{O\)\###\;ST ){} 18 | location "/status.html" { 19 | try_files /abc/${uri} /abc/${uri}.html =404 ; 20 | } 21 | "location" "/sta; 22 | tus" {"return" 302 /status.html;} 23 | "location" /upstream_conf { "return" 200 /status.html; }} 24 | server 25 | {}} 26 | -------------------------------------------------------------------------------- /testdata/configs/messy/off: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nginxinc/nginx-go-crossplane/572130cfdf1fbfd5714d93c36855c010c4656b54/testdata/configs/messy/off -------------------------------------------------------------------------------- /testdata/configs/missing-semicolon-above/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | location /is-broken { 4 | proxy_pass http://is.broken.example 5 | } 6 | location /not-broken { 7 | proxy_pass http://not.broken.example; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/missing-semicolon-below/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | location /not-broken { 4 | proxy_pass http://not.broken.example; 5 | } 6 | location /is-broken { 7 | proxy_pass http://is.broken.example 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/missing-semicolon/broken-above.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | location /is-broken { 4 | proxy_pass http://is.broken.example 5 | } 6 | location /not-broken { 7 | proxy_pass http://not.broken.example; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/missing-semicolon/broken-above.json: -------------------------------------------------------------------------------- 1 | {"status":"failed","errors":[{"file":"python/missing-semicolon/broken-above.conf","error":"directive \"proxy_pass\" is not terminated by \";\" in python/missing-semicolon/broken-above.conf:4","line":4}],"config":[{"file":"python/missing-semicolon/broken-above.conf","status":"failed","errors":[{"error":"directive \"proxy_pass\" is not terminated by \";\" in python/missing-semicolon/broken-above.conf:4","line":4}],"parsed":[{"directive":"http","line":1,"args":[],"block":[{"directive":"server","line":2,"args":[],"block":[{"directive":"location","line":3,"args":["/is-broken"],"block":[]},{"directive":"location","line":6,"args":["/not-broken"],"block":[{"directive":"proxy_pass","line":7,"args":["http://not.broken.example"]}]}]}]}]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/missing-semicolon/broken-below.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | location /not-broken { 4 | proxy_pass http://not.broken.example; 5 | } 6 | location /is-broken { 7 | proxy_pass http://is.broken.example 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/missing-semicolon/broken-below.json: -------------------------------------------------------------------------------- 1 | {"status":"failed","errors":[{"file":"python/missing-semicolon/broken-below.conf","error":"directive \"proxy_pass\" is not terminated by \";\" in python/missing-semicolon/broken-below.conf:7","line":7}],"config":[{"file":"python/missing-semicolon/broken-below.conf","status":"failed","errors":[{"error":"directive \"proxy_pass\" is not terminated by \";\" in python/missing-semicolon/broken-below.conf:7","line":7}],"parsed":[{"directive":"http","line":1,"args":[],"block":[{"directive":"server","line":2,"args":[],"block":[{"directive":"location","line":3,"args":["/not-broken"],"block":[{"directive":"proxy_pass","line":4,"args":["http://not.broken.example"]}]},{"directive":"location","line":6,"args":["/is-broken"],"block":[]}]}]}]}]} 2 | -------------------------------------------------------------------------------- /testdata/configs/nap-waf-v4/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes 4; 3 | 4 | load_module modules/ngx_http_app_protect_module.so; 5 | 6 | error_log /var/log/nginx/error.log debug; 7 | 8 | events { 9 | worker_connections 65536; 10 | } 11 | 12 | http { 13 | include /etc/nginx/mime.types; 14 | default_type application/octet-stream; 15 | sendfile on; 16 | keepalive_timeout 65; 17 | 18 | app_protect_enable on; # This is how you enable NGINX App Protect WAF in the relevant context/block 19 | app_protect_policy_file "/etc/app_protect/conf/NginxDefaultPolicy.json"; # This is a reference to the policy file to use. If not defined, the default policy is used 20 | app_protect_security_log_enable on; # This section enables the logging capability 21 | app_protect_security_log "/etc/app_protect/conf/log_default.json" syslog:server=127.0.0.1:515; # This is where the remote logger is defined in terms of: logging options (defined in the referenced file), log server IP, log server port 22 | 23 | server { 24 | listen 80; 25 | server_name localhost; 26 | proxy_http_version 1.1; 27 | 28 | location / { 29 | client_max_body_size 0; 30 | default_type text/html; 31 | proxy_pass http://172.29.38.211:80$request_uri; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /testdata/configs/nap-waf-v5/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes 4; 3 | 4 | load_module modules/ngx_http_app_protect_module.so; 5 | 6 | error_log /var/log/nginx/error.log debug; 7 | 8 | events { 9 | worker_connections 65536; 10 | } 11 | 12 | http { 13 | include /etc/nginx/mime.types; 14 | default_type application/octet-stream; 15 | sendfile on; 16 | keepalive_timeout 65; 17 | 18 | app_protect_enforcer_address 127.0.0.1:50000; 19 | app_protect_enable on; # This is how you enable NGINX App Protect WAF in the relevant context/block 20 | app_protect_policy_file "/policies/policy1.tgz"; # This is a reference to the policy bundle file to use. If not defined, the default policy is used 21 | app_protect_security_log_enable on; # This section enables the logging capability 22 | app_protect_security_log log_all syslog:server=127.0.0.1:515; # This is where the remote logger is defined in terms of: logging options (defined in the referenced file), log server IP, log server port 23 | 24 | server { 25 | listen 80; 26 | server_name localhost; 27 | proxy_http_version 1.1; 28 | 29 | location / { 30 | client_max_body_size 0; 31 | default_type text/html; 32 | proxy_pass http://172.29.38.211/; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /testdata/configs/premature-eof/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | listen -------------------------------------------------------------------------------- /testdata/configs/quote-behavior/nginx.conf: -------------------------------------------------------------------------------- 1 | "outer-quote" "left"-quote right-"quote" inner"-"quote; 2 | "" ""left-empty right-empty"" inner""empty right-empty-single"; 3 | -------------------------------------------------------------------------------- /testdata/configs/quote-behavior/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/quote-behavior/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "outer-quote", 12 | "line": 1, 13 | "args": [ 14 | "left", 15 | "-quote", 16 | "right-\"quote\"", 17 | "inner\"-\"quote" 18 | ] 19 | }, 20 | { 21 | "directive": "", 22 | "line": 2, 23 | "args": [ 24 | "", 25 | "left-empty", 26 | "right-empty\"\"", 27 | "inner\"\"empty", 28 | "right-empty-single\"" 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /testdata/configs/quote-behavior/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/quote-behavior/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "outer-quote", 12 | "line": 1, 13 | "args": [ 14 | "left", 15 | "-quote", 16 | "right-\"quote\"", 17 | "inner\"-\"quote" 18 | ] 19 | }, 20 | { 21 | "directive": "", 22 | "line": 2, 23 | "args": [ 24 | "", 25 | "left-empty", 26 | "right-empty\"\"", 27 | "inner\"\"empty", 28 | "right-empty-single\"" 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /testdata/configs/quoted-right-brace/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | http { 3 | log_format main escape=json 4 | '{ "@timestamp": "$time_iso8601", ' 5 | '"server_name": "$server_name", ' 6 | '"host": "$host", ' 7 | '"status": "$status", ' 8 | '"request": "$request", ' 9 | '"uri": "$uri", ' 10 | '"args": "$args", ' 11 | '"https": "$https", ' 12 | '"request_method": "$request_method", ' 13 | '"referer": "$http_referer", ' 14 | '"agent": "$http_user_agent"' 15 | '}'; 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/quoted-right-brace/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/quoted-right-brace/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [] 15 | }, 16 | { 17 | "directive": "http", 18 | "line": 2, 19 | "args": [], 20 | "block": [ 21 | { 22 | "directive": "log_format", 23 | "line": 3, 24 | "args": [ 25 | "main", 26 | "escape=json", 27 | "{ \"@timestamp\": \"$time_iso8601\", ", 28 | "\"server_name\": \"$server_name\", ", 29 | "\"host\": \"$host\", ", 30 | "\"status\": \"$status\", ", 31 | "\"request\": \"$request\", ", 32 | "\"uri\": \"$uri\", ", 33 | "\"args\": \"$args\", ", 34 | "\"https\": \"$https\", ", 35 | "\"request_method\": \"$request_method\", ", 36 | "\"referer\": \"$http_referer\", ", 37 | "\"agent\": \"$http_user_agent\"", 38 | "}" 39 | ] 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /testdata/configs/quoted-right-brace/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/quoted-right-brace/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [] 14 | }, 15 | { 16 | "directive": "http", 17 | "line": 2, 18 | "args": [], 19 | "block": [ 20 | { 21 | "directive": "log_format", 22 | "line": 3, 23 | "args": [ 24 | "main", 25 | "escape=json", 26 | "{ \"@timestamp\": \"$time_iso8601\", ", 27 | "\"server_name\": \"$server_name\", ", 28 | "\"host\": \"$host\", ", 29 | "\"status\": \"$status\", ", 30 | "\"request\": \"$request\", ", 31 | "\"uri\": \"$uri\", ", 32 | "\"args\": \"$args\", ", 33 | "\"https\": \"$https\", ", 34 | "\"request_method\": \"$request_method\", ", 35 | "\"referer\": \"$http_referer\", ", 36 | "\"agent\": \"$http_user_agent\"", 37 | "}" 38 | ] 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /testdata/configs/returns/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | events {} 3 | 4 | http { 5 | server { 6 | listen 8083; 7 | location ~ "/hello/world;"{ 8 | return 301 /status.html; 9 | } 10 | if ($request_method = P\{O\)\###\;ST ){} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /testdata/configs/returns/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/returns/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "user", 12 | "line": 1, 13 | "args": [ 14 | "nginx" 15 | ] 16 | }, 17 | { 18 | "directive": "events", 19 | "line": 2, 20 | "args": [], 21 | "block": [] 22 | }, 23 | { 24 | "directive": "http", 25 | "line": 4, 26 | "args": [], 27 | "block": [ 28 | { 29 | "directive": "server", 30 | "line": 5, 31 | "args": [], 32 | "block": [ 33 | { 34 | "directive": "listen", 35 | "line": 6, 36 | "args": [ 37 | "8083" 38 | ] 39 | }, 40 | { 41 | "directive": "location", 42 | "line": 7, 43 | "args": [ 44 | "~", 45 | "/hello/world;" 46 | ], 47 | "block": [ 48 | { 49 | "directive": "return", 50 | "line": 8, 51 | "args": [ 52 | "301", 53 | "/status.html" 54 | ] 55 | } 56 | ] 57 | }, 58 | { 59 | "directive": "if", 60 | "line": 10, 61 | "args": [ 62 | "$request_method", 63 | "=", 64 | "P\\{O\\)\\###\\;ST" 65 | ], 66 | "block": [] 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /testdata/configs/russian-text/nginx.conf: -------------------------------------------------------------------------------- 1 | env 'русский текст'; 2 | events {} 3 | -------------------------------------------------------------------------------- /testdata/configs/russian-text/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/russian-text/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "env", 12 | "line": 1, 13 | "args": [ 14 | "русский текст" 15 | ] 16 | }, 17 | { 18 | "directive": "events", 19 | "line": 2, 20 | "args": [], 21 | "block": [] 22 | } 23 | ] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /testdata/configs/russian-text/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/russian-text/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "env", 12 | "line": 1, 13 | "args": [ 14 | "русский текст" 15 | ] 16 | }, 17 | { 18 | "directive": "events", 19 | "line": 2, 20 | "args": [] 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /testdata/configs/simple-variable-with-braces/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | location /proxy { 10 | set $backend_protocol http; 11 | set $backend_host bar; 12 | set $foo ''; 13 | proxy_pass $backend_protocol://$backend_host${foo}; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/simple/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | location / { 10 | return 200 "foo bar baz"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/simple/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/simple/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "worker_connections", 17 | "line": 2, 18 | "args": [ 19 | "1024" 20 | ] 21 | } 22 | ] 23 | }, 24 | { 25 | "directive": "http", 26 | "line": 5, 27 | "args": [], 28 | "block": [ 29 | { 30 | "directive": "server", 31 | "line": 6, 32 | "args": [], 33 | "block": [ 34 | { 35 | "directive": "listen", 36 | "line": 7, 37 | "args": [ 38 | "127.0.0.1:8080" 39 | ] 40 | }, 41 | { 42 | "directive": "server_name", 43 | "line": 8, 44 | "args": [ 45 | "default_server" 46 | ] 47 | }, 48 | { 49 | "directive": "location", 50 | "line": 9, 51 | "args": [ 52 | "/" 53 | ], 54 | "block": [ 55 | { 56 | "directive": "return", 57 | "line": 10, 58 | "args": [ 59 | "200", 60 | "foo bar baz" 61 | ] 62 | } 63 | ] 64 | } 65 | ] 66 | } 67 | ] 68 | } 69 | ] 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /testdata/configs/simple/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/simple/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "worker_connections", 17 | "line": 2, 18 | "args": [ 19 | "1024" 20 | ] 21 | } 22 | ] 23 | }, 24 | { 25 | "directive": "http", 26 | "line": 5, 27 | "args": [], 28 | "block": [ 29 | { 30 | "directive": "server", 31 | "line": 6, 32 | "args": [], 33 | "block": [ 34 | { 35 | "directive": "listen", 36 | "line": 7, 37 | "args": [ 38 | "127.0.0.1:8080" 39 | ] 40 | }, 41 | { 42 | "directive": "server_name", 43 | "line": 8, 44 | "args": [ 45 | "default_server" 46 | ] 47 | }, 48 | { 49 | "directive": "location", 50 | "line": 9, 51 | "args": [ 52 | "/" 53 | ], 54 | "block": [ 55 | { 56 | "directive": "return", 57 | "line": 10, 58 | "args": [ 59 | "200", 60 | "foo bar baz" 61 | ] 62 | } 63 | ] 64 | } 65 | ] 66 | } 67 | ] 68 | } 69 | ] 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /testdata/configs/spelling-mistake/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | 3 | http { 4 | server { 5 | location / { 6 | #directive is misspelled 7 | proxy_passs http://foo.bar; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/spelling-mistake/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/spelling-mistake/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [] 15 | }, 16 | { 17 | "directive": "http", 18 | "line": 3, 19 | "args": [], 20 | "block": [ 21 | { 22 | "directive": "server", 23 | "line": 4, 24 | "args": [], 25 | "block": [ 26 | { 27 | "directive": "location", 28 | "line": 5, 29 | "args": [ 30 | "/" 31 | ], 32 | "block": [ 33 | { 34 | "directive": "#", 35 | "line": 6, 36 | "args": [], 37 | "comment": "directive is misspelled" 38 | }, 39 | { 40 | "directive": "proxy_passs", 41 | "line": 7, 42 | "args": [ 43 | "http://foo.bar" 44 | ] 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | ] 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /testdata/configs/testdata/braces/extra-brace.conf: -------------------------------------------------------------------------------- 1 | # Generated by NGINX Controller 2021-02-01 17:36:11.009002952 +0000 UTC m=+230.885274373; 2 | user nginx; 3 | worker_processes auto; 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | load_module modules/ngx_http_f5_metrics_module.so; 7 | events { 8 | worker_connections 1024; 9 | 10 | ##### Extra brace 11 | }} 12 | 13 | 14 | http { 15 | server { 16 | server_name 127.0.0.1; 17 | listen 127.0.0.1:49151; 18 | access_log off; 19 | f5_metrics off; 20 | location /api { 21 | api; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /testdata/configs/testdata/braces/missing-brace.conf: -------------------------------------------------------------------------------- 1 | # Generated by NGINX Controller 2021-02-01 17:36:11.009002952 +0000 UTC m=+230.885274373; 2 | user nginx; 3 | worker_processes auto; 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | load_module modules/ngx_http_f5_metrics_module.so; 7 | events { 8 | worker_connections 1024; 9 | 10 | } 11 | 12 | http { 13 | server { 14 | server_name 127.0.0.1; 15 | listen 127.0.0.1:49151; 16 | access_log off; 17 | f5_metrics off; 18 | location /api { 19 | api; 20 | } 21 | } 22 | ### Missing brace below 23 | -------------------------------------------------------------------------------- /testdata/configs/testdata/broken1/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | 3 | http { 4 | server { 5 | server_name ${url ; 6 | } 7 | } -------------------------------------------------------------------------------- /testdata/configs/testdata/broken1/nginx2.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | 3 | http { 4 | server { 5 | server_name# ${url ; 6 | } 7 | } -------------------------------------------------------------------------------- /testdata/configs/testdata/comments-between-args/nginx.conf: -------------------------------------------------------------------------------- 1 | http { #comment 1 2 | log_format #comment 2 3 | \#arg\ 1 #comment 3 4 | '#arg 2' #comment 4 5 | #comment 5 6 | ; 7 | } 8 | -------------------------------------------------------------------------------- /testdata/configs/testdata/directive-with-space/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | } 3 | http { 4 | map $http_user_agent $mobile { 5 | default 0; 6 | '~Opera Mini' 1; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /testdata/configs/testdata/empty-config/nginx.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nginxinc/nginx-go-crossplane/572130cfdf1fbfd5714d93c36855c010c4656b54/testdata/configs/testdata/empty-config/nginx.conf -------------------------------------------------------------------------------- /testdata/configs/testdata/empty-value-map/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | } 3 | http { 4 | map string $variable { 5 | '' $arg; 6 | *.example.com ''; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /testdata/configs/testdata/if-expr/empty-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if () { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/if-expr/empty-spaced-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ( ) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/if-expr/missing-closing-paren.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ($slow { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/if-expr/missing-opening-paren.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if $slow) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/if-expr/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ($slow) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/if-expr/no-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if $slow { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/if-expr/spaced-parens.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | if ( $slow ) { 10 | set $var 10; 11 | } 12 | location / { 13 | return 200 "foo bar baz"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-globbed/http.conf: -------------------------------------------------------------------------------- 1 | http { 2 | include servers/*.conf; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-globbed/locations/location1.conf: -------------------------------------------------------------------------------- 1 | location /foo { 2 | return 200 'foo'; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-globbed/locations/location2.conf: -------------------------------------------------------------------------------- 1 | location /bar { 2 | return 200 'bar'; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-globbed/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | include http.conf; 3 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-globbed/servers/locations/not-included.conf: -------------------------------------------------------------------------------- 1 | # this file should never be included 2 | asdfasdfasdfasdfasdfasdfasdfasdfasdf 3 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-globbed/servers/server1.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8080; 3 | include locations/*.conf; 4 | } 5 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-globbed/servers/server2.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8081; 3 | include locations/*.conf; 4 | } 5 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-regular/conf.d/bar.conf: -------------------------------------------------------------------------------- 1 | # this file should never be included 2 | asdfasdfasdfasdfasdfasdfasdfasdfasdf 3 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-regular/conf.d/foo.conf: -------------------------------------------------------------------------------- 1 | # this file should never be included 2 | asdfasdfasdfasdfasdfasdfasdfasdfasdf 3 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-regular/conf.d/server.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 127.0.0.1:8080; 3 | server_name default_server; 4 | include foo.conf; 5 | include bar.conf; 6 | } 7 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-regular/foo.conf: -------------------------------------------------------------------------------- 1 | location /foo { 2 | return 200 'foo'; 3 | } 4 | -------------------------------------------------------------------------------- /testdata/configs/testdata/includes-regular/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | http { 3 | include conf.d/server.conf; 4 | } 5 | -------------------------------------------------------------------------------- /testdata/configs/testdata/large-config/nginx.conf.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nginxinc/nginx-go-crossplane/572130cfdf1fbfd5714d93c36855c010c4656b54/testdata/configs/testdata/large-config/nginx.conf.bz2 -------------------------------------------------------------------------------- /testdata/configs/testdata/lua-block-larger/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | content_by_lua_block { 3 | ngx.req.read_body() -- explicitly read the req body 4 | local data = ngx.req.get_body_data() 5 | if data then 6 | ngx.say("body data:") 7 | ngx.print(data) 8 | return 9 | end 10 | 11 | -- body may get buffered in a temp file: 12 | local file = ngx.req.get_body_file() 13 | if file then 14 | ngx.say("body is in file ", file) 15 | else 16 | ngx.say("no body found") 17 | end 18 | } 19 | access_by_lua_block { 20 | -- check the client IP address is in our black list 21 | if ngx.var.remote_addr == "132.5.72.3" then 22 | ngx.exit(ngx.HTTP_FORBIDDEN) 23 | end 24 | 25 | -- check if the URI contains bad words 26 | if ngx.var.uri and 27 | string.match(ngx.var.request_body, "evil") 28 | then 29 | return ngx.redirect("/terms_of_use.html") 30 | end 31 | 32 | -- tests passed 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /testdata/configs/testdata/lua-block-simple/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | init_by_lua_block { 3 | print("Lua block code with curly brace str {") 4 | } 5 | init_worker_by_lua_block { 6 | print("Work that every worker") 7 | } 8 | body_filter_by_lua_block { 9 | local data, eof = ngx.arg[1], ngx.arg[2] 10 | } 11 | header_filter_by_lua_block { 12 | ngx.header["content-length"] = nil 13 | } 14 | server { 15 | listen 127.0.0.1:8080; 16 | location / { 17 | content_by_lua_block { 18 | ngx.say("I need no extra escaping here, for example: \r\nblah") 19 | } 20 | return 200 "foo bar baz"; 21 | } 22 | ssl_certificate_by_lua_block { 23 | print("About to initiate a new SSL handshake!") 24 | } 25 | location /a { 26 | client_max_body_size 100k; 27 | client_body_buffer_size 100k; 28 | } 29 | } 30 | 31 | upstream foo { 32 | server 127.0.0.1; 33 | balancer_by_lua_block { 34 | -- use Lua to do something interesting here 35 | } 36 | log_by_lua_block { 37 | print("I need no extra escaping here, for example: \r\nblah") 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /testdata/configs/testdata/lua-block-tricky/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | listen 127.0.0.1:8080; 4 | server_name content_by_lua_block ; # make sure this doesn't trip up lexers 5 | set_by_lua_block $res { -- irregular lua block directive 6 | local a = 32 7 | local b = 56 8 | 9 | ngx.var.diff = a - b; -- write to $diff directly 10 | return a + b; -- return the $sum value normally 11 | } 12 | "rewrite_by_lua_block" { -- have valid braces in Lua code and quotes around directive 13 | do_something("hello, world!\nhiya\n") 14 | a = { 1, 2, 3 } 15 | btn = iup.button({title="ok"}) 16 | } 17 | } 18 | upstream content_by_lua_block { 19 | # stuff 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /testdata/configs/testdata/messy/nginx.conf: -------------------------------------------------------------------------------- 1 | user nobody; 2 | # hello\n\\n\\\n worlddd \#\\#\\\# dfsf\n \\n \\\n \ 3 | "events" { "worker_connections" "2048"; } 4 | 5 | "http" {#forteen 6 | # this is a comment 7 | "access_log" off;default_type "text/plain"; error_log "off"; 8 | server { 9 | "listen" "8083" ; 10 | "return" 200 "Ser\" ' ' ver\\ \ $server_addr:\$server_port\n\nTime: $time_local\n\n"; 11 | } 12 | "server" {"listen" 8080; 13 | 'root' /usr/share/nginx/html; 14 | location ~ "/hello/world;"{"return" 301 /status.html;} 15 | location /foo{}location /bar{} 16 | location /\{\;\}\ #\ ab {}# hello 17 | if ($request_method = P\{O\)\###\;ST ){} 18 | location "/status.html" { 19 | try_files /abc/${uri} /abc/${uri}.html =404 ; 20 | } 21 | "location" "/sta; 22 | tus" {"return" 302 /status.html;} 23 | "location" /upstream_conf { "return" 200 /status.html; }} 24 | server 25 | {}} 26 | -------------------------------------------------------------------------------- /testdata/configs/testdata/missing-semicolon-above/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | location /is-broken { 4 | proxy_pass http://is.broken.example 5 | } 6 | location /not-broken { 7 | proxy_pass http://not.broken.example; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/testdata/missing-semicolon-below/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | server { 3 | location /not-broken { 4 | proxy_pass http://not.broken.example; 5 | } 6 | location /is-broken { 7 | proxy_pass http://is.broken.example 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/testdata/quote-behavior/nginx.conf: -------------------------------------------------------------------------------- 1 | "outer-quote" "left"-quote right-"quote" inner"-"quote; 2 | "" ""left-empty right-empty"" inner""empty right-empty-single"; 3 | -------------------------------------------------------------------------------- /testdata/configs/testdata/quoted-right-brace/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | http { 3 | log_format main escape=json 4 | '{ "@timestamp": "$time_iso8601", ' 5 | '"server_name": "$server_name", ' 6 | '"host": "$host", ' 7 | '"status": "$status", ' 8 | '"request": "$request", ' 9 | '"uri": "$uri", ' 10 | '"args": "$args", ' 11 | '"https": "$https", ' 12 | '"request_method": "$request_method", ' 13 | '"referer": "$http_referer", ' 14 | '"agent": "$http_user_agent"' 15 | '}'; 16 | } 17 | -------------------------------------------------------------------------------- /testdata/configs/testdata/russian-text/nginx.conf: -------------------------------------------------------------------------------- 1 | env 'русский текст'; 2 | events {} 3 | -------------------------------------------------------------------------------- /testdata/configs/testdata/simple/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | location / { 10 | return 200 "foo bar baz"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/testdata/spelling-mistake/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | 3 | http { 4 | server { 5 | location / { 6 | #directive is misspelled 7 | proxy_passs http://foo.bar; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/configs/testdata/upstream_resolver_directive/multiple_resolvers.conf: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/testdata/upstream_resolver_directive/multiple_resolvers.conf.golden: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/testdata/upstream_resolver_directive/multiple_resolvers_with_ports.conf: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/testdata/upstream_resolver_directive/multiple_resolvers_with_ports.conf.golden: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/testdata/upstream_resolver_directive/simple.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | location / { 10 | return 200 "foo bar baz"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/testdata/upstream_resolver_directive/simple.conf.golden: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | location / { 10 | return 200 "foo bar baz"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/testdata/with-comments/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | #comment 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; #listen 8 | server_name default_server; 9 | location / { ## this is brace 10 | # location / 11 | return 200 "foo bar baz"; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /testdata/configs/types/nginx.conf: -------------------------------------------------------------------------------- 1 | http { 2 | types { 3 | text/html html htm shtml; 4 | text/css css; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /testdata/configs/ubuntu-default/mime.types: -------------------------------------------------------------------------------- 1 | 2 | types { 3 | text/html html htm shtml; 4 | text/css css; 5 | text/xml xml; 6 | image/gif gif; 7 | image/jpeg jpeg jpg; 8 | application/javascript js; 9 | application/atom+xml atom; 10 | application/rss+xml rss; 11 | 12 | text/mathml mml; 13 | text/plain txt; 14 | text/vnd.sun.j2me.app-descriptor jad; 15 | text/vnd.wap.wml wml; 16 | text/x-component htc; 17 | 18 | image/png png; 19 | image/tiff tif tiff; 20 | image/vnd.wap.wbmp wbmp; 21 | image/x-icon ico; 22 | image/x-jng jng; 23 | image/x-ms-bmp bmp; 24 | image/svg+xml svg svgz; 25 | image/webp webp; 26 | 27 | application/font-woff woff; 28 | application/java-archive jar war ear; 29 | application/json json; 30 | application/mac-binhex40 hqx; 31 | application/msword doc; 32 | application/pdf pdf; 33 | application/postscript ps eps ai; 34 | application/rtf rtf; 35 | application/vnd.apple.mpegurl m3u8; 36 | application/vnd.ms-excel xls; 37 | application/vnd.ms-fontobject eot; 38 | application/vnd.ms-powerpoint ppt; 39 | application/vnd.wap.wmlc wmlc; 40 | application/vnd.google-earth.kml+xml kml; 41 | application/vnd.google-earth.kmz kmz; 42 | application/x-7z-compressed 7z; 43 | application/x-cocoa cco; 44 | application/x-java-archive-diff jardiff; 45 | application/x-java-jnlp-file jnlp; 46 | application/x-makeself run; 47 | application/x-perl pl pm; 48 | application/x-pilot prc pdb; 49 | application/x-rar-compressed rar; 50 | application/x-redhat-package-manager rpm; 51 | application/x-sea sea; 52 | application/x-shockwave-flash swf; 53 | application/x-stuffit sit; 54 | application/x-tcl tcl tk; 55 | application/x-x509-ca-cert der pem crt; 56 | application/x-xpinstall xpi; 57 | application/xhtml+xml xhtml; 58 | application/xspf+xml xspf; 59 | application/zip zip; 60 | 61 | application/octet-stream bin exe dll; 62 | application/octet-stream deb; 63 | application/octet-stream dmg; 64 | application/octet-stream iso img; 65 | application/octet-stream msi msp msm; 66 | 67 | application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; 68 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; 69 | application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; 70 | 71 | audio/midi mid midi kar; 72 | audio/mpeg mp3; 73 | audio/ogg ogg; 74 | audio/x-m4a m4a; 75 | audio/x-realaudio ra; 76 | 77 | video/3gpp 3gpp 3gp; 78 | video/mp2t ts; 79 | video/mp4 mp4; 80 | video/mpeg mpeg mpg; 81 | video/quicktime mov; 82 | video/webm webm; 83 | video/x-flv flv; 84 | video/x-m4v m4v; 85 | video/x-mng mng; 86 | video/x-ms-asf asx asf; 87 | video/x-ms-wmv wmv; 88 | video/x-msvideo avi; 89 | } 90 | -------------------------------------------------------------------------------- /testdata/configs/ubuntu-default/modules-enabled/50-mod-http-image-filter.conf: -------------------------------------------------------------------------------- 1 | load_module modules/ngx_http_image_filter_module.so; 2 | -------------------------------------------------------------------------------- /testdata/configs/ubuntu-default/modules-enabled/50-mod-http-xslt-filter.conf: -------------------------------------------------------------------------------- 1 | load_module modules/ngx_http_xslt_filter_module.so; 2 | -------------------------------------------------------------------------------- /testdata/configs/ubuntu-default/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | pid /run/nginx.pid; 4 | include modules-enabled/*.conf; 5 | 6 | events { 7 | worker_connections 768; 8 | # multi_accept on; 9 | } 10 | 11 | http { 12 | 13 | ## 14 | # Basic Settings 15 | ## 16 | 17 | sendfile on; 18 | tcp_nopush on; 19 | tcp_nodelay on; 20 | keepalive_timeout 65; 21 | types_hash_max_size 2048; 22 | # server_tokens off; 23 | 24 | # server_names_hash_bucket_size 64; 25 | # server_name_in_redirect off; 26 | 27 | include mime.types; 28 | default_type application/octet-stream; 29 | 30 | ## 31 | # SSL Settings 32 | ## 33 | 34 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE 35 | ssl_prefer_server_ciphers on; 36 | 37 | ## 38 | # Logging Settings 39 | ## 40 | 41 | access_log /var/log/nginx/access.log; 42 | error_log /var/log/nginx/error.log; 43 | 44 | ## 45 | # Gzip Settings 46 | ## 47 | 48 | gzip on; 49 | 50 | # gzip_vary on; 51 | # gzip_proxied any; 52 | # gzip_comp_level 6; 53 | # gzip_buffers 16 8k; 54 | # gzip_http_version 1.1; 55 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 56 | 57 | ## 58 | # Virtual Host Configs 59 | ## 60 | 61 | include conf.d/*.conf; 62 | include sites-enabled/*; 63 | } 64 | 65 | 66 | #mail { 67 | # # See sample authentication script at: 68 | # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript 69 | # 70 | # # auth_http localhost/auth.php; 71 | # # pop3_capabilities "TOP" "USER"; 72 | # # imap_capabilities "IMAP4rev1" "UIDPLUS"; 73 | # 74 | # server { 75 | # listen localhost:110; 76 | # protocol pop3; 77 | # proxy on; 78 | # } 79 | # 80 | # server { 81 | # listen localhost:143; 82 | # protocol imap; 83 | # proxy on; 84 | # } 85 | #} 86 | -------------------------------------------------------------------------------- /testdata/configs/ubuntu-default/sites-enabled/default: -------------------------------------------------------------------------------- 1 | ## 2 | # You should look at the following URL's in order to grasp a solid understanding 3 | # of Nginx configuration files in order to fully unleash the power of Nginx. 4 | # https://www.nginx.com/resources/wiki/start/ 5 | # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ 6 | # https://wiki.debian.org/Nginx/DirectoryStructure 7 | # 8 | # In most cases, administrators will remove this file from sites-enabled/ and 9 | # leave it as reference inside of sites-available where it will continue to be 10 | # updated by the nginx packaging team. 11 | # 12 | # This file will automatically load configuration files provided by other 13 | # applications, such as Drupal or Wordpress. These applications will be made 14 | # available underneath a path with that package name, such as /drupal8. 15 | # 16 | # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. 17 | ## 18 | 19 | # Default server configuration 20 | # 21 | server { 22 | listen 80 default_server; 23 | listen [::]:80 default_server; 24 | 25 | # SSL configuration 26 | # 27 | # listen 443 ssl default_server; 28 | # listen [::]:443 ssl default_server; 29 | # 30 | # Note: You should disable gzip for SSL traffic. 31 | # See: https://bugs.debian.org/773332 32 | # 33 | # Read up on ssl_ciphers to ensure a secure configuration. 34 | # See: https://bugs.debian.org/765782 35 | # 36 | # Self signed certs generated by the ssl-cert package 37 | # Don't use them in a production server! 38 | # 39 | # include snippets/snakeoil.conf; 40 | 41 | root /var/www/html; 42 | 43 | # Add index.php to the list if you are using PHP 44 | index index.html index.htm index.nginx-debian.html; 45 | 46 | server_name _; 47 | 48 | location / { 49 | # First attempt to serve request as file, then 50 | # as directory, then fall back to displaying a 404. 51 | try_files $uri $uri/ =404; 52 | } 53 | 54 | # pass PHP scripts to FastCGI server 55 | # 56 | #location ~ \.php$ { 57 | # include snippets/fastcgi-php.conf; 58 | # 59 | # # With php-fpm (or other unix sockets): 60 | # fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; 61 | # # With php-cgi (or other tcp sockets): 62 | # fastcgi_pass 127.0.0.1:9000; 63 | #} 64 | 65 | # deny access to .htaccess files, if Apache's document root 66 | # concurs with nginx's one 67 | # 68 | #location ~ /\.ht { 69 | # deny all; 70 | #} 71 | } 72 | 73 | 74 | # Virtual Host configuration for example.com 75 | # 76 | # You can move that to a different file under sites-available/ and symlink that 77 | # to sites-enabled/ to enable it. 78 | # 79 | #server { 80 | # listen 80; 81 | # listen [::]:80; 82 | # 83 | # server_name example.com; 84 | # 85 | # root /var/www/example.com; 86 | # index index.html; 87 | # 88 | # location / { 89 | # try_files $uri $uri/ =404; 90 | # } 91 | #} 92 | -------------------------------------------------------------------------------- /testdata/configs/upstream_resolver_directive/multiple_resolvers.conf: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/upstream_resolver_directive/multiple_resolvers.conf.golden: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/upstream_resolver_directive/multiple_resolvers_with_ports.conf: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/upstream_resolver_directive/multiple_resolvers_with_ports.conf.golden: -------------------------------------------------------------------------------- 1 | http { 2 | upstream upstream1 { 3 | zone some_zone 64k; 4 | resolver 1.1.1.1 2.2.2.2 [fe80::12]; 5 | server 1.2.3.4:80; 6 | keepalive 64; 7 | keepalive_requests 100; 8 | keepalive_timeout 60s; 9 | } 10 | server { 11 | server_name 127.0.0.1; 12 | listen 127.0.0.1:49151; 13 | access_log off; 14 | location /api { 15 | api; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testdata/configs/upstream_resolver_directive/simple.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | location / { 10 | return 200 "foo bar baz"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/upstream_resolver_directive/simple.conf.golden: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; 8 | server_name default_server; 9 | location / { 10 | return 200 "foo bar baz"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testdata/configs/with-comments/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | #comment 5 | http { 6 | server { 7 | listen 127.0.0.1:8080; #listen 8 | server_name default_server; 9 | location / { ## this is brace 10 | # location / 11 | return 200 "foo bar baz"; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /testdata/configs/with-comments/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/with-comments/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "worker_connections", 17 | "line": 2, 18 | "args": [ 19 | "1024" 20 | ] 21 | } 22 | ] 23 | }, 24 | { 25 | "directive": "#", 26 | "line": 4, 27 | "args": [], 28 | "comment": "comment" 29 | }, 30 | { 31 | "directive": "http", 32 | "line": 5, 33 | "args": [], 34 | "block": [ 35 | { 36 | "directive": "server", 37 | "line": 6, 38 | "args": [], 39 | "block": [ 40 | { 41 | "directive": "listen", 42 | "line": 7, 43 | "args": [ 44 | "127.0.0.1:8080" 45 | ] 46 | }, 47 | { 48 | "directive": "#", 49 | "line": 7, 50 | "args": [], 51 | "comment": "listen" 52 | }, 53 | { 54 | "directive": "server_name", 55 | "line": 8, 56 | "args": [ 57 | "default_server" 58 | ] 59 | }, 60 | { 61 | "directive": "location", 62 | "line": 9, 63 | "args": [ 64 | "/" 65 | ], 66 | "block": [ 67 | { 68 | "directive": "#", 69 | "line": 9, 70 | "args": [], 71 | "comment": "# this is brace" 72 | }, 73 | { 74 | "directive": "#", 75 | "line": 10, 76 | "args": [], 77 | "comment": " location /" 78 | }, 79 | { 80 | "directive": "return", 81 | "line": 11, 82 | "args": [ 83 | "200", 84 | "foo bar baz" 85 | ] 86 | } 87 | ] 88 | } 89 | ] 90 | }, 91 | { 92 | "directive": "server", 93 | "line": 14, 94 | "args": [], 95 | "block": [ 96 | { 97 | "directive": "listen", 98 | "line": 15, 99 | "args": [ 100 | "80" 101 | ] 102 | }, 103 | { 104 | "directive": "server_name", 105 | "line": 16, 106 | "args": [ 107 | "prod" 108 | ] 109 | }, 110 | { 111 | "directive": "location", 112 | "line": 17, 113 | "args": [ 114 | "/" 115 | ], 116 | "block": [ 117 | { 118 | "directive": "return", 119 | "line": 18, 120 | "args": [ 121 | "200", 122 | "whirled peas" 123 | ] 124 | } 125 | ] 126 | } 127 | ] 128 | } 129 | ] 130 | } 131 | ] 132 | } 133 | ] 134 | } 135 | -------------------------------------------------------------------------------- /testdata/configs/with-comments/xp.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "errors": [], 4 | "config": [ 5 | { 6 | "file": "testdata/configs/with-comments/nginx.conf", 7 | "status": "ok", 8 | "errors": [], 9 | "parsed": [ 10 | { 11 | "directive": "events", 12 | "line": 1, 13 | "args": [], 14 | "block": [ 15 | { 16 | "directive": "worker_connections", 17 | "line": 2, 18 | "args": [ 19 | "1024" 20 | ] 21 | } 22 | ] 23 | }, 24 | { 25 | "directive": "#", 26 | "line": 4, 27 | "args": [], 28 | "comment": "comment" 29 | }, 30 | { 31 | "directive": "http", 32 | "line": 5, 33 | "args": [], 34 | "block": [ 35 | { 36 | "directive": "server", 37 | "line": 6, 38 | "args": [], 39 | "block": [ 40 | { 41 | "directive": "listen", 42 | "line": 7, 43 | "args": [ 44 | "127.0.0.1:8080" 45 | ] 46 | }, 47 | { 48 | "directive": "#", 49 | "line": 7, 50 | "args": [], 51 | "comment": "listen" 52 | }, 53 | { 54 | "directive": "server_name", 55 | "line": 8, 56 | "args": [ 57 | "default_server" 58 | ] 59 | }, 60 | { 61 | "directive": "location", 62 | "line": 9, 63 | "args": [ 64 | "/" 65 | ], 66 | "block": [ 67 | { 68 | "directive": "#", 69 | "line": 9, 70 | "args": [], 71 | "comment": "# this is brace" 72 | }, 73 | { 74 | "directive": "#", 75 | "line": 10, 76 | "args": [], 77 | "comment": " location /" 78 | }, 79 | { 80 | "directive": "return", 81 | "line": 11, 82 | "args": [ 83 | "200", 84 | "foo bar baz" 85 | ] 86 | } 87 | ] 88 | } 89 | ] 90 | }, 91 | { 92 | "directive": "server", 93 | "line": 14, 94 | "args": [], 95 | "block": [ 96 | { 97 | "directive": "listen", 98 | "line": 15, 99 | "args": [ 100 | "80" 101 | ] 102 | }, 103 | { 104 | "directive": "server_name", 105 | "line": 16, 106 | "args": [ 107 | "prod" 108 | ] 109 | }, 110 | { 111 | "directive": "location", 112 | "line": 17, 113 | "args": [ 114 | "/" 115 | ], 116 | "block": [ 117 | { 118 | "directive": "return", 119 | "line": 18, 120 | "args": [ 121 | "200", 122 | "whirled peas" 123 | ] 124 | } 125 | ] 126 | } 127 | ] 128 | } 129 | ] 130 | } 131 | ] 132 | } 133 | ] 134 | } 135 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | // This file just exists to ensure we download the tools we need for building 5 | // See https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module 6 | 7 | package crossplane 8 | 9 | import ( 10 | _ "github.com/jstemmer/go-junit-report/parser" 11 | _ "golang.org/x/tools/imports" 12 | ) 13 | -------------------------------------------------------------------------------- /util_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) F5, Inc. 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0 license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package crossplane_test 9 | 10 | import ( 11 | "encoding/json" 12 | "testing" 13 | 14 | . "github.com/nginxinc/nginx-go-crossplane" //nolint: revive 15 | ) 16 | 17 | //nolint:funlen 18 | func TestPayload(t *testing.T) { 19 | t.Parallel() 20 | t.Run("combine", func(t *testing.T) { 21 | t.Parallel() 22 | payload := Payload{ 23 | Config: []Config{ 24 | { 25 | File: "example1.conf", 26 | Parsed: Directives{ 27 | { 28 | Directive: "include", 29 | Args: []string{"example2.conf"}, 30 | Line: 1, 31 | Includes: []int{1}, 32 | }, 33 | }, 34 | }, 35 | { 36 | File: "example2.conf", 37 | Parsed: Directives{ 38 | { 39 | Directive: "events", 40 | Args: []string{}, 41 | Line: 1, 42 | }, 43 | { 44 | Directive: "http", 45 | Args: []string{}, 46 | Line: 2, 47 | }, 48 | }, 49 | }, 50 | }, 51 | } 52 | expected := Payload{ 53 | Status: "ok", 54 | Errors: []PayloadError{}, 55 | Config: []Config{ 56 | { 57 | File: "example1.conf", 58 | Status: "ok", 59 | Errors: []ConfigError{}, 60 | Parsed: Directives{ 61 | { 62 | Directive: "events", 63 | Args: []string{}, 64 | Line: 1, 65 | }, 66 | { 67 | Directive: "http", 68 | Args: []string{}, 69 | Line: 2, 70 | }, 71 | }, 72 | }, 73 | }, 74 | } 75 | combined, err := payload.Combined() 76 | if err != nil { 77 | t.Fatal(err) 78 | } 79 | b1, _ := json.Marshal(expected) 80 | b2, _ := json.Marshal(*combined) 81 | if string(b1) != string(b2) { 82 | t.Fatalf("expected: %s\nbut got: %s", b1, b2) 83 | } 84 | }) 85 | } 86 | --------------------------------------------------------------------------------