Skip to content

Make http types directives analysable #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ Contributors
* Ivan Poluyanov <i.poluyanov@icloud.com> `@poluyanov <https://github.com/poluyanov>`_
* Raymond Lau <raymond.lau.ca@gmail.com> `@Raymond26 <https://github.com/Raymond26>`_
* Luca Comellini <luca.com@gmail.com> `@lucacome <https://github.com/lucacome>`_
* Ron Vider <viderron@gmail.com> `@RonVider <https://github.com/RonVider>`_
* Ron Vider <viderron@gmail.com> `@RonVider <https://github.com/RonVider>`_
* Chris Novakovic <chris@chrisn.me.uk> `@chrisnovakovic <https://github.com/chrisnovakovic>`_
23 changes: 13 additions & 10 deletions crossplane/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions tests/configs/types/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
http {
types {
text/html html;
image/gif gif;
image/jpeg jpg jpeg;
}
}
43 changes: 43 additions & 0 deletions tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 55 additions & 0 deletions tests/test_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
}
]
}
]
}
]
}
]
}