tokenize.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package nginx
  2. import (
  3. "bufio"
  4. "regexp"
  5. "strings"
  6. "unicode"
  7. )
  8. func (c *NgxConfig) parseServer(scanner *bufio.Scanner) {
  9. server := NewNgxServer()
  10. for scanner.Scan() {
  11. d := parseDirective(scanner)
  12. switch d.Directive {
  13. case Location:
  14. server.parseLocation(d.Params)
  15. case CommentStart:
  16. server.commentQueue.Enqueue(d.Params)
  17. default:
  18. server.parseDirective(d)
  19. }
  20. }
  21. // Attach the rest of the comments to the last location
  22. if len(server.Locations) > 0 {
  23. server.Locations[len(server.Locations)-1].Comments += server.commentQueue.DequeueAllComments()
  24. }
  25. // Attach comments which are over the current server
  26. server.Comments = c.commentQueue.DequeueAllComments()
  27. c.Servers = append(c.Servers, server)
  28. }
  29. func (c *NgxConfig) parseUpstream(scanner *bufio.Scanner) {
  30. upstream := &NgxUpstream{}
  31. for scanner.Scan() {
  32. d := NgxDirective{}
  33. text := strings.TrimSpace(scanner.Text())
  34. // escape empty line or comment line
  35. if len(text) < 1 || text[0] == '#' {
  36. return
  37. }
  38. sep := len(text) - 1
  39. for k, v := range text {
  40. if unicode.IsSpace(v) {
  41. sep = k
  42. break
  43. }
  44. }
  45. d.Directive = text[0:sep]
  46. d.Params = strings.Trim(text[sep:], ";")
  47. if d.Directive == Server {
  48. upstream.Directives = append(upstream.Directives, &d)
  49. } else if upstream.Name == "" {
  50. upstream.Name = d.Directive
  51. }
  52. }
  53. // attach comments which are over the current upstream
  54. upstream.Comments = c.commentQueue.DequeueAllComments()
  55. c.Upstreams = append(c.Upstreams, upstream)
  56. }
  57. func (s *NgxServer) parseDirective(d NgxDirective) {
  58. orig := d.Orig()
  59. // handle inline comments
  60. str, comments, _ := strings.Cut(orig, "#")
  61. if d.Directive == If {
  62. d.Params = "if " + d.Params
  63. d.Params = fmtCode(d.Params)
  64. s.Directives = append(s.Directives, &d)
  65. return
  66. }
  67. regExp := regexp.MustCompile("(\\S+?)\\s+?{?(.+)[;|}]")
  68. matchSlice := regExp.FindAllStringSubmatch(str, -1)
  69. for k, v := range matchSlice {
  70. // [[gzip_min_length 256; gzip_min_length 256] [gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth] [gzip on; gzip on] [gzip_vary on; gzip_vary on] [location /x/ {} location /x/ {] [gzip_comp_level 4; gzip_comp_level 4]]
  71. if len(v) > 0 {
  72. scanner := bufio.NewScanner(strings.NewReader(v[0]))
  73. if scanner.Scan() {
  74. d = parseDirective(scanner)
  75. // inline location
  76. if d.Directive == Location {
  77. s.parseLocation(d.Orig())
  78. } else {
  79. if k == 0 {
  80. d.Comments = s.commentQueue.DequeueAllComments()
  81. } else if k == len(matchSlice)-1 {
  82. d.Comments = comments
  83. }
  84. // trim right ';'
  85. d.TrimParams()
  86. // map[directive]=>[]Params
  87. s.Directives = append(s.Directives, &d)
  88. }
  89. }
  90. }
  91. }
  92. }
  93. func (s *NgxServer) parseLocation(str string) {
  94. path, content, _ := strings.Cut(str, "{")
  95. path = strings.TrimSpace(path)
  96. content = strings.TrimSpace(content)
  97. content = strings.Trim(content, "}")
  98. content = fmtCode(content)
  99. location := &NgxLocation{
  100. Path: path,
  101. Content: content,
  102. }
  103. location.Comments = s.commentQueue.DequeueAllComments()
  104. s.Locations = append(s.Locations, location)
  105. }