Skip to content

Commit 14ba2b9

Browse files
committed
Refactor add_header directives to use AddHeaderDirective class and improve header handling
1 parent 8d4188a commit 14ba2b9

File tree

5 files changed

+65
-68
lines changed

5 files changed

+65
-68
lines changed

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
GIXY
22
====
3-
[![Mozilla Public License 2.0](https://img.shields.io/github/license/dvershinin/gixy.svg?style=flat-square)](https://github.com/dvershinin/gixy/blob/master/LICENSE)
3+
[![Mozilla Public License 2.0](https://img.shields.io/badge/license-MPLv2.0-brightgreen?style=flat-square)](https://github.com/dvershinin/gixy/blob/master/LICENSE)
44
[![Python tests](https://github.com/dvershinin/gixy/actions/workflows/pythonpackage.yml/badge.svg)](https://github.com/dvershinin/gixy/actions/workflows/pythonpackage.yml)
5-
[![Your feedback is greatly appreciated](https://img.shields.io/maintenance/yes/2023.svg?style=flat-square)](https://github.com/dvershinin/gixy/issues/new)
5+
[![Your feedback is greatly appreciated](https://img.shields.io/maintenance/yes/2025.svg?style=flat-square)](https://github.com/dvershinin/gixy/issues/new)
66
[![GitHub issues](https://img.shields.io/github/issues/dvershinin/gixy.svg?style=flat-square)](https://github.com/dvershinin/gixy/issues)
77
[![GitHub pull requests](https://img.shields.io/github/issues-pr/dvershinin/gixy.svg?style=flat-square)](https://github.com/dvershinin/gixy/pulls)
88

gixy/core/sre_parse/sre_parse.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def getwidth(self):
138138
if op is BRANCH:
139139
i = MAXREPEAT - 1
140140
j = 0
141-
for av in av[1]:
141+
for _ in av[1]:
142142
l, h = av.getwidth()
143143
i = min(i, l)
144144
j = max(j, h)
@@ -166,7 +166,9 @@ def getwidth(self):
166166

167167

168168
class Tokenizer:
169+
169170
def __init__(self, string):
171+
self.next = None
170172
self.string = string
171173
self.index = 0
172174
self.__next()
@@ -753,11 +755,6 @@ def literal(literal, p=p, pappend=a):
753755
else:
754756
pappend((LITERAL, literal))
755757

756-
sep = source[:0]
757-
if type(sep) is type(""):
758-
makechar = chr
759-
else:
760-
makechar = unichr
761758
while 1:
762759
this = sget()
763760
if this is None:
@@ -795,20 +792,20 @@ def literal(literal, p=p, pappend=a):
795792
this = this + sget()
796793
if s.next in OCTDIGITS:
797794
this = this + sget()
798-
literal(makechar(int(this[1:], 8) & 0xFF))
795+
literal(chr(int(this[1:], 8) & 0xFF))
799796
elif c in DIGITS:
800797
isoctal = False
801798
if s.next in DIGITS:
802799
this = this + sget()
803800
if c in OCTDIGITS and this[2] in OCTDIGITS and s.next in OCTDIGITS:
804801
this = this + sget()
805802
isoctal = True
806-
literal(makechar(int(this[1:], 8) & 0xFF))
803+
literal(chr(int(this[1:], 8) & 0xFF))
807804
if not isoctal:
808805
a((MARK, int(this[1:])))
809806
else:
810807
try:
811-
this = makechar(ESCAPES[this][1])
808+
this = chr(ESCAPES[this][1])
812809
except KeyError:
813810
pass
814811
literal(this)

gixy/directives/directive.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,53 @@ def __init__(self, name, args):
7777
super(AddHeaderDirective, self).__init__(name, args)
7878
self.header = args[0].lower()
7979
self.value = args[1]
80+
self.headers = {self.header: self.value}
8081
self.always = False
8182
if len(args) > 2 and args[2] == "always":
8283
self.always = True
8384

8485

86+
class MoreSetHeadersDirective(Directive):
87+
"""
88+
Syntax: more_set_headers 'Foo: bar' 'Baz: bah';
89+
"""
90+
91+
nginx_name = "more_set_headers"
92+
93+
def get_headers(self):
94+
# See headers more documentation: https://github.com/openresty/headers-more-nginx-module#description
95+
result = {}
96+
skip_next = False
97+
for arg in self.args:
98+
if arg in ["-s", "-t"]:
99+
# Mark to skip the next value because it's not a header
100+
skip_next = True
101+
elif arg.startswith("-"):
102+
# Skip any options
103+
continue
104+
elif skip_next:
105+
skip_next = False
106+
elif not skip_next:
107+
# Now it's a header in format "Header: value" or "Header:" or just "Header" (for clearing)
108+
parts = arg.split(":", 1)
109+
header = parts[0]
110+
value = None
111+
if len(parts) > 1 and parts[1].strip():
112+
# strip only whitespace character from left side, preserving newlines
113+
# this is needed to support multiline headers
114+
value = parts[1].lstrip(" ")
115+
result[header] = value
116+
return result
117+
118+
def __init__(self, name, args):
119+
super().__init__(name, args)
120+
self.headers = self.get_headers()
121+
# first header is the main header name
122+
self.header = list(self.headers.keys())[0]
123+
# value is
124+
self.value = self.headers[self.header]
125+
126+
85127
class SetDirective(Directive):
86128
nginx_name = "set"
87129
provide_variables = True
Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import gixy
2+
from gixy.directives.directive import AddHeaderDirective
23
from gixy.plugins.plugin import Plugin
34

45

@@ -7,38 +8,16 @@ class add_header_content_type(Plugin):
78
Bad example: add_header Content-Type text/plain;
89
Good example: default_type text/plain;
910
"""
10-
summary = 'Found add_header usage for setting Content-Type.'
11+
12+
summary = "Found add_header usage for setting Content-Type."
1113
severity = gixy.severity.LOW
1214
description = 'Target Content-Type in NGINX should not be set via "add_header"'
13-
help_url = 'https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/add_header_content_type.md'
14-
directives = ['add_header']
15+
help_url = "https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/add_header_content_type.md"
16+
directives = ["add_header"]
1517

16-
def audit(self, directive):
17-
header_values = get_header_values(directive)
18-
if directive.header == 'content-type':
19-
reason = 'You probably want "default_type {default_type};" instead of "add_header" or "more_set_headers"'.format(default_type=header_values[0])
20-
self.add_issue(
21-
directive=directive,
22-
reason=reason
18+
def audit(self, directive: AddHeaderDirective):
19+
if directive.header == "content-type":
20+
reason = 'You probably want "default_type {default_type};" instead of "add_header" or "more_set_headers"'.format(
21+
default_type=directive.value
2322
)
24-
25-
26-
def get_header_values(directive):
27-
if directive.name == 'add_header':
28-
return [directive.args[1]]
29-
30-
# See headers more documentation: https://github.com/openresty/headers-more-nginx-module#description
31-
result = []
32-
skip_next = False
33-
for arg in directive.args:
34-
if arg in ['-s', '-t']:
35-
# Skip next value, because it's not a header
36-
skip_next = True
37-
elif arg.startswith('-'):
38-
# Skip any options
39-
pass
40-
elif skip_next:
41-
skip_next = False
42-
elif not skip_next:
43-
result.append(arg)
44-
return result
23+
self.add_issue(directive=directive, reason=reason)
Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import gixy
2+
from gixy.directives.directive import AddHeaderDirective
23
from gixy.plugins.plugin import Plugin
34

45

@@ -20,41 +21,19 @@ class add_header_multiline(Plugin):
2021
help_url = "https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/addheadermultiline.md"
2122
directives = ["add_header", "more_set_headers"]
2223

23-
def audit(self, directive):
24-
header_values = get_header_values(directive)
25-
for value in header_values:
24+
def audit(self, directive: AddHeaderDirective):
25+
for header, value in directive.headers.items():
2626
if "\n\x20" in value or "\n\t" in value:
2727
self.add_issue(directive=directive)
2828
break
2929
if "\n" in value:
3030
reason = (
31-
'A newline character is found in the directive "{directive}". The resulting header will be '
31+
'A newline character is found in the directive "{directive}". The resulting header {header} will be '
3232
"incomplete. Ensure the value is fit on a single line".format(
33-
directive=directive.name
33+
directive=directive.name, header=header
3434
)
3535
)
3636
self.add_issue(
3737
severity=gixy.severity.HIGH, directive=directive, reason=reason
3838
)
3939
break
40-
41-
42-
def get_header_values(directive):
43-
if directive.name == "add_header":
44-
return [directive.args[1]]
45-
46-
# See headers more documentation: https://github.com/openresty/headers-more-nginx-module#description
47-
result = []
48-
skip_next = False
49-
for arg in directive.args:
50-
if arg in ["-s", "-t"]:
51-
# Skip the next value because it's not a header
52-
skip_next = True
53-
elif arg.startswith("-"):
54-
# Skip any options
55-
pass
56-
elif skip_next:
57-
skip_next = False
58-
elif not skip_next:
59-
result.append(arg)
60-
return result

0 commit comments

Comments
 (0)