Skip to content

Commit b0fd16c

Browse files
authored
Merge pull request #24 from fulder/master
Refactor Key regex
2 parents b2eb8d5 + ff5a0aa commit b0fd16c

File tree

2 files changed

+84
-16
lines changed

2 files changed

+84
-16
lines changed

nginx.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ def as_strings(self):
382382
"""Return key as nginx config string."""
383383
if self.value == '' or self.value is None:
384384
return '{0};\n'.format(self.name)
385-
if ';' in self.value or '#' in self.value:
385+
if '"' not in self.value and (';' in self.value or '#' in self.value):
386386
return '{0} "{1}";\n'.format(self.name, self.value)
387387
return '{0} {1};\n'.format(self.name, self.value)
388388

@@ -477,19 +477,13 @@ def loads(data, conf=True):
477477
index += m.end()
478478
continue
479479

480-
key_with_quoted = r'^\s*(\S*?)\s*"([^"]+)";?|\'([^\']+)\';?|\\S+;?'
481-
key_wo_quoted = r'^\s*([a-zA-Z0-9-_]+?)\s+(.+?);'
482-
m1 = re.compile(key_with_quoted, re.S).search(data[index:])
483-
m2 = re.compile(key_wo_quoted, re.S).search(data[index:])
484-
if m1 and m2:
485-
if m1.start() <= m2.start():
486-
m = m1
487-
else:
488-
m = m2
489-
else:
490-
m = m1 or m2
480+
s1 = r'("[^"]+"|\'[^\']+\'|[^\s;]+)'
481+
s2 = r'("[^"]*"|\'[^\']*\'|[^\s;]*)'
482+
s3 = r'(\s*[^;]*?)'
483+
key = r'^\s*{}\s*{}{};'.format(s1, s2, s3)
484+
m = re.compile(key, re.S).search(data[index:])
491485
if m:
492-
k = Key(m.group(1), m.group(2))
486+
k = Key(m.group(1), m.group(2) + m.group(3))
493487
if lopen and isinstance(lopen[0], (Container, Server)):
494488
lopen[0].add(k)
495489
else:

tests.py

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
server_name localhost 127.0.0.1;
4646
root /srv/http; # And also this one
4747
mykey "myvalue; #notme myothervalue";
48+
"quoted_key" "quoted_value";
4849
# This one too
4950
index index.php;
5051
if (!-e $request_filename)
@@ -101,6 +102,61 @@
101102
"""
102103

103104

105+
TESTBLOCK_CASE_5 = """
106+
upstream test0 {
107+
server 1.1.1.1:8080;
108+
send "some request";
109+
}
110+
111+
upstream test1 {
112+
server 1.1.1.1:8080;
113+
send 'some request';
114+
}
115+
116+
server {
117+
server_name "www.example.com";
118+
119+
location / {
120+
root html;
121+
}
122+
}
123+
"""
124+
125+
126+
TESTBLOCK_CASE_6 = """
127+
upstream test0 {
128+
server 1.1.1.1:8080;
129+
check interval=3000 rise=2 fall=3 timeout=3000 type=http;
130+
check_http_send "GET /alive.html HTTP/1.0\r\n\r\n";
131+
check_http_expect_alive http_2xx http_3xx;
132+
}
133+
134+
upstream test1 {
135+
ip_hash;
136+
server 2.2.2.2:9000;
137+
check_http_send 'GET /alive.html HTTP/1.0\r\n\r\n';
138+
}
139+
"""
140+
141+
TESTBLOCK_CASE_7 = """
142+
upstream xx.com_backend {
143+
server 10.193.2.2:9061 weight=1 max_fails=2 fail_timeout=30s;
144+
server 10.193.2.1:9061 weight=1 max_fails=2 fail_timeout=30s;
145+
session_sticky;
146+
}
147+
148+
server {
149+
listen 80;
150+
151+
location / {
152+
set $xlocation 'test';
153+
proxy_pass http://xx.com_backend;
154+
}
155+
}
156+
"""
157+
158+
159+
104160
class TestPythonNginx(unittest.TestCase):
105161
def test_basic_load(self):
106162
self.assertTrue(nginx.loads(TESTBLOCK_CASE_1) is not None)
@@ -124,21 +180,24 @@ def test_key_parse(self):
124180
self.assertEqual(firstKey.name, 'listen')
125181
self.assertEqual(firstKey.value, '80')
126182
self.assertEqual(thirdKey.name, 'mykey')
127-
self.assertEqual(thirdKey.value, 'myvalue; #notme myothervalue')
183+
self.assertEqual(thirdKey.value, '"myvalue; #notme myothervalue"')
128184

129185
def test_key_parse_complex(self):
130186
data = nginx.loads(TESTBLOCK_CASE_2)
131-
self.assertEqual(len(data.server.keys), 5)
187+
self.assertEqual(len(data.server.keys), 6)
132188
firstKey = data.server.keys[0]
133189
thirdKey = data.server.keys[3]
190+
fourthKey = data.server.keys[4]
134191
self.assertEqual(firstKey.name, 'listen')
135192
self.assertEqual(firstKey.value, '80')
136193
self.assertEqual(thirdKey.name, 'mykey')
137-
self.assertEqual(thirdKey.value, 'myvalue; #notme myothervalue')
194+
self.assertEqual(thirdKey.value, '"myvalue; #notme myothervalue"')
138195
self.assertEqual(
139196
data.server.locations[-1].keys[0].value,
140197
"301 $scheme://$host:$server_port${request_uri}bitbucket/"
141198
)
199+
self.assertEqual(fourthKey.name, '"quoted_key"')
200+
self.assertEqual(fourthKey.value, '"quoted_value"')
142201

143202
def test_location_parse(self):
144203
data = nginx.loads(TESTBLOCK_CASE_1)
@@ -162,6 +221,21 @@ def test_reflection(self):
162221
out_data = '\n' + nginx.dumps(inp_data)
163222
self.assertEqual(TESTBLOCK_CASE_1, out_data)
164223

224+
def test_quoted_key_value(self):
225+
data = nginx.loads(TESTBLOCK_CASE_5)
226+
out_data = '\n' + nginx.dumps(data)
227+
self.assertEqual(out_data, TESTBLOCK_CASE_5)
228+
229+
def test_complex_upstream(self):
230+
inp_data = nginx.loads(TESTBLOCK_CASE_6)
231+
out_data = '\n' + nginx.dumps(inp_data)
232+
self.assertEqual(TESTBLOCK_CASE_6, out_data)
233+
234+
def test_session_sticky(self):
235+
inp_data = nginx.loads(TESTBLOCK_CASE_7)
236+
out_data = '\n' + nginx.dumps(inp_data)
237+
self.assertEqual(TESTBLOCK_CASE_7, out_data)
238+
165239
def test_filtering(self):
166240
data = nginx.loads(TESTBLOCK_CASE_1)
167241
self.assertEqual(len(data.server.filter('Key', 'mykey')), 1)

0 commit comments

Comments
 (0)