diff --git a/AUTHORS.rst b/AUTHORS.rst index 37e8961..6af4968 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -14,4 +14,5 @@ Contributors * Ivan Poluyanov `@poluyanov `_ * Raymond Lau `@Raymond26 `_ * Luca Comellini `@lucacome `_ -* Ron Vider `@RonVider `_ \ No newline at end of file +* Ron Vider `@RonVider `_ +* Chris Novakovic `@chrisnovakovic `_ diff --git a/crossplane/analyzer.py b/crossplane/analyzer.py index e9d0e8e..5169cd0 100644 --- a/crossplane/analyzer.py +++ b/crossplane/analyzer.py @@ -2126,23 +2126,26 @@ def analyze(fname, stmt, term, ctx=(), strict=False, check_ctx=True, directive = stmt['directive'] line = stmt['line'] - # if strict and directive isn't recognized then throw error - if strict and directive not in DIRECTIVES: - reason = 'unknown directive "%s"' % directive - raise NgxParserDirectiveUnknownError(reason, fname, line) + ctx_http_types = len(ctx) >= 2 and ctx[0] == 'http' and ctx[-1] == 'types' - # if we don't know where this directive is allowed and how - # many arguments it can take then don't bother analyzing it - if ctx not in CONTEXTS or directive not in DIRECTIVES: - return + if not ctx_http_types: + # if strict and directive isn't recognized then throw error + if strict and directive not in DIRECTIVES: + reason = 'unknown directive "%s"' % directive + raise NgxParserDirectiveUnknownError(reason, fname, line) + + # if we don't know where this directive is allowed and how + # many arguments it can take then don't bother analyzing it + if ctx not in CONTEXTS or directive not in DIRECTIVES: + return args = stmt.get('args') or [] n_args = len(args) - masks = DIRECTIVES[directive] + masks = [NGX_CONF_1MORE] if ctx_http_types else DIRECTIVES[directive] # if this directive can't be used in this context then throw an error - if check_ctx: + if not ctx_http_types and check_ctx: masks = [mask for mask in masks if mask & CONTEXTS[ctx]] if not masks: reason = '"%s" directive is not allowed here' % directive diff --git a/tests/configs/types/nginx.conf b/tests/configs/types/nginx.conf new file mode 100644 index 0000000..a9e13ef --- /dev/null +++ b/tests/configs/types/nginx.conf @@ -0,0 +1,7 @@ +http { + types { + text/html html; + image/gif gif; + image/jpeg jpg jpeg; + } +} diff --git a/tests/test_build.py b/tests/test_build.py index eff3d79..aef52ee 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -226,6 +226,49 @@ def test_build_multiple_comments_on_one_line(): assert built == '#comment1\nuser root; #comment2 #comment3' +def test_build_types(): + payload = [ + { + 'directive': 'http', + 'line': 1, + 'args': [], + 'block': [ + { + 'directive': 'types', + 'line': 2, + 'args': [], + 'block': [ + { + 'directive': 'text/html', + 'line': 3, + 'args': ['html'] + }, + { + 'directive': 'image/gif', + 'line': 4, + 'args': ['gif'] + }, + { + 'directive': 'image/jpeg', + 'line': 5, + 'args': ['jpg', 'jpeg'] + } + ] + } + ] + } + ] + built = crossplane.build(payload, indent=4, tabs=False) + assert built == '\n'.join([ + 'http {', + ' types {', + ' text/html html;', + ' image/gif gif;', + ' image/jpeg jpg jpeg;', + ' }', + '}' + ]) + def test_build_files_with_missing_status_and_errors(tmpdir): assert len(tmpdir.listdir()) == 0 diff --git a/tests/test_parse.py b/tests/test_parse.py index 873b086..5c6f162 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -975,3 +975,58 @@ def test_comments_between_args(): } ] } + + +def test_types_checks(): + dirname = os.path.join(here, 'configs', 'types') + config = os.path.join(dirname, 'nginx.conf') + payload = crossplane.parse( + config, + strict=True, + check_ctx=True, + check_args=True, + ) + + # Check that strict mode doesn't raise errors when parsing http types blocks + assert payload == { + 'status': 'ok', + 'errors': [], + 'config': [ + { + 'file': os.path.join(dirname, 'nginx.conf'), + 'status': 'ok', + 'errors': [], + 'parsed': [ + { + 'directive': 'http', + 'line': 1, + 'args': [], + 'block': [ + { + 'directive': 'types', + 'line': 2, + 'args': [], + 'block': [ + { + 'directive': 'text/html', + 'line': 3, + 'args': ['html'] + }, + { + 'directive': 'image/gif', + 'line': 4, + 'args': ['gif'] + }, + { + 'directive': 'image/jpeg', + 'line': 5, + 'args': ['jpg', 'jpeg'] + } + ] + } + ] + } + ] + } + ] + }