feat: 增加nginx config 格式化工具
This commit is contained in:

committed by
zhengkunwang223

parent
7dad47464d
commit
a1ac689a5e
172
backend/utils/nginx/parser/parser.go
Normal file
172
backend/utils/nginx/parser/parser.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
components "github.com/1Panel-dev/1Panel/backend/utils/nginx/components"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/nginx/parser/flag"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
lexer *lexer
|
||||
currentToken flag.Flag
|
||||
followingToken flag.Flag
|
||||
blockWrappers map[string]func(*components.Directive) components.IDirective
|
||||
directiveWrappers map[string]func(*components.Directive) components.IDirective
|
||||
}
|
||||
|
||||
func NewStringParser(str string) *Parser {
|
||||
return NewParserFromLexer(lex(str))
|
||||
}
|
||||
|
||||
func NewParser(filePath string) (*Parser, error) {
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := newLexer(bufio.NewReader(f))
|
||||
l.file = filePath
|
||||
p := NewParserFromLexer(l)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func NewParserFromLexer(lexer *lexer) *Parser {
|
||||
parser := &Parser{
|
||||
lexer: lexer,
|
||||
}
|
||||
|
||||
parser.nextToken()
|
||||
parser.nextToken()
|
||||
|
||||
parser.blockWrappers = map[string]func(*components.Directive) components.IDirective{
|
||||
"http": func(directive *components.Directive) components.IDirective {
|
||||
return parser.wrapHttp(directive)
|
||||
},
|
||||
"server": func(directive *components.Directive) components.IDirective {
|
||||
return parser.wrapServer(directive)
|
||||
},
|
||||
"location": func(directive *components.Directive) components.IDirective {
|
||||
return parser.wrapLocation(directive)
|
||||
},
|
||||
"upstream": func(directive *components.Directive) components.IDirective {
|
||||
return parser.wrapUpstream(directive)
|
||||
},
|
||||
}
|
||||
|
||||
parser.directiveWrappers = map[string]func(*components.Directive) components.IDirective{
|
||||
"server": func(directive *components.Directive) components.IDirective {
|
||||
return parser.parseUpstreamServer(directive)
|
||||
},
|
||||
}
|
||||
|
||||
return parser
|
||||
}
|
||||
|
||||
func (p *Parser) nextToken() {
|
||||
p.currentToken = p.followingToken
|
||||
p.followingToken = p.lexer.scan()
|
||||
}
|
||||
|
||||
func (p *Parser) curTokenIs(t flag.Type) bool {
|
||||
return p.currentToken.Type == t
|
||||
}
|
||||
|
||||
func (p *Parser) followingTokenIs(t flag.Type) bool {
|
||||
return p.followingToken.Type == t
|
||||
}
|
||||
|
||||
func (p *Parser) Parse() *components.Config {
|
||||
return &components.Config{
|
||||
FilePath: p.lexer.file,
|
||||
Block: p.parseBlock(),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseBlock() *components.Block {
|
||||
|
||||
context := &components.Block{
|
||||
Comment: "",
|
||||
Directives: make([]components.IDirective, 0),
|
||||
}
|
||||
|
||||
parsingloop:
|
||||
for {
|
||||
switch {
|
||||
case p.curTokenIs(flag.EOF) || p.curTokenIs(flag.BlockEnd):
|
||||
break parsingloop
|
||||
case p.curTokenIs(flag.Keyword):
|
||||
context.Directives = append(context.Directives, p.parseStatement())
|
||||
case p.curTokenIs(flag.Comment):
|
||||
context.Directives = append(context.Directives, &components.Comment{
|
||||
Detail: p.currentToken.Literal,
|
||||
})
|
||||
}
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
func (p *Parser) parseStatement() components.IDirective {
|
||||
d := &components.Directive{
|
||||
Name: p.currentToken.Literal,
|
||||
}
|
||||
|
||||
for p.nextToken(); p.currentToken.IsParameterEligible(); p.nextToken() {
|
||||
d.Parameters = append(d.Parameters, p.currentToken.Literal)
|
||||
}
|
||||
|
||||
if p.curTokenIs(flag.Semicolon) {
|
||||
if dw, ok := p.directiveWrappers[d.Name]; ok {
|
||||
return dw(d)
|
||||
}
|
||||
if p.followingTokenIs(flag.Comment) && p.currentToken.Line == p.followingToken.Line {
|
||||
d.Comment = p.followingToken.Literal
|
||||
p.nextToken()
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
if p.curTokenIs(flag.BlockStart) {
|
||||
|
||||
inLineComment := ""
|
||||
if p.followingTokenIs(flag.Comment) && p.currentToken.Line == p.followingToken.Line {
|
||||
inLineComment = p.followingToken.Literal
|
||||
p.nextToken()
|
||||
p.nextToken()
|
||||
}
|
||||
block := p.parseBlock()
|
||||
block.Comment = inLineComment
|
||||
d.Block = block
|
||||
if bw, ok := p.blockWrappers[d.Name]; ok {
|
||||
return bw(d)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("unexpected token %s (%s) on line %d, column %d", p.currentToken.Type.String(), p.currentToken.Literal, p.currentToken.Line, p.currentToken.Column))
|
||||
}
|
||||
|
||||
func (p *Parser) wrapLocation(directive *components.Directive) *components.Location {
|
||||
return components.NewLocation(directive)
|
||||
}
|
||||
|
||||
func (p *Parser) wrapServer(directive *components.Directive) *components.Server {
|
||||
s, _ := components.NewServer(directive)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *Parser) wrapUpstream(directive *components.Directive) *components.Upstream {
|
||||
s, _ := components.NewUpstream(directive)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *Parser) wrapHttp(directive *components.Directive) *components.Http {
|
||||
h, _ := components.NewHttp(directive)
|
||||
return h
|
||||
}
|
||||
|
||||
func (p *Parser) parseUpstreamServer(directive *components.Directive) *components.UpstreamServer {
|
||||
return components.NewUpstreamServer(directive)
|
||||
}
|
Reference in New Issue
Block a user