package nginx import ( "errors" "slices" "strings" "github.com/tufanbarisyildirim/gonginx/config" "github.com/tufanbarisyildirim/gonginx/dumper" "github.com/tufanbarisyildirim/gonginx/parser" ) // Parser Nginx vhost 配置解析器 type Parser struct { c *config.Config orderIndex map[string]int } func NewParser(str ...string) (*Parser, error) { if len(str) == 0 { str = append(str, defaultConf) } p := parser.NewStringParser(str[0], parser.WithSkipIncludeParsingErr(), parser.WithSkipValidDirectivesErr()) c, err := p.Parse() if err != nil { return nil, err } orderIndex := make(map[string]int) for i, name := range order { orderIndex[name] = i } return &Parser{c: c, orderIndex: orderIndex}, nil } func (p *Parser) Config() *config.Config { return p.c } // Find 通过表达式查找配置 // eg: Find("server.listen") func (p *Parser) Find(key string) ([]config.IDirective, error) { parts := strings.Split(key, ".") var block *config.Block var ok bool block = p.c.Block for i := 0; i < len(parts)-1; i++ { key = parts[i] directives := block.FindDirectives(key) if len(directives) == 0 { return nil, errors.New("given key not found") } if len(directives) > 1 { return nil, errors.New("multiple directives found") } block, ok = directives[0].GetBlock().(*config.Block) if !ok { return nil, errors.New("block is not *config.Block") } } var result []config.IDirective for _, dir := range block.GetDirectives() { if dir.GetName() == parts[len(parts)-1] { result = append(result, dir) } } return result, nil } // FindOne 通过表达式查找一个配置 // eg: FindOne("server.server_name") func (p *Parser) FindOne(key string) (config.IDirective, error) { directives, err := p.Find(key) if err != nil { return nil, err } if len(directives) == 0 { return nil, errors.New("given key not found") } return directives[0], nil } // Clear 通过表达式移除配置 // eg: Clear("server.server_name") func (p *Parser) Clear(key string) error { parts := strings.Split(key, ".") last := parts[len(parts)-1] parts = parts[:len(parts)-1] var block *config.Block var ok bool block = p.c.Block for i := 0; i < len(parts); i++ { directives := block.FindDirectives(parts[i]) if len(directives) == 0 { return errors.New("given key not found") } if len(directives) > 1 { return errors.New("multiple directives found") } block, ok = directives[0].GetBlock().(*config.Block) if !ok { return errors.New("block is not *config.Block") } } var newDirectives []config.IDirective for _, directive := range block.GetDirectives() { if directive.GetName() != last { newDirectives = append(newDirectives, directive) } } block.Directives = newDirectives return nil } // Set 通过表达式设置配置 // eg: Set("server.server_name", []directive) func (p *Parser) Set(key string, directives []*config.Directive) error { parts := strings.Split(key, ".") var block *config.Block var ok bool block = p.c.Block for i := 0; i < len(parts); i++ { sub := block.FindDirectives(parts[i]) if len(sub) == 0 { return errors.New("given key not found") } if len(sub) > 1 { return errors.New("multiple directives found") } block, ok = sub[0].GetBlock().(*config.Block) if !ok { return errors.New("block is not *config.Block") } } for _, directive := range directives { directive.SetParent(block) block.Directives = append(block.Directives, directive) } return nil } func (p *Parser) Sort() { p.sortDirectives(p.c.Directives, p.orderIndex) } func (p *Parser) Dump() string { p.Sort() return dumper.DumpConfig(p.c, dumper.IndentedStyle) } func (p *Parser) sortDirectives(directives []config.IDirective, orderIndex map[string]int) { slices.SortFunc(directives, func(a config.IDirective, b config.IDirective) int { return orderIndex[a.GetName()] - orderIndex[b.GetName()] }) for _, directive := range directives { if block, ok := directive.GetBlock().(*config.Block); ok { p.sortDirectives(block.Directives, orderIndex) } } }