Mini Shell
# -*- coding: utf-8 -*-
from crossplane.lexer import register_external_lexer
from crossplane.builder import register_external_builder
from crossplane.compat import fix_pep_479
from crossplane.errors import NgxParserBaseException
from crossplane.ext.abstract import CrossplaneExtension
class EmplaceIter:
def __init__(self, it):
self.it = it
self.ret = []
def __iter__(self):
return self
def __next__(self):
if len(self.ret) > 0:
v = self.ret.pop()
return v
return next(self.it)
next = __next__
def put_back(self, v):
self.ret.append(v)
class LuaBlockPlugin(CrossplaneExtension):
"""
This plugin adds special handling for Lua code block directives (*_by_lua_block)
We don't need to handle non-block or file directives because those are parsed
correctly by base Crossplane functionality.
"""
# todo maybe: populate the actual directive bit masks if analyzer/parser logic is needed
directives = {
'access_by_lua_block': [],
'balancer_by_lua_block': [],
'body_filter_by_lua_block': [],
'content_by_lua_block': [],
'header_filter_by_lua_block': [],
'init_by_lua_block': [],
'init_worker_by_lua_block': [],
'log_by_lua_block': [],
'rewrite_by_lua_block': [],
'set_by_lua_block': [],
'ssl_certificate_by_lua_block': [],
'ssl_session_fetch_by_lua_block': [],
'ssl_session_store_by_lua_block': [],
}
def register_extension(self):
register_external_lexer(directives=self.directives, lexer=self.lex)
register_external_builder(directives=self.directives, builder=self.build)
@fix_pep_479
def lex(self, char_iterator, directive):
if directive == "set_by_lua_block":
# https://github.com/openresty/lua-nginx-module#set_by_lua_block
# The sole *_by_lua_block directive that has an arg
arg = ''
for char, line in char_iterator:
if char.isspace():
if arg:
yield (arg, line, False)
break
while char.isspace():
char, line = next(char_iterator)
arg += char
depth = 0
token = ''
# check that Lua block starts correctly
while True:
char, line = next(char_iterator)
if not char.isspace():
break
if char != "{":
reason = 'expected { to start Lua block'
raise LuaBlockParserSyntaxError(reason, filename=None, lineno=line)
depth += 1
char_iterator = EmplaceIter(char_iterator)
# Grab everything in Lua block as a single token
# and watch for curly brace '{' in strings
for char, line in char_iterator:
if char == '-':
prev_char, prev_line = char, line
char, comment_line = next(char_iterator)
if char == '-':
token += '-'
while char != '\n':
token += char
char, line = next(char_iterator)
else:
char_iterator.put_back((char, comment_line))
char, line = prev_char, prev_line
elif char == '{':
depth += 1
elif char == '}':
depth -= 1
elif char in ('"', "'"):
quote = char
token += quote
char, line = next(char_iterator)
while char != quote:
token += quote if char == quote else char
char, line = next(char_iterator)
if depth < 0:
reason = 'unxpected "}"'
raise LuaBlockParserSyntaxError(reason, filename=None, lineno=line)
if depth == 0:
yield (token, line, True) # True because this is treated like a string
yield (';', line, False)
raise StopIteration
token += char
def parse(self, stmt, parsing, tokens, ctx=(), consume=False):
pass
def build(self, stmt, padding, indent=4, tabs=False):
built = stmt['directive']
if built == 'set_by_lua_block':
block = stmt['args'][1]
built += " %s" % stmt['args'][0]
else:
block = stmt['args'][0]
return built + ' {' + block + '}'
class LuaBlockParserSyntaxError(NgxParserBaseException):
pass
Zerion Mini Shell 1.0