mirror of https://github.com/yandex/gixy
557 lines
12 KiB
Python
557 lines
12 KiB
Python
from nose.tools import assert_equals
|
|
from gixy.parser.raw_parser import *
|
|
|
|
|
|
def test_directive():
|
|
config = '''
|
|
access_log syslog:server=127.0.0.1,tag=nginx_sentry toolsformat;
|
|
user http;
|
|
internal;
|
|
set $foo "bar";
|
|
set $foo 'bar';
|
|
proxy_pass http://unix:/run/sock.socket;
|
|
rewrite ^/([a-zA-Z0-9]+)$ /$1/${arg_v}.pb break;
|
|
server_name some.tld ~^(www\.)?podberi.(?:ru|com|ua)$
|
|
~^(www\.)?guru.yandex.ru$;
|
|
'''
|
|
|
|
expected = [
|
|
['access_log', 'syslog:server=127.0.0.1,tag=nginx_sentry', 'toolsformat'],
|
|
['user', 'http'],
|
|
['internal'],
|
|
['set', '$foo', 'bar'],
|
|
['set', '$foo', 'bar'],
|
|
['proxy_pass', 'http://unix:/run/sock.socket'],
|
|
['rewrite', '^/([a-zA-Z0-9]+)$', '/$1/${arg_v}.pb', 'break'],
|
|
['server_name', 'some.tld', '~^(www\.)?podberi.(?:ru|com|ua)$', '~^(www\.)?guru.yandex.ru$']
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_block():
|
|
config = '''
|
|
http {
|
|
}
|
|
'''
|
|
|
|
expected = [['http', [], []]]
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_block_with_child():
|
|
config = '''
|
|
http {
|
|
gzip on;
|
|
}
|
|
'''
|
|
|
|
expected = [['http', [], [['gzip', 'on']]]]
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_location_simple():
|
|
config = '''
|
|
location / {
|
|
}
|
|
location = /foo {
|
|
}
|
|
location ~ ^/bar {
|
|
}
|
|
location ~* ^/baz$ {
|
|
}
|
|
location ^~ ^/bazz {
|
|
}
|
|
# Whitespace may be omitted:((
|
|
location ~\.(js|css)$ {
|
|
}
|
|
'''
|
|
|
|
expected = [['location', ['/'], []],
|
|
['location', ['=', '/foo'], []],
|
|
['location', ['~', '^/bar'], []],
|
|
['location', ['~*', '^/baz$'], []],
|
|
['location', ['^~', '^/bazz'], []],
|
|
['Whitespace may be omitted:(('],
|
|
['location', ['~', '\.(js|css)$'], []]]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_quoted_strings():
|
|
config = '''
|
|
some_sq '\\'la\\.\\/\\"';
|
|
some_dq '\\'la\\.\\/\\"';
|
|
'''
|
|
|
|
expected = [['some_sq', '\'la\\.\\/\"'],
|
|
['some_dq', '\'la\\.\\/\"']]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_location_child():
|
|
config = '''
|
|
location = /foo {
|
|
proxy_pass http://unix:/run/sock.socket;
|
|
}
|
|
'''
|
|
|
|
expected = [['location', ['=', '/foo'], [
|
|
['proxy_pass', 'http://unix:/run/sock.socket']
|
|
]]]
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_nested_location():
|
|
config = '''
|
|
location ~* ^/foo {
|
|
location = /foo/bar {
|
|
internal;
|
|
proxy_pass http://any.yandex.ru;
|
|
}
|
|
|
|
location = /foo/baz {
|
|
proxy_pass upstream;
|
|
}
|
|
}
|
|
'''
|
|
|
|
expected = [['location', ['~*', '^/foo'], [
|
|
['location', ['=', '/foo/bar'], [
|
|
['internal'],
|
|
['proxy_pass', 'http://any.yandex.ru']
|
|
]],
|
|
['location', ['=', '/foo/baz'], [
|
|
['proxy_pass', 'upstream']
|
|
]],
|
|
]]]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_hash_block():
|
|
config = '''
|
|
geo $geo {
|
|
default 0;
|
|
|
|
127.0.0.1 2;
|
|
192.168.1.0/24 1;
|
|
10.1.0.0/16 1;
|
|
|
|
::1 2;
|
|
2001:0db8::/32 1;
|
|
}
|
|
'''
|
|
|
|
expected = [['geo', ['$geo'], [
|
|
['default', '0'],
|
|
['127.0.0.1', '2'],
|
|
['192.168.1.0/24', '1'],
|
|
['10.1.0.0/16', '1'],
|
|
['::1', '2'],
|
|
['2001:0db8::/32', '1']
|
|
]]]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_hash_block_in_location():
|
|
config = '''
|
|
location /iphone/ {
|
|
types {
|
|
text/html html htm shtml;
|
|
application/json json;
|
|
application/rss+xml rss;
|
|
text/vnd.sun.j2me.app-descriptor jad;
|
|
}
|
|
}
|
|
'''
|
|
|
|
expected = [['location', ['/iphone/'], [
|
|
['types', [], [
|
|
['text/html', 'html', 'htm', 'shtml'],
|
|
['application/json', 'json'],
|
|
['application/rss+xml', 'rss'],
|
|
['text/vnd.sun.j2me.app-descriptor', 'jad']
|
|
]],
|
|
]]]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_named_location():
|
|
config = '''
|
|
location @foo {
|
|
proxy_pass http://any.yandex.ru;
|
|
}
|
|
'''
|
|
|
|
expected = [['location', ['@foo'], [
|
|
['proxy_pass', 'http://any.yandex.ru']
|
|
]]]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_if():
|
|
config = '''
|
|
# http://nginx.org/ru/docs/http/ngx_http_rewrite_module.html#if
|
|
|
|
if ($http_user_agent ~ MSIE) {
|
|
rewrite ^(.*)$ /msie/$1 break;
|
|
}
|
|
|
|
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
|
|
set $id $1;
|
|
}
|
|
|
|
if ($request_method = POST) {
|
|
return 405;
|
|
}
|
|
|
|
if ($slow) {
|
|
limit_rate 10k;
|
|
}
|
|
|
|
if ($invalid_referer) {
|
|
return 403;
|
|
}
|
|
|
|
if (!-e "/var/data/$dataset") {
|
|
return 503;
|
|
}
|
|
|
|
if ($https_or_slb = (by_\(sl\)b|https)) {
|
|
}
|
|
|
|
if ($host ~* (lori|rage2)\.yandex\.(ru|ua|com|com\.tr)) {
|
|
set $x_frame_options ALLOW;
|
|
}
|
|
|
|
if ($request_filename ~* ^.*?/(\d+_)([^/]+)$) {
|
|
}
|
|
|
|
if ($http_user_agent ~* "^WordPress.*; verifying pingback") {
|
|
}
|
|
|
|
if ($foo = "BAR") { rewrite ^(.*)$ /bar; }
|
|
'''
|
|
|
|
expected = [
|
|
['http://nginx.org/ru/docs/http/ngx_http_rewrite_module.html#if'],
|
|
['if', ['$http_user_agent', '~', 'MSIE'], [
|
|
['rewrite', '^(.*)$', '/msie/$1', 'break']
|
|
]],
|
|
['if', ['$http_cookie', '~*', 'id=([^;]+)(?:;|$)'], [
|
|
['set', '$id', '$1']
|
|
]],
|
|
['if', ['$request_method', '=', 'POST'], [
|
|
['return', '405']
|
|
]],
|
|
['if', ['$slow'], [
|
|
['limit_rate', '10k']
|
|
]],
|
|
['if', ['$invalid_referer'], [
|
|
['return', '403']
|
|
]],
|
|
['if', ['!-e', '/var/data/$dataset'], [
|
|
['return', '503']
|
|
]],
|
|
['if', ['$https_or_slb', '=', '(by_\(sl\)b|https)'], [
|
|
]],
|
|
['if', ['$host', '~*', '(lori|rage2)\.yandex\.(ru|ua|com|com\.tr)'], [
|
|
['set', '$x_frame_options', 'ALLOW']
|
|
]],
|
|
['if', ['$request_filename', '~*', '^.*?/(\d+_)([^/]+)$'], [
|
|
]],
|
|
['if', ['$http_user_agent', '~*', '^WordPress.*; verifying pingback'], [
|
|
]],
|
|
['if', ['$foo', '=', 'BAR'], [
|
|
['rewrite', '^(.*)$', '/bar']
|
|
]]
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_hash_block_map():
|
|
config = '''
|
|
# http://nginx.org/ru/docs/http/ngx_http_map_module.html
|
|
|
|
map $http_host $name {
|
|
hostnames;
|
|
|
|
default 0;
|
|
|
|
example.com 1;
|
|
*.example.com 1;
|
|
example.org 2;
|
|
*.example.org 2;
|
|
.example.net 3;
|
|
wap.* 4;
|
|
}
|
|
|
|
map $http_user_agent $mobile {
|
|
default 0;
|
|
"~Opera Mini" 1;
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['http://nginx.org/ru/docs/http/ngx_http_map_module.html'],
|
|
['map', ['$http_host', '$name'], [
|
|
['hostnames'],
|
|
['default', '0'],
|
|
['example.com', '1'],
|
|
['*.example.com', '1'],
|
|
['example.org', '2'],
|
|
['*.example.org', '2'],
|
|
['.example.net', '3'],
|
|
['wap.*', '4'],
|
|
]],
|
|
['map', ['$http_user_agent', '$mobile'], [
|
|
['default', '0'],
|
|
['~Opera Mini', '1'],
|
|
]]
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_upstream():
|
|
config = '''
|
|
# http://nginx.org/ru/docs/http/ngx_http_upstream_module.html
|
|
|
|
upstream backend {
|
|
server backend1.example.com weight=5;
|
|
server backend2.example.com:8080;
|
|
server unix:/tmp/backend3;
|
|
|
|
server backup1.example.com:8080 backup;
|
|
server backup2.example.com:8080 backup;
|
|
}
|
|
|
|
server {
|
|
location / {
|
|
proxy_pass http://backend;
|
|
}
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['http://nginx.org/ru/docs/http/ngx_http_upstream_module.html'],
|
|
['upstream', ['backend'], [
|
|
['server', 'backend1.example.com', 'weight=5'],
|
|
['server', 'backend2.example.com:8080'],
|
|
['server', 'unix:/tmp/backend3'],
|
|
['server', 'backup1.example.com:8080', 'backup'],
|
|
['server', 'backup2.example.com:8080', 'backup'],
|
|
]],
|
|
['server', [], [
|
|
['location', ['/'], [
|
|
['proxy_pass', 'http://backend']
|
|
]]
|
|
]]]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_issue_8():
|
|
config = '''
|
|
# http://nginx.org/ru/docs/http/ngx_http_upstream_module.html
|
|
if ($http_referer ~* (\.(ru|ua|by|kz)/(pages/music|partners/|page-no-rights\.xml)) ) {
|
|
set $temp A;
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['http://nginx.org/ru/docs/http/ngx_http_upstream_module.html'],
|
|
['if', ['$http_referer', '~*', '(\.(ru|ua|by|kz)/(pages/music|partners/|page-no-rights\.xml))'], [
|
|
['set', '$temp', 'A']
|
|
]]
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_issue_11():
|
|
config = '''
|
|
init_by_lua_block {
|
|
tvm = require "nginx.tvm"
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['init_by_lua_block', [], ['tvm', '=', 'require', '"nginx.tvm"']]
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_lua_block():
|
|
config = '''
|
|
# https://github.com/openresty/lua-nginx-module#typical-uses
|
|
location = /lua {
|
|
# MIME type determined by default_type:
|
|
default_type 'text/plain';
|
|
|
|
content_by_lua_block {
|
|
local res = ngx.location.capture("/some_other_location")
|
|
if res then
|
|
ngx.say("status: ", res.status)
|
|
ngx.say("body:")
|
|
ngx.print(res.body)
|
|
end
|
|
}
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['https://github.com/openresty/lua-nginx-module#typical-uses'],
|
|
['location', ['=', '/lua'], [
|
|
['MIME type determined by default_type:'],
|
|
['default_type', 'text/plain'],
|
|
['content_by_lua_block', [], [
|
|
'local', 'res', '=', 'ngx.location.capture(', '"/some_other_location"', ')',
|
|
'if', 'res', 'then',
|
|
'ngx.say(', '"status: "', ',', 'res.status)',
|
|
'ngx.say(', '"body:"', ')',
|
|
'ngx.print(res.body)',
|
|
'end']]
|
|
]]
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_lua_block_brackets():
|
|
config = '''
|
|
location = /foo {
|
|
rewrite_by_lua_block {
|
|
res = ngx.location.capture("/memc",
|
|
{ args = { cmd = "incr", key = ngx.var.uri } }
|
|
)
|
|
}
|
|
|
|
proxy_pass http://blah.blah.com;
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['location', ['=', '/foo'], [
|
|
['rewrite_by_lua_block', [], [
|
|
'res', '=', 'ngx.location.capture(', '"/memc"', ',',
|
|
['args', '=', ['cmd', '=', '"incr"', ',', 'key', '=', 'ngx.var.uri']],
|
|
')']],
|
|
['proxy_pass', 'http://blah.blah.com']
|
|
]]
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_file_delims():
|
|
config = '''
|
|
# configuration file /etc/nginx/nginx.conf:
|
|
http {
|
|
include sites/*.conf;
|
|
}
|
|
|
|
# configuration file /etc/nginx/sites/default.conf:
|
|
server {
|
|
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['/etc/nginx/nginx.conf'],
|
|
['http', [], [
|
|
['include', 'sites/*.conf']
|
|
]],
|
|
['/etc/nginx/sites/default.conf'],
|
|
['server', [], []]
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_comments():
|
|
config = '''
|
|
# Some comment
|
|
add_header X-Some-Comment some;
|
|
|
|
#
|
|
# Comment with padding
|
|
#
|
|
add_header X-Padding-Comment padding;
|
|
|
|
#
|
|
add_header X-Blank-Comment blank;
|
|
'''
|
|
|
|
expected = [
|
|
['Some comment'],
|
|
['add_header', 'X-Some-Comment', 'some'],
|
|
[''],
|
|
['Comment with padding'],
|
|
[''],
|
|
['add_header', 'X-Padding-Comment', 'padding'],
|
|
[''],
|
|
['add_header', 'X-Blank-Comment', 'blank'],
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_upstream_dot():
|
|
config = '''
|
|
upstream test.mysite.com {
|
|
server 127.0.0.1:9009;
|
|
}
|
|
'''
|
|
|
|
expected = [
|
|
['upstream', ['test.mysite.com'], [
|
|
['server', '127.0.0.1:9009']
|
|
]],
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_empty_config():
|
|
config = '''
|
|
'''
|
|
|
|
expected = []
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_utfbom_decoding():
|
|
config = b'''\xef\xbb\xbf
|
|
add_header X-Test "Windows-1251";
|
|
'''
|
|
|
|
expected = [
|
|
['add_header', 'X-Test', 'Windows-1251']
|
|
]
|
|
|
|
assert_config(config, expected)
|
|
|
|
|
|
def test_national_comment_decoding():
|
|
config = b'''
|
|
# \xeb\xff-\xeb\xff-\xeb\xff = Lya-lya-lya
|
|
add_header X-Test "Windows-1251";
|
|
'''
|
|
|
|
actual = RawParser().parse(config)
|
|
assert_equals(len(actual.asList()), 2)
|
|
|
|
|
|
def assert_config(config, expected):
|
|
actual = RawParser().parse(config)
|
|
assert_equals(actual.asList(), expected)
|