mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-14 01:34:47 +08:00
feat: 增加nginx config 格式化工具
This commit is contained in:
parent
7dad47464d
commit
a1ac689a5e
@ -99,3 +99,8 @@ func ExistWithStrArray(str string, arr []string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsNum(s string) bool {
|
||||||
|
_, err := strconv.ParseFloat(s, 64)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
50
backend/utils/nginx/components/block.go
Normal file
50
backend/utils/nginx/components/block.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
type Block struct {
|
||||||
|
Comment string
|
||||||
|
Directives []IDirective
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) GetDirectives() []IDirective {
|
||||||
|
return b.Directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) GetComment() string {
|
||||||
|
return b.Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) FindDirectives(directiveName string) []IDirective {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
for _, directive := range b.GetDirectives() {
|
||||||
|
if directive.GetName() == directiveName {
|
||||||
|
directives = append(directives, directive)
|
||||||
|
}
|
||||||
|
if directive.GetBlock() != nil {
|
||||||
|
directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) UpdateDirectives(directiveName string, directive Directive) {
|
||||||
|
directives := make([]IDirective, len(b.GetDirectives()))
|
||||||
|
index := -1
|
||||||
|
for i, dir := range b.GetDirectives() {
|
||||||
|
if dir.GetName() == directiveName {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index > -1 {
|
||||||
|
directives[index] = &directive
|
||||||
|
} else {
|
||||||
|
directives = append(directives, &directive)
|
||||||
|
}
|
||||||
|
b.Directives = directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) AddDirectives(directive Directive) {
|
||||||
|
directives := append(b.GetDirectives(), &directive)
|
||||||
|
b.Directives = directives
|
||||||
|
}
|
21
backend/utils/nginx/components/comment.go
Normal file
21
backend/utils/nginx/components/comment.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
type Comment struct {
|
||||||
|
Detail string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Comment) GetName() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Comment) GetParameters() []string {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Comment) GetBlock() IBlock {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Comment) GetComment() string {
|
||||||
|
return c.Detail
|
||||||
|
}
|
28
backend/utils/nginx/components/config.go
Normal file
28
backend/utils/nginx/components/config.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
*Block
|
||||||
|
FilePath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) FindDirectives(directiveName string) []IDirective {
|
||||||
|
return c.Block.FindDirectives(directiveName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) FindUpstreams() []*Upstream {
|
||||||
|
var upstreams []*Upstream
|
||||||
|
directives := c.Block.FindDirectives("upstream")
|
||||||
|
for _, directive := range directives {
|
||||||
|
upstreams = append(upstreams, directive.(*Upstream))
|
||||||
|
}
|
||||||
|
return upstreams
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) FindServers() []*Server {
|
||||||
|
var servers []*Server
|
||||||
|
directives := c.Block.FindDirectives("server")
|
||||||
|
for _, directive := range directives {
|
||||||
|
servers = append(servers, directive.(*Server))
|
||||||
|
}
|
||||||
|
return servers
|
||||||
|
}
|
24
backend/utils/nginx/components/directive.go
Normal file
24
backend/utils/nginx/components/directive.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
type Directive struct {
|
||||||
|
Block IBlock
|
||||||
|
Name string
|
||||||
|
Comment string
|
||||||
|
Parameters []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) GetComment() string {
|
||||||
|
return d.Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) GetName() string {
|
||||||
|
return d.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) GetParameters() []string {
|
||||||
|
return d.Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) GetBlock() IBlock {
|
||||||
|
return d.Block
|
||||||
|
}
|
93
backend/utils/nginx/components/http.go
Normal file
93
backend/utils/nginx/components/http.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Http struct {
|
||||||
|
Comment string
|
||||||
|
Servers []*Server
|
||||||
|
Directives []IDirective
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) GetComment() string {
|
||||||
|
return h.Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHttp(directive IDirective) (*Http, error) {
|
||||||
|
if block := directive.GetBlock(); block != nil {
|
||||||
|
http := &Http{
|
||||||
|
Servers: []*Server{},
|
||||||
|
Directives: []IDirective{},
|
||||||
|
Comment: block.GetComment(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, directive := range block.GetDirectives() {
|
||||||
|
if server, ok := directive.(*Server); ok {
|
||||||
|
http.Servers = append(http.Servers, server)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
http.Directives = append(http.Directives, directive)
|
||||||
|
}
|
||||||
|
|
||||||
|
return http, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("http directive must have a block")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) GetName() string {
|
||||||
|
return "http"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) GetParameters() []string {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) GetDirectives() []IDirective {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
directives = append(directives, h.Directives...)
|
||||||
|
for _, directive := range h.Servers {
|
||||||
|
directives = append(directives, directive)
|
||||||
|
}
|
||||||
|
return directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) FindDirectives(directiveName string) []IDirective {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
for _, directive := range h.GetDirectives() {
|
||||||
|
if directive.GetName() == directiveName {
|
||||||
|
directives = append(directives, directive)
|
||||||
|
}
|
||||||
|
if directive.GetBlock() != nil {
|
||||||
|
directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) UpdateDirectives(directiveName string, directive Directive) {
|
||||||
|
directives := make([]IDirective, len(h.GetDirectives()))
|
||||||
|
index := -1
|
||||||
|
for i, dir := range h.GetDirectives() {
|
||||||
|
if dir.GetName() == directiveName {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index > -1 {
|
||||||
|
directives[index] = &directive
|
||||||
|
} else {
|
||||||
|
directives = append(directives, &directive)
|
||||||
|
}
|
||||||
|
h.Directives = directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) AddDirectives(directive Directive) {
|
||||||
|
directives := append(h.GetDirectives(), &directive)
|
||||||
|
h.Directives = directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Http) GetBlock() IBlock {
|
||||||
|
return h
|
||||||
|
}
|
32
backend/utils/nginx/components/location.go
Normal file
32
backend/utils/nginx/components/location.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
type Location struct {
|
||||||
|
*Directive
|
||||||
|
Modifier string
|
||||||
|
Match string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocation(directive *Directive) *Location {
|
||||||
|
location := &Location{
|
||||||
|
Modifier: "",
|
||||||
|
Match: "",
|
||||||
|
Directive: directive,
|
||||||
|
}
|
||||||
|
if directive.GetBlock() != nil {
|
||||||
|
directive.Comment = directive.GetBlock().GetComment()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(directive.Parameters) == 0 {
|
||||||
|
panic("no enough parameter for location")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(directive.Parameters) == 1 {
|
||||||
|
location.Match = directive.Parameters[0]
|
||||||
|
return location
|
||||||
|
} else if len(directive.Parameters) == 2 {
|
||||||
|
location.Modifier = directive.Parameters[0]
|
||||||
|
location.Match = directive.Parameters[1]
|
||||||
|
return location
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
107
backend/utils/nginx/components/server.go
Normal file
107
backend/utils/nginx/components/server.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Comment string
|
||||||
|
Listens []*ServerListen
|
||||||
|
Directives []IDirective
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(directive IDirective) (*Server, error) {
|
||||||
|
server := &Server{}
|
||||||
|
if block := directive.GetBlock(); block != nil {
|
||||||
|
server.Comment = block.GetComment()
|
||||||
|
directives := block.GetDirectives()
|
||||||
|
for _, dir := range directives {
|
||||||
|
if dir.GetName() == "listen" {
|
||||||
|
server.Listens = append(server.Listens, NewServerListen(dir.GetParameters()))
|
||||||
|
} else {
|
||||||
|
server.Directives = append(server.Directives, dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return server, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("server directive must have a block")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetName() string {
|
||||||
|
return "server"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetParameters() []string {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetBlock() IBlock {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetComment() string {
|
||||||
|
return s.Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetDirectives() []IDirective {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
for _, ls := range s.Listens {
|
||||||
|
directives = append(directives, ls)
|
||||||
|
}
|
||||||
|
directives = append(directives, s.Directives...)
|
||||||
|
return directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddListen(bind string, defaultServer bool, params ...string) {
|
||||||
|
listen := &ServerListen{
|
||||||
|
Bind: bind,
|
||||||
|
Parameters: params,
|
||||||
|
}
|
||||||
|
if defaultServer {
|
||||||
|
listen.DefaultServer = DefaultServer
|
||||||
|
}
|
||||||
|
s.Listens = append(s.Listens, listen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveListenByBind(bind string) {
|
||||||
|
index := 0
|
||||||
|
listens := s.Listens
|
||||||
|
for _, listen := range s.Listens {
|
||||||
|
if listen.Bind != bind || len(listen.Parameters) > 0 {
|
||||||
|
listens[index] = listen
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Listens = listens
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) FindDirectives(directiveName string) []IDirective {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
for _, directive := range s.Directives {
|
||||||
|
if directive.GetName() == directiveName {
|
||||||
|
directives = append(directives, directive)
|
||||||
|
}
|
||||||
|
if directive.GetBlock() != nil {
|
||||||
|
directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) UpdateDirectives(directiveName string, directive Directive) {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
for _, dir := range s.Directives {
|
||||||
|
if dir.GetName() == directiveName {
|
||||||
|
directives = append(directives, &directive)
|
||||||
|
} else {
|
||||||
|
directives = append(directives, dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Directives = directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddDirectives(directive Directive) {
|
||||||
|
directives := append(s.Directives, &directive)
|
||||||
|
s.Directives = directives
|
||||||
|
}
|
68
backend/utils/nginx/components/server_listen.go
Normal file
68
backend/utils/nginx/components/server_listen.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const DefaultServer = "default_server"
|
||||||
|
|
||||||
|
type ServerListen struct {
|
||||||
|
Bind string
|
||||||
|
DefaultServer string
|
||||||
|
Parameters []string
|
||||||
|
Comment string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServerListen(params []string) *ServerListen {
|
||||||
|
server := &ServerListen{
|
||||||
|
Parameters: []string{},
|
||||||
|
}
|
||||||
|
for _, param := range params {
|
||||||
|
if isBind(param) {
|
||||||
|
server.Bind = param
|
||||||
|
} else if param == DefaultServer {
|
||||||
|
server.DefaultServer = DefaultServer
|
||||||
|
} else {
|
||||||
|
server.Parameters = append(server.Parameters, param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBind(param string) bool {
|
||||||
|
if common.IsNum(param) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.Contains(param, "*") || strings.Contains(param, ":") || strings.Contains(param, ".") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *ServerListen) GetName() string {
|
||||||
|
return "listen"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *ServerListen) GetBlock() IBlock {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *ServerListen) GetParameters() []string {
|
||||||
|
params := []string{sl.Bind}
|
||||||
|
params = append(params, sl.DefaultServer)
|
||||||
|
params = append(params, sl.Parameters...)
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *ServerListen) GetComment() string {
|
||||||
|
return sl.Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *ServerListen) AddDefaultServer() {
|
||||||
|
sl.DefaultServer = DefaultServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *ServerListen) RemoveDefaultServe() {
|
||||||
|
sl.DefaultServer = ""
|
||||||
|
}
|
24
backend/utils/nginx/components/statement.go
Normal file
24
backend/utils/nginx/components/statement.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
type IBlock interface {
|
||||||
|
GetDirectives() []IDirective
|
||||||
|
FindDirectives(directiveName string) []IDirective
|
||||||
|
UpdateDirectives(directiveName string, directive Directive)
|
||||||
|
AddDirectives(directive Directive)
|
||||||
|
GetComment() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type IDirective interface {
|
||||||
|
GetName() string
|
||||||
|
GetParameters() []string
|
||||||
|
GetBlock() IBlock
|
||||||
|
GetComment() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileDirective interface {
|
||||||
|
isFileDirective()
|
||||||
|
}
|
||||||
|
|
||||||
|
type IncludeDirective interface {
|
||||||
|
FileDirective
|
||||||
|
}
|
94
backend/utils/nginx/components/upstream.go
Normal file
94
backend/utils/nginx/components/upstream.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Upstream struct {
|
||||||
|
UpstreamName string
|
||||||
|
UpstreamServers []*UpstreamServer
|
||||||
|
Directives []IDirective
|
||||||
|
Comment string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) GetName() string {
|
||||||
|
return "upstream"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) GetParameters() []string {
|
||||||
|
return []string{us.UpstreamName}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) GetBlock() IBlock {
|
||||||
|
return us
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) GetComment() string {
|
||||||
|
return us.Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) GetDirectives() []IDirective {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
directives = append(directives, us.Directives...)
|
||||||
|
for _, uss := range us.UpstreamServers {
|
||||||
|
directives = append(directives, uss)
|
||||||
|
}
|
||||||
|
|
||||||
|
return directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpstream(directive IDirective) (*Upstream, error) {
|
||||||
|
parameters := directive.GetParameters()
|
||||||
|
us := &Upstream{
|
||||||
|
UpstreamName: parameters[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
if block := directive.GetBlock(); block != nil {
|
||||||
|
us.Comment = block.GetComment()
|
||||||
|
for _, d := range block.GetDirectives() {
|
||||||
|
if d.GetName() == "server" {
|
||||||
|
us.UpstreamServers = append(us.UpstreamServers, NewUpstreamServer(d))
|
||||||
|
} else {
|
||||||
|
us.Directives = append(us.Directives, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return us, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("missing upstream block")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) AddServer(server *UpstreamServer) {
|
||||||
|
us.UpstreamServers = append(us.UpstreamServers, server)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) FindDirectives(directiveName string) []IDirective {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
for _, directive := range us.Directives {
|
||||||
|
if directive.GetName() == directiveName {
|
||||||
|
directives = append(directives, directive)
|
||||||
|
}
|
||||||
|
if directive.GetBlock() != nil {
|
||||||
|
directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) UpdateDirectives(directiveName string, directive Directive) {
|
||||||
|
directives := make([]IDirective, 0)
|
||||||
|
for _, dir := range us.GetDirectives() {
|
||||||
|
if dir.GetName() == directiveName {
|
||||||
|
directives = append(directives, &directive)
|
||||||
|
} else {
|
||||||
|
directives = append(directives, dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
us.Directives = directives
|
||||||
|
}
|
||||||
|
|
||||||
|
func (us *Upstream) AddDirectives(directive Directive) {
|
||||||
|
directives := append(us.GetDirectives(), &directive)
|
||||||
|
us.Directives = directives
|
||||||
|
}
|
77
backend/utils/nginx/components/upstream_server.go
Normal file
77
backend/utils/nginx/components/upstream_server.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpstreamServer struct {
|
||||||
|
Comment string
|
||||||
|
Address string
|
||||||
|
Flags []string
|
||||||
|
Parameters map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uss *UpstreamServer) GetName() string {
|
||||||
|
return "server"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uss *UpstreamServer) GetBlock() IBlock {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uss *UpstreamServer) GetParameters() []string {
|
||||||
|
return uss.GetDirective().Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uss *UpstreamServer) GetComment() string {
|
||||||
|
return uss.Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uss *UpstreamServer) GetDirective() *Directive {
|
||||||
|
directive := &Directive{
|
||||||
|
Name: "server",
|
||||||
|
Parameters: make([]string, 0),
|
||||||
|
Block: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
directive.Parameters = append(directive.Parameters, uss.Address)
|
||||||
|
|
||||||
|
paramNames := make([]string, 0)
|
||||||
|
for k := range uss.Parameters {
|
||||||
|
paramNames = append(paramNames, k)
|
||||||
|
}
|
||||||
|
sort.Strings(paramNames)
|
||||||
|
|
||||||
|
for _, k := range paramNames {
|
||||||
|
directive.Parameters = append(directive.Parameters, fmt.Sprintf("%s=%s", k, uss.Parameters[k]))
|
||||||
|
}
|
||||||
|
|
||||||
|
directive.Parameters = append(directive.Parameters, uss.Flags...)
|
||||||
|
|
||||||
|
return directive
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpstreamServer(directive IDirective) *UpstreamServer {
|
||||||
|
uss := &UpstreamServer{
|
||||||
|
Comment: directive.GetComment(),
|
||||||
|
Flags: make([]string, 0),
|
||||||
|
Parameters: make(map[string]string, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, parameter := range directive.GetParameters() {
|
||||||
|
if i == 0 {
|
||||||
|
uss.Address = parameter
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(parameter, "=") {
|
||||||
|
s := strings.SplitN(parameter, "=", 2)
|
||||||
|
uss.Parameters[s[0]] = s[1]
|
||||||
|
} else {
|
||||||
|
uss.Flags = append(uss.Flags, parameter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uss
|
||||||
|
}
|
132
backend/utils/nginx/dumper.go
Normal file
132
backend/utils/nginx/dumper.go
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package nginx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
components "github.com/1Panel-dev/1Panel/backend/utils/nginx/components"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//NoIndentStyle default style
|
||||||
|
NoIndentStyle = &Style{
|
||||||
|
SortDirectives: false,
|
||||||
|
StartIndent: 0,
|
||||||
|
Indent: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
//IndentedStyle default style
|
||||||
|
IndentedStyle = &Style{
|
||||||
|
SortDirectives: false,
|
||||||
|
StartIndent: 0,
|
||||||
|
Indent: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
//NoIndentSortedStyle default style
|
||||||
|
NoIndentSortedStyle = &Style{
|
||||||
|
SortDirectives: true,
|
||||||
|
StartIndent: 0,
|
||||||
|
Indent: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
//NoIndentSortedSpaceStyle default style
|
||||||
|
NoIndentSortedSpaceStyle = &Style{
|
||||||
|
SortDirectives: true,
|
||||||
|
SpaceBeforeBlocks: true,
|
||||||
|
StartIndent: 0,
|
||||||
|
Indent: 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type Style struct {
|
||||||
|
SortDirectives bool
|
||||||
|
SpaceBeforeBlocks bool
|
||||||
|
StartIndent int
|
||||||
|
Indent int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStyle() *Style {
|
||||||
|
style := &Style{
|
||||||
|
SortDirectives: false,
|
||||||
|
StartIndent: 0,
|
||||||
|
Indent: 4,
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Style) Iterate() *Style {
|
||||||
|
newStyle := &Style{
|
||||||
|
SortDirectives: s.SortDirectives,
|
||||||
|
SpaceBeforeBlocks: s.SpaceBeforeBlocks,
|
||||||
|
StartIndent: s.StartIndent + s.Indent,
|
||||||
|
Indent: s.Indent,
|
||||||
|
}
|
||||||
|
return newStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
func DumpDirective(d components.IDirective, style *Style) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
if style.SpaceBeforeBlocks && d.GetBlock() != nil {
|
||||||
|
buf.WriteString("\n")
|
||||||
|
}
|
||||||
|
buf.WriteString(fmt.Sprintf("%s%s", strings.Repeat(" ", style.StartIndent), d.GetName()))
|
||||||
|
if len(d.GetParameters()) > 0 {
|
||||||
|
buf.WriteString(fmt.Sprintf(" %s", strings.Join(d.GetParameters(), " ")))
|
||||||
|
}
|
||||||
|
if d.GetBlock() == nil {
|
||||||
|
if d.GetName() != "" {
|
||||||
|
buf.WriteRune(';')
|
||||||
|
buf.WriteString(" ")
|
||||||
|
}
|
||||||
|
if d.GetComment() != "" {
|
||||||
|
buf.WriteString(d.GetComment())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf.WriteString(" {")
|
||||||
|
if d.GetComment() != "" {
|
||||||
|
buf.WriteString(" ")
|
||||||
|
buf.WriteString(d.GetComment())
|
||||||
|
}
|
||||||
|
buf.WriteString("\n")
|
||||||
|
buf.WriteString(DumpBlock(d.GetBlock(), style.Iterate()))
|
||||||
|
buf.WriteString(fmt.Sprintf("\n%s}", strings.Repeat(" ", style.StartIndent)))
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DumpBlock(b components.IBlock, style *Style) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
directives := b.GetDirectives()
|
||||||
|
if style.SortDirectives {
|
||||||
|
sort.SliceStable(directives, func(i, j int) bool {
|
||||||
|
return directives[i].GetName() < directives[j].GetName()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, directive := range directives {
|
||||||
|
buf.WriteString(DumpDirective(directive, style))
|
||||||
|
if i != len(directives)-1 {
|
||||||
|
buf.WriteString("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DumpConfig(c *components.Config, style *Style) string {
|
||||||
|
return DumpBlock(c.Block, style)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteConfig(c *components.Config, style *Style) error {
|
||||||
|
dir, _ := filepath.Split(c.FilePath)
|
||||||
|
err := os.MkdirAll(dir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(c.FilePath, []byte(DumpConfig(c, style)), 0644)
|
||||||
|
}
|
14
backend/utils/nginx/nginx.go
Normal file
14
backend/utils/nginx/nginx.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package nginx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/nginx/components"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/nginx/parser"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetConfig(path string) (*components.Config, error) {
|
||||||
|
p, err := parser.NewParser(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p.Parse(), nil
|
||||||
|
}
|
82
backend/utils/nginx/parser/flag/flag.go
Normal file
82
backend/utils/nginx/parser/flag/flag.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package flag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Type int
|
||||||
|
|
||||||
|
const (
|
||||||
|
EOF Type = iota
|
||||||
|
Eol
|
||||||
|
Keyword
|
||||||
|
QuotedString
|
||||||
|
Variable
|
||||||
|
BlockStart
|
||||||
|
BlockEnd
|
||||||
|
Semicolon
|
||||||
|
Comment
|
||||||
|
Illegal
|
||||||
|
Regex
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
FlagName = map[Type]string{
|
||||||
|
QuotedString: "QuotedString",
|
||||||
|
EOF: "Eof",
|
||||||
|
Keyword: "Keyword",
|
||||||
|
Variable: "Variable",
|
||||||
|
BlockStart: "BlockStart",
|
||||||
|
BlockEnd: "BlockEnd",
|
||||||
|
Semicolon: "Semicolon",
|
||||||
|
Comment: "Comment",
|
||||||
|
Illegal: "Illegal",
|
||||||
|
Regex: "Regex",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (tt Type) String() string {
|
||||||
|
return FlagName[tt]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Flag struct {
|
||||||
|
Type Type
|
||||||
|
Literal string
|
||||||
|
Line int
|
||||||
|
Column int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Flag) String() string {
|
||||||
|
return fmt.Sprintf("{Type:%s,Literal:\"%s\",Line:%d,Column:%d}", t.Type, t.Literal, t.Line, t.Column)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Flag) Lit(literal string) Flag {
|
||||||
|
t.Literal = literal
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Flag) EqualTo(t2 Flag) bool {
|
||||||
|
return t.Type == t2.Type && t.Literal == t2.Literal
|
||||||
|
}
|
||||||
|
|
||||||
|
type Flags []Flag
|
||||||
|
|
||||||
|
func (fs Flags) EqualTo(flags Flags) bool {
|
||||||
|
if len(fs) != len(flags) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, t := range fs {
|
||||||
|
if !t.EqualTo(flags[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Flag) Is(typ Type) bool {
|
||||||
|
return t.Type == typ
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Flag) IsParameterEligible() bool {
|
||||||
|
return t.Is(Keyword) || t.Is(QuotedString) || t.Is(Variable) || t.Is(Regex)
|
||||||
|
}
|
209
backend/utils/nginx/parser/lexer.go
Normal file
209
backend/utils/nginx/parser/lexer.go
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/nginx/parser/flag"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type lexer struct {
|
||||||
|
reader *bufio.Reader
|
||||||
|
file string
|
||||||
|
line int
|
||||||
|
column int
|
||||||
|
Latest flag.Flag
|
||||||
|
}
|
||||||
|
|
||||||
|
func lex(content string) *lexer {
|
||||||
|
return newLexer(bytes.NewBuffer([]byte(content)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLexer(r io.Reader) *lexer {
|
||||||
|
return &lexer{
|
||||||
|
line: 1,
|
||||||
|
reader: bufio.NewReader(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) scan() flag.Flag {
|
||||||
|
s.Latest = s.getNextFlag()
|
||||||
|
return s.Latest
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (s *lexer) all() flag.Flags {
|
||||||
|
// tokens := make([]flag.Flag, 0)
|
||||||
|
// for {
|
||||||
|
// v := s.scan()
|
||||||
|
// if v.Type == flag.EOF || v.Type == -1 {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// tokens = append(tokens, v)
|
||||||
|
// }
|
||||||
|
// return tokens
|
||||||
|
//}
|
||||||
|
|
||||||
|
func (s *lexer) getNextFlag() flag.Flag {
|
||||||
|
retoFlag:
|
||||||
|
ch := s.peek()
|
||||||
|
switch {
|
||||||
|
case isSpace(ch):
|
||||||
|
s.skipWhitespace()
|
||||||
|
goto retoFlag
|
||||||
|
case isEOF(ch):
|
||||||
|
return s.NewToken(flag.EOF).Lit(string(s.read()))
|
||||||
|
case ch == ';':
|
||||||
|
return s.NewToken(flag.Semicolon).Lit(string(s.read()))
|
||||||
|
case ch == '{':
|
||||||
|
return s.NewToken(flag.BlockStart).Lit(string(s.read()))
|
||||||
|
case ch == '}':
|
||||||
|
return s.NewToken(flag.BlockEnd).Lit(string(s.read()))
|
||||||
|
case ch == '#':
|
||||||
|
return s.scanComment()
|
||||||
|
case ch == '$':
|
||||||
|
return s.scanVariable()
|
||||||
|
case isQuote(ch):
|
||||||
|
return s.scanQuotedString(ch)
|
||||||
|
default:
|
||||||
|
return s.scanKeyword()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) peek() rune {
|
||||||
|
r, _, _ := s.reader.ReadRune()
|
||||||
|
_ = s.reader.UnreadRune()
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
type runeCheck func(rune) bool
|
||||||
|
|
||||||
|
func (s *lexer) readUntil(until runeCheck) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteRune(s.read())
|
||||||
|
|
||||||
|
for {
|
||||||
|
if ch := s.peek(); isEOF(ch) {
|
||||||
|
break
|
||||||
|
} else if until(ch) {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
buf.WriteRune(s.read())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) NewToken(tokenType flag.Type) flag.Flag {
|
||||||
|
return flag.Flag{
|
||||||
|
Type: tokenType,
|
||||||
|
Line: s.line,
|
||||||
|
Column: s.column,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) readWhile(while runeCheck) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteRune(s.read())
|
||||||
|
|
||||||
|
for {
|
||||||
|
if ch := s.peek(); while(ch) {
|
||||||
|
buf.WriteRune(s.read())
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) skipWhitespace() {
|
||||||
|
s.readWhile(isSpace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) scanComment() flag.Flag {
|
||||||
|
return s.NewToken(flag.Comment).Lit(s.readUntil(isEndOfLine))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) scanQuotedString(delimiter rune) flag.Flag {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
tok := s.NewToken(flag.QuotedString)
|
||||||
|
buf.WriteRune(s.read()) //consume delimiter
|
||||||
|
for {
|
||||||
|
ch := s.read()
|
||||||
|
|
||||||
|
if ch == rune(flag.EOF) {
|
||||||
|
panic("unexpected end of file while scanning a string, maybe an unclosed quote?")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch == '\\' {
|
||||||
|
if needsEscape(s.peek(), delimiter) {
|
||||||
|
switch s.read() {
|
||||||
|
case 'n':
|
||||||
|
buf.WriteRune('\n')
|
||||||
|
case 'r':
|
||||||
|
buf.WriteRune('\r')
|
||||||
|
case 't':
|
||||||
|
buf.WriteRune('\t')
|
||||||
|
case '\\':
|
||||||
|
buf.WriteRune('\\')
|
||||||
|
case delimiter:
|
||||||
|
buf.WriteRune(delimiter)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteRune(ch)
|
||||||
|
if ch == delimiter {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tok.Lit(buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) scanKeyword() flag.Flag {
|
||||||
|
return s.NewToken(flag.Keyword).Lit(s.readUntil(isKeywordTerminator))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) scanVariable() flag.Flag {
|
||||||
|
return s.NewToken(flag.Variable).Lit(s.readUntil(isKeywordTerminator))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lexer) read() rune {
|
||||||
|
ch, _, err := s.reader.ReadRune()
|
||||||
|
if err != nil {
|
||||||
|
return rune(flag.EOF)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch == '\n' {
|
||||||
|
s.column = 1
|
||||||
|
s.line++
|
||||||
|
} else {
|
||||||
|
s.column++
|
||||||
|
}
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func isQuote(ch rune) bool {
|
||||||
|
return ch == '"' || ch == '\'' || ch == '`'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isKeywordTerminator(ch rune) bool {
|
||||||
|
return isSpace(ch) || isEndOfLine(ch) || ch == '{' || ch == ';'
|
||||||
|
}
|
||||||
|
|
||||||
|
func needsEscape(ch, delimiter rune) bool {
|
||||||
|
return ch == delimiter || ch == 'n' || ch == 't' || ch == '\\' || ch == 'r'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSpace(ch rune) bool {
|
||||||
|
return ch == ' ' || ch == '\t' || isEndOfLine(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEOF(ch rune) bool {
|
||||||
|
return ch == rune(flag.EOF)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEndOfLine(ch rune) bool {
|
||||||
|
return ch == '\r' || ch == '\n'
|
||||||
|
}
|
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)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user